MPAndroidChart之自定义高亮区域

MPAndroidChart 是Android开源库中最为著名的一个图标库,功能齐全,拓展性强,在github上start量超过25K,fork量超过6K。
由于MPAndroidChart开源Demo中的原型过于不太吸引广大用户的眼球,往往在开发过程中需要自定义一些效果,例如现在要讲的高亮效果,以Demo中的BarChart高亮效果为例,只覆盖在Bar所绘制的区域,如果想要改变这个区域,那么我们需要自定义高亮覆盖的区域。
先来看看高亮效果是怎么绘制出来的:
MPAndroidChart Api中暴露了一个接口用来设置高亮效果的开关:

chart.getData().setHighlightEnabled(boolean isEnable)

从getData开始跟踪代码到ChartData类,这个类里面有方法:

public void setHighlightEnabled(boolean enabled) {
        for (IDataSet set : mDataSets) {
            set.setHighlightEnabled(enabled);
        }
    }

从这段代码可以看到,绘制高亮的控制权掌控在IDataSet里面,也就是我们设置进图表中的数据里面。那么我们看看从数据对象中看看,找到BarChart这个类适配的对象BarData,进到这个类中,貌似并没有发现什么有价值的东西,那么我们再从BarChart中看看,在BarChart中有几个貌似跟Highlight有关的东西:

protected boolean mHighlightFullBarEnabled = false;

/**
     * Set this to true to make the highlight operation full-bar oriented, false to make it highlight single values (relevant
     * only for stacked). If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry
     * was tapped.
     * Default: false
     *
     * @param enabled
     */
    public void setHighlightFullBarEnabled(boolean enabled) {
        mHighlightFullBarEnabled = enabled;
    }
/**
     * Set this to true to make the highlight operation full-bar oriented, false to make it highlight single values (relevant
     * only for stacked). If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry
     * was tapped.
     * Default: false
     *
     * @param enabled
     */
    public void setHighlightFullBarEnabled(boolean enabled) {
        mHighlightFullBarEnabled = enabled;
    }

    /**
     * @return true the highlight operation is be full-bar oriented, false if single-value
     */
    @Override
    public boolean isHighlightFullBarEnabled() {
        return mHighlightFullBarEnabled;
    }

然而这些对我们来说并没什么用,进入父类看看也是如此,那么进入顶级类中看看,我们会在Chart中发现一个东西:

protected IHighlighter mHighlighter;

这个是将高亮对象封装到图表适配的数据对象中的:

/**
     * An array of `Highlight` objects corresponding to the selected xValue and dataSetIndex.
     *
     * @param set
     * @param dataSetIndex
     * @param xVal
     * @param rounding
     * @return
     */
    protected List<Highlight> buildHighlights(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) {

        ArrayList<Highlight> highlights = new ArrayList<>();

        //noinspection unchecked
        List<Entry> entries = set.getEntriesForXValue(xVal);
        if (entries.size() == 0) {
            // Try to find closest x-value and take all entries for that x-value
            final Entry closest = set.getEntryForXValue(xVal, Float.NaN, rounding);
            if (closest != null)
            {
                //noinspection unchecked
                entries = set.getEntriesForXValue(closest.getX());
            }
        }

        if (entries.size() == 0)
            return highlights;

        for (Entry e : entries) {
            MPPointD pixels = mChart.getTransformer(
                    set.getAxisDependency()).getPixelForValues(e.getX(), e.getY());

            highlights.add(new Highlight(
                    e.getX(), e.getY(),
                    (float) pixels.x, (float) pixels.y,
                    dataSetIndex, set.getAxisDependency()));
        }

        return highlights;
    }

好像除了这些也没什么了。
难道没办法自定义自己喜欢的样式了吗?
当然不是,图表绘制时,还有一个渲染器,将数据渲染到图表中,找到相应的渲染器看看。
果然没让我们失望,在BarChartRenderer这个类中找到一个方法:

@Override
    public void drawHighlighted(Canvas c, Highlight[] indices) {

        //获取数据对象
        BarData barData = mChart.getBarData();

        for (Highlight high : indices) {
            //遍历高亮对象,设置高亮属性
            IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());

            if (set == null || !set.isHighlightEnabled())
                continue;

            BarEntry e = set.getEntryForXValue(high.getX(), high.getY());

            if (!isInBoundsX(e, set))
                continue;

            Transformer trans = mChart.getTransformer(set.getAxisDependency());

            mHighlightPaint.setColor(set.getHighLightColor());
            mHighlightPaint.setAlpha(set.getHighLightAlpha());

            boolean isStack = (high.getStackIndex() >= 0  && e.isStacked()) ? true : false;

            final float y1;
            final float y2;

            if (isStack) {

                if(mChart.isHighlightFullBarEnabled()) {

                    y1 = e.getPositiveSum();
                    y2 = -e.getNegativeSum();

                } else {

                    Range range = e.getRanges()[high.getStackIndex()];

                    y1 = range.from;
                    y2 = range.to;
                }

            } else {
                y1 = e.getY();
                y2 = 0.f;
            }
            //设置高亮区域
            prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
            //绘制高亮区域
            setHighlightDrawPos(high, mBarRect);

            c.drawRect(mBarRect, mHighlightPaint);
        }
    }
protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) {

        float left = x - barWidthHalf;
        float right = x + barWidthHalf;
        float top = y1;
        float bottom = y2;

        mBarRect.set(left, top, right, bottom);

        trans.rectToPixelPhase(mBarRect, mAnimator.getPhaseY());
    }
/**
     * Sets the drawing position of the highlight object based on the riven bar-rect.
     * @param high
     */
    protected void setHighlightDrawPos(Highlight high, RectF bar) {
        high.setDraw(bar.centerX(), bar.top);
    }

这个方法专门用户绘制高亮效果,改变mBarRect的区域就可以改变高亮区域了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值