1. 程式人生 > >一步一步教你寫股票走勢圖——K線圖二(圖表聯動)

一步一步教你寫股票走勢圖——K線圖二(圖表聯動)

K線圖越做發現坑越多,跟之前做的分時圖完全不是一個重量級的啊,分時圖不需要滾動,少走了很多彎路,K線圖因為滾動的問題,會導致很多其他問題,比如:

  • 多個圖表之間滾動時怎麼聯動
  • 高亮滾動衝突
  • 放縮聯動

表對齊

下面我們就開始介紹本節的內容,要想實現圖表之間的聯動,那麼必須得保證圖表是對齊的,聯動起來效果才能保持一致,圖表對齊功能,我們在分時圖部分已經講解,程式碼一致,還是簡單貼下程式碼:

 /*設定量表對齊*/
    private void setOffset() {
        float lineLeft = combinedchart.getViewPortHandler
().offsetLeft(); float barLeft = barChart.getViewPortHandler().offsetLeft(); float lineRight = combinedchart.getViewPortHandler().offsetRight(); float barRight = barChart.getViewPortHandler().offsetRight(); float offsetLeft, offsetRight; /*注:setExtraLeft...函式是針對圖表相對位置計算,比如A表offLeftA=20dp,B表offLeftB=30dp,則A.setExtraLeftOffset(10),並不是30,還有注意單位轉換*/
if (barLeft < lineLeft) { offsetLeft = Utils.convertPixelsToDp(lineLeft - barLeft); barChart.setExtraLeftOffset(offsetLeft); } else { offsetLeft = Utils.convertPixelsToDp(barLeft-lineLeft); combinedchart.setExtraLeftOffset(offsetLeft);
} /*注:setExtraRight...函式是針對圖表絕對位置計算,比如A表offRightA=20dp,B表offRightB=30dp,則A.setExtraLeftOffset(30),並不是10,還有注意單位轉換*/ if (barRight < lineRight) { offsetRight = Utils.convertPixelsToDp(lineRight); barChart.setExtraRightOffset(offsetRight); } else { offsetRight = Utils.convertPixelsToDp(barRight); combinedchart.setExtraRightOffset(offsetRight); } }

表聯動

表的聯動這裡包括滾動聯動、放縮聯動,具體操作效果圖還是參照自選股:

這裡寫圖片描述

博主在stackover上發現了有人曾提過類似問題:

這裡寫圖片描述

幸運的是有人也回答了這個問題,具體請點選上面的連結檢視。

public class CoupleChartGestureListener implements OnChartGestureListener {

    private static final String TAG = CoupleChartGestureListener.class.getSimpleName();

    private Chart srcChart;
    private Chart[] dstCharts;

    public CoupleChartGestureListener(Chart srcChart, Chart[] dstCharts) {
        this.srcChart = srcChart;
        this.dstCharts = dstCharts;
    }

  ……

    @Override
    public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
//        Log.d(TAG, "onChartScale " + scaleX + "/" + scaleY + " X=" + me.getX() + "Y=" + me.getY());
        syncCharts();
    }

    @Override
    public void onChartTranslate(MotionEvent me, float dX, float dY) {
//        Log.d(TAG, "onChartTranslate " + dX + "/" + dY + " X=" + me.getX() + "Y=" + me.getY());
        syncCharts();
    }

    public void syncCharts() {
        Matrix srcMatrix;
        float[] srcVals = new float[9];
        Matrix dstMatrix;
        float[] dstVals = new float[9];

        // get src chart translation matrix:
        srcMatrix = srcChart.getViewPortHandler().getMatrixTouch();
        srcMatrix.getValues(srcVals);

        // apply X axis scaling and position to dst charts:
        for (Chart dstChart : dstCharts) {
            if (dstChart.getVisibility() == View.VISIBLE) {
                dstMatrix = dstChart.getViewPortHandler().getMatrixTouch();
                dstMatrix.getValues(dstVals);

                dstVals[Matrix.MSCALE_X] = srcVals[Matrix.MSCALE_X];
                dstVals[Matrix.MSKEW_X] = srcVals[Matrix.MSKEW_X];
                dstVals[Matrix.MTRANS_X] = srcVals[Matrix.MTRANS_X];
                dstVals[Matrix.MSKEW_Y] = srcVals[Matrix.MSKEW_Y];
                dstVals[Matrix.MSCALE_Y] = srcVals[Matrix.MSCALE_Y];
                dstVals[Matrix.MTRANS_Y] = srcVals[Matrix.MTRANS_Y];
                dstVals[Matrix.MPERSP_0] = srcVals[Matrix.MPERSP_0];
                dstVals[Matrix.MPERSP_1] = srcVals[Matrix.MPERSP_1];
                dstVals[Matrix.MPERSP_2] = srcVals[Matrix.MPERSP_2];

                dstMatrix.setValues(dstVals);
                dstChart.getViewPortHandler().refresh(dstMatrix, dstChart, true);
            }
        }
    }
}

於是抱著試試看的態度試了一下,卻發現問題了,請看:

這裡寫圖片描述

我們發現對同一個表進行滾動時,沒有任何問題,但是在一個表滾動ing,再對另一個表進行滾動,就會出現衝突了,剛開始我以為是我的問題,後來發現同樣用這端程式碼的其他人,也出現這個問題,不知道哪位大神能給出解決方法,請大神留下您那寶貴的意見。
考慮到這個衝突問題比較嚴重,稍微滑動就會出現這種情況,所以機智的樓主想出了另一招,加了兩行程式碼:

  combinedchart.setDragDecelerationEnabled(false);
  barChart.setDragDecelerationEnabled(false);

估計有人已經知道這兩句程式碼的意思了,作用就是手指滑動螢幕,離開後不會有慣性滾動,這雖然解決了上面的bug,但是在體驗上卻大不如前,不過只好先這麼著了,看效果圖:
這裡寫圖片描述

滾動聯動已經完成,還有放縮聯動呢,我們看下效果圖:

這裡寫圖片描述

ok,木有問題,圖表聯動部分到這裡結束,下面初步介紹一下高亮聯動,因為這裡涉及到手勢衝突問題,目前只實現了簡單的點選高亮聯動,具體的在滾動中然後使用高亮,我們日後再行補充,這裡邏輯和分時圖一樣,直接上程式碼:

 combinedchart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
                barChart.highlightValues(new Highlight[]{h});
               // combinedchart.setHighlightValue(h);
            }

            @Override
            public void onNothingSelected() {

            }
        });
        barChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
                combinedchart.highlightValues(new Highlight[]{h});

            }

            @Override
            public void onNothingSelected() {

            }
        });

這裡寫圖片描述

本期內容就講到這裡了,這只是個初版,以後還會改進,但是畢竟都是要經歷的砍,所以還是放出來了,以後慢慢會優化,有好的建議希望能聯絡我,將更好的東西開源出來!