Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> MPAndroidChart系列源碼解讀(五)

MPAndroidChart系列源碼解讀(五)

編輯:關於Android編程

本篇主要是LineChart實戰相關知識和簡單的源碼剖析,相關源碼沒有,自己動手實踐學習才是最有效的方法。


LineChart Simple

運行效果圖

\

個人感官覺得某些屬性設置後太難看了並沒有添加,so效果圖上沒有顯示,如果你想測試這些屬性自行參考下面的api介紹<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMyBpZD0="一些調用方法說明">一些調用方法說明

設置圖標數據內容視圖的背景顏色(默認RGB(240,240,240))

mChart.setDrawGridBackground(true);
mChart.setGridBackgroundColor(Color.RED);

關於圖表的描述文字,默認放在圖表右下角10個像素padding,也可以自己手動設置字體、文字大小、文字顯示位置等

mChart.setDescription("LineChart");
mChart.setDescriptionColor(Color.BLACK);
mChart.setDescriptionPosition(300 , 300);
mChart.setDescriptionTextSize(16);
mChart.setDescriptionTypeface(Typeface.DEFAULT_BOLD);
mChart.setNoDataTextDescription("LineChart no Data");

這裡特別提示Description繪制的setDescritionPosition方法的值,並不是設置的繪制文字起始位置,而是結束位置。參考下面

\

Touch觸摸滑動相關,如果禁用了MaskView以及點擊縮放滑動都不起效果了(默認沒有禁用)

 mChart.setTouchEnabled(false);

關於圖表更多關於縮放相關的參考下面API

  //是否允許拖拽圖表
  mChart.setDragEnabled(true);
  //是否允許縮放圖表
  mChart.setScaleEnabled(true);
  //是否允許縮放X軸比例
  mChart.setScaleXEnabled(true);
  //是否允許縮放Y軸比例
  mChart.setScaleYEnabled(true);

  //setScaleEnabled方法就是禁用x、y兩個軸都不能縮放如果在這個方法調用後再單獨調用setScaleXEnable、setScaleYEnable

  //就沒有了之前x、y軸都不能縮放的效果,單擊照樣能縮放。

setPinchZoom(true) 時,x y軸同時縮放坐標尺比例根據手勢縮放,false測更具手勢方向和是否禁止縮放判斷縮放各自對應軸的刻度值比例,下圖是true時的效果概念圖

\

設置整個圖表的背景色

 mChart.setBackgroundColor(Color.GRAY);

\

觸摸圖標會有個高亮的十字虛線出現和MaskView彈出,這玩意在之前blog就有提到過,這裡不解釋了,調用參考官方Simple

 MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view);
 mChart.setMarkerView(mv);

圖表上添加x、y軸的軸線LimitLine,參考下面流程(LimitLine的屬性set方法自己參考API即可)

  LimitLine limitLineX = new LimitLine(20,"");
  LimitLine limitLineY = new LimitLine(50,"");

  // .......config limitLine x y...............    

  XAxis xAxis = lineChart.getXAxis();
  YAxis yAxis = lineChart.getAxisLeft();

  xAxis.addLimitLine(limitLineX);
  yAxis.addLimitLine(limitLineY);

補充說明(Lable對齊位置參考LimitLabelPosition枚舉,關於軸線相關API請自行參考源碼,之前blog也已有過理解,不再敘述):

\

最後一步就是裝數據設置Data,這裡得注意一點,不同版本會有所變化,這裡提供的是最新版本的方式setValues,MaskView之前拷貝以前下載的Simple裡面的對應的有些方法不支持也需要自行參考自己版本對應類提供的方法

 public void setData(ArrayList valuesY){
        ArrayList values = new ArrayList();
        for (int i = 0; i < valuesY.size(); i++) {
            values.add(new Entry(i, valuesY.get(i)));
        }
        LineDataSet set1;
        if (lineChart.getData() != null &&
                lineChart.getData().getDataSetCount() > 0) {
            set1 = (LineDataSet) lineChart.getData().getDataSetByIndex(0);
            set1.setValues(values);
            lineChart.getData().notifyDataChanged();
            lineChart.notifyDataSetChanged();
        } else {
            set1 = new LineDataSet(values, "LimitLine 1");
            set1.enableDashedLine(10f, 5f, 0f);
            set1.enableDashedHighlightLine(10f, 5f, 0f);
           //TODO 省略config set1自行參考源代碼裡面的Simple,見名知其意,不過多解釋
            ArrayList dataSets = new ArrayList();
            dataSets.add(set1);
            LineData data = new LineData(dataSets);
            lineChart.setData(data);
        }
    }

這裡再提供一些不常用的API方法

 //設置Chart縮放的最大限度值
 mChart.getViewPortHandler().setMaximumScaleY(2f);
 mChart.getViewPortHandler().setMaximumScaleX(2f);

//移動圖表位置中心
mChart.centerViewTo(200, 500, YAxis.AxisDependency.LEFT);

//圖例樣式配置
Legend l = mChart.getLegend();
l.setForm(LegendForm.SQUARE);//正方形、圓形、線條
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);//位置
l.setPosition(Legend.LegendPosition.RIGHT_OF_CHART);//位於Chart右側

//具體使用參考枚舉類相關源碼

圖例樣式類似下圖效果

\


LineChart源碼分析

LineChart簡化版UML

\

LIneChart核心知識點

ChartInterface 該接口提供chart視圖已知的尺寸、界限、范圍等,在之前blog已有提到這裡不過多解釋。
BarLineScatterCandleBubbleDataProvider、LineDataProvider從繼承來看都是相關屬性的擴展,之前同樣blog有提到,具體實現在Chart相關類裡面。

LineChart Draw方法相關的無非就是drawText、drawLine這些相關方法,這裡就不提了,這裡呢簡單說一下核心工作流程:

onTouch方法通過代理的方式處理Touch事件

public abstract class BarLineChartBase>>
        extends Chart implements BarLineScatterCandleBubbleDataProvider {

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        if (mChartTouchListener == null || mData == null)
            return false;

        // check if touch gestures are enabled
        if (!mTouchEnabled)
            return false;
        else
            return mChartTouchListener.onTouch(this, event);
    }


}

touch移動需要computeScroll,這個方法很久以前blog了解過了不累贅敘述具體用途

  @Override
    public void computeScroll() {

        if (mChartTouchListener instanceof BarLineChartTouchListener)
            ((BarLineChartTouchListener) mChartTouchListener).computeScroll();
    }

而ChartTouchListener僅僅是一個抽象類,很多方法都沒有具體實現,具體實現在請移到這裡BarLineChartTouchListener。

\

這裡麼的拖拽和縮放執行通過一些列的計算判斷條件執行Matrix的postTranslate和postScale方法達到效果,當然這裡面涉及到的還有模式的修改、移動的處理、高亮顯示等相關事件。

至於MaskView是在什麼地方被draw到圖表中的呢?接著往下看..
在BarLineChartTouchListener處理touch事件引起的重繪回回到父類BarLineChartBase的onDraw方法裡面,調用到父類Chart的 drawMarkers(canvas);方法,下面是具體方法塊(MaskVew的繪制的和取消繪制不用多說了吧)

protected void drawMarkers(Canvas canvas) {

        // if there is no marker view or drawing marker is disabled
        if (mMarkerView == null || !mDrawMarkerViews || !valuesToHighlight())
            return;

        for (int i = 0; i < mIndicesToHighlight.length; i++) {

            Highlight highlight = mIndicesToHighlight[i];
            int xIndex = highlight.getXIndex();
            int dataSetIndex = highlight.getDataSetIndex();

            float deltaX = mXAxis != null 
                ? mXAxis.mAxisRange
                : ((mData == null ? 0.f : mData.getXValCount()) - 1.f);

            if (xIndex <= deltaX && xIndex <= deltaX * mAnimator.getPhaseX()) {

                Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]);

                // make sure entry not null
                if (e == null || e.getXIndex() != mIndicesToHighlight[i].getXIndex())
                    continue;

                float[] pos = getMarkerPosition(e, highlight);

                // check bounds
                if (!mViewPortHandler.isInBounds(pos[0], pos[1]))
                    continue;

                // callbacks to update the content
                mMarkerView.refreshContent(e, highlight);

                // mMarkerView.measure(MeasureSpec.makeMeasureSpec(0,
                // MeasureSpec.UNSPECIFIED),
                // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                // mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(),
                // mMarkerView.getMeasuredHeight());
                // mMarkerView.draw(mDrawCanvas, pos[0], pos[1]);

                mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(),
                        mMarkerView.getMeasuredHeight());

                if (pos[1] - mMarkerView.getHeight() <= 0) {
                    float y = mMarkerView.getHeight() - pos[1];
                    mMarkerView.draw(canvas, pos[0], pos[1] + y);
                } else {
                    mMarkerView.draw(canvas, pos[0], pos[1]);
                }
            }
        }
    }

在官方simple的Activity有實現接口OnChartGestureListener,在onChartGestureEnd方法有執行如下操作

@Override
    public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
        if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP)
            lineChart.highlightValues(null);
    }

如果不是輕敲的觸摸了屏幕,就取消MaskView的繪制。

由於Touch的具體實現個人不想再細致分析,感覺太累就點到為止,了解大致工作流程就好。

小結

學到兩點知識:

1.接口的設計

2.MaskView draw到畫布

以上內容你若覺得可以歡迎點贊,記得點贊哦!本篇若有理解錯誤之處還望指出,以免誤人子弟,有問題在個人知識范圍內歡迎交流。逗逼的學習之路途漫漫,還好最近工作不忙,明天繼續..

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved