关于MPAndroidChart记录几个问题

 

近期需要有一个曲线图表的需求,最前的图表功能的自定义View写,感觉性能上不过关,所以这次使用那个*炸天的Android图表宇宙无敌开源库MPAndroidChart,凭着中学生英语的水平大致看了下文档。

关于MPAndroidChart记录几个问题_第1张图片

还是自己好好撸源码吧,MPAndroidChart其实已经封装的很好了,API也很易懂,但是有一些细节需要改动源码,希望可以帮到大家,先看看MPAndroidChart的包。

关于MPAndroidChart记录几个问题_第2张图片

只选标了几个,其实包名已经超清楚了,其实Utils里就有很多干货,计算Text的高度等方法很好用,当然常做自定义控件的朋友应该都很熟悉了。

由于直接用的公司代码,所以没有整段的贴。。。。好了,开始撸代码。

关于MPAndroidChart记录几个问题_第3张图片

很简单一个demo,这里可能有两个问题,我在看相关文档的时候看见过有一些同学问过一个问题,Line模式的图怎么让它一出来就呈现缩放的状态,而且要支持手势。这里其实是用的ViewPortHandler类做的处理,这个类作者声明必须要仔细阅读文档之后再使用,否则容易出现问题,真是吓屎了好吧。ViewPortHandler内部包含一个Matrix对象,拿这个Matrix就可以对Line做一些操作了。此处参考了gogooing的处理方式。

private void setHandler(CombinedChart combinedChart) {
        final ViewPortHandler viewPortHandlerBar = combinedChart.getViewPortHandler();
        viewPortHandlerBar.setMaximumScaleX(3);//最大缩放因子。
        Matrix touchmatrix = viewPortHandlerBar.getMatrixTouch();
        final float xscale = 3;
        touchmatrix.postScale(xscale, 1f);
}

这个方法在数据加载设置完之后调用,然后还需要一步操作,因为这个时候你会发现,你的线是从头开始的,一般初始显示都希望是显示最后一根。

setHandler(mChartPrice);
mChartPrice.moveViewToX(Data.size() - 1);

哈哈,最后移动一下就好啦。

另外一个问题是,最左边labels如果过长的话就会被挡住一半。

关于MPAndroidChart记录几个问题_第4张图片

其实源码是做过Label超出屏幕的处理,结果最后一个Label的判断一直没有走进去过,把i == mXAxis.mEntryCount - 1改为i == mXAxis.mEntryCount就可以了,这里不知道是不是有什么问题,总之哪个判断就是进不去。

/**
     * draws the x-labels on the specified y-position
     *
     * @param pos
     */
    protected void drawLabels(Canvas c, float pos, MPPointF anchor) {
        ........//省略N行代码
        for (int i = 0; i < positions.length; i += 2) {
            float x = positions[i];
            if (mViewPortHandler.isInBoundsX(x)) {
                String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis);
                //这个判断里是处理第一个和最后一个labels,当然也可以自己写。
                if (mXAxis.isAvoidFirstLastClippingEnabled()) {
                    // avoid clipping of the last
                    if (i == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) {
                        float width = Utils.calcTextWidth(mAxisLabelPaint, label);
                        if (width > mViewPortHandler.offsetRight() * 2
                                && x + width > mViewPortHandler.getChartWidth())
                            x -= width / 2;
                        // avoid clipping of the first
                    } else if (i == 0) {
                            //第一个点不做操作
//                        float width = Utils.calcTextWidth(mAxisLabelPaint, label);
//                        x += width / 2;
                    }
                }
                drawLabel(c, label, x, pos, anchor, labelRotationAngleDegrees);
            }
        }
    }

显示的问题解决了,还有是事件问题,MPAndroidChart提供的手势很多,但是Highlight的手势很单一,直接在Chart上滑动就可以触发Highlight显示,还有Chart缩放的时候好像是不能出现Highlight的,个人观察是这样,那就只能改源码了,我们希望可以长按显示Highlight,并且松开手Highlight消失。

这个库的包名都可以很好的帮助理解功能,关于绘制的类都在renderer包下面,关于手势很容易联想带listener,没错就是listener包下的BarLineChartTouchListener(折线图是这个)。onTouch方法简直不要太熟悉,手势操作就在这了,200行左右很少,逻辑也很清楚。我们在MotionEvent.ACTION_MOVE里面做改动。可以看到这个类里面还有一个onLongPress方法,这个是系统类GestureDetector内部类SimpleOnGestureListener的一个长按事件的回调方法。现在我们找一个标志位,来标记长按事件,事实上可以直接拿SimpleOnGestureListener里的mLastGesture来用。直接添加5-8行处的代码,这就解决了缩放状态下不能是使用Highlight的问题。然后抬手的时候就是在ACTION_CANCEL、ACTION_POINTER_UP、ACTION_POINTER_UP中加入mChart.highlightValue(null);mLastGesture=ChartGesture.NONE;两句代码,把标志位和Highlight复原即可。

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View v, MotionEvent event) {
            case MotionEvent.ACTION_MOVE:
                if (mLastGesture==ChartGesture.LONG_PRESS){
                    performHighlightDrag(event);
                    break;
                }
                if (mTouchMode == DRAG) {
                    mChart.disableScroll();
                    float x = mChart.isDragXEnabled() ? event.getX() - mTouchStartPoint.x : 0.f;
                    float y = mChart.isDragYEnabled() ? event.getY() - mTouchStartPoint.y : 0.f;
                    performDrag(event, x, y);
                } else if (mTouchMode == X_ZOOM || mTouchMode == Y_ZOOM || mTouchMode == PINCH_ZOOM) {
                    mChart.disableScroll();
                    if (mChart.isScaleXEnabled() || mChart.isScaleYEnabled())
                        performZoom(event);
                } else if (mTouchMode == NONE
                        && Math.abs(distance(event.getX(), mTouchStartPoint.x, event.getY(),
                        mTouchStartPoint.y)) > mDragTriggerDist) {
                    if (mChart.isDragEnabled()) {
                        boolean shouldPan = !mChart.isFullyZoomedOut() ||
                                !mChart.hasNoDragOffset();
                        if (shouldPan) {
                            float distanceX = Math.abs(event.getX() - mTouchStartPoint.x);
                            float distanceY = Math.abs(event.getY() - mTouchStartPoint.y);
                            // Disable dragging in a direction that's disallowed
                            if ((mChart.isDragXEnabled() || distanceY >= distanceX) &&
                                    (mChart.isDragYEnabled() || distanceY <= distanceX)) {
                                mLastGesture = ChartGesture.DRAG;
                                mTouchMode = DRAG;
                            }
                        } else {
                            if (mChart.isHighlightPerDragEnabled()) {
                                mLastGesture = ChartGesture.DRAG;
                                if (mChart.isHighlightPerDragEnabled())
                                    performHighlightDrag(event);
                            }
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                final VelocityTracker velocityTracker = mVelocityTracker;
                final int pointerId = event.getPointerId(0);
                velocityTracker.computeCurrentVelocity(1000, Utils.getMaximumFlingVelocity());
                final float velocityY = velocityTracker.getYVelocity(pointerId);
                final float velocityX = velocityTracker.getXVelocity(pointerId);
                if (Math.abs(velocityX) > Utils.getMinimumFlingVelocity() ||
                        Math.abs(velocityY) > Utils.getMinimumFlingVelocity()) {
                    if (mTouchMode == DRAG && mChart.isDragDecelerationEnabled()) {
                        stopDeceleration();
                        mDecelerationLastTime = AnimationUtils.currentAnimationTimeMillis();
                        mDecelerationCurrentPoint.x = event.getX();
                        mDecelerationCurrentPoint.y = event.getY();
                        mDecelerationVelocity.x = velocityX;
                        mDecelerationVelocity.y = velocityY;
                        Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by
                        // Google
                    }
                }
                if (mTouchMode == X_ZOOM ||
                        mTouchMode == Y_ZOOM ||
                        mTouchMode == PINCH_ZOOM ||
                        mTouchMode == POST_ZOOM) {

                    // Range might have changed, which means that Y-axis labels
                    // could have changed in size, affecting Y-axis size.
                    // So we need to recalculate offsets.
                    mChart.calculateOffsets();
                    mChart.postInvalidate();
                }
                mTouchMode = NONE;
                mChart.enableScroll();
                if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
                }
                endAction(event);
                break;
            case MotionEvent.ACTION_POINTER_UP:
                Utils.velocityTrackerPointerUpCleanUpIfNecessary(event, mVelocityTracker);
                mTouchMode = POST_ZOOM;
                break;
            case MotionEvent.ACTION_CANCEL:
                mTouchMode = NONE;
                endAction(event);
                break;
        }
        // perform the transformation, update the chart
        mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true);
        return true; // indicate event was handled
    }
@Override
    public void onLongPress(MotionEvent e) {
        mLastGesture = ChartGesture.LONG_PRESS;
        OnChartGestureListener l = mChart.getOnChartGestureListener();
        if (l != null) {
            l.onChartLongPressed(e);
        }
    }
先记录这几个问题- -。

 

你可能感兴趣的:(android)