MPAndroidChart的實現堆疊柱狀圖。 柱狀圖自己封裝,暴露設置數據的方法。可以直接放到自己代碼用

首先看一下效果圖,把2種數據,疊加展示。

下面我們來看一下代碼是如何實現的。

1.首先我把實現堆疊柱狀圖封裝了MyBarChart。下面直接上代碼。

代碼裏面直接把設置chart的一些屬性配置好了。對外暴露了一個設置數據的接口。使用的時候在直接調用

setBarDataSet() 方法,傳相應的參數設置數據。
public class MyBarChart extends BarChart{
    private ValueFormatter mXAxisFormatter;
    protected Typeface tfLight;
    private Context context;
    public MyBarChart(Context context) {
        super(context);
        tfLight = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf");
        this.context=context;
        initSetting();
    }

    public MyBarChart(Context context, AttributeSet attrs) {
        super(context, attrs);
        tfLight = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf");
        this.context=context;
        initSetting();
    }

    public MyBarChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        tfLight = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf");
        this.context=context;
        initSetting();
    }

    /**
     *
     */
    public  void initSetting() {
        setDrawBarShadow(false);//設置陰影
        setDrawValueAboveBar(true);//設置所有的數值在圖形的上面,而不是圖形上
        getDescription().setEnabled(false);//不描述
        // if more than 60 entries are displayed in the chart, no values will be
        // drawn     // 如果60多個條目顯示在圖表,drawn沒有值
        setMaxVisibleValueCount(60);

        // scaling can now only be done on x- and y-axis separately
        setPinchZoom(false);//設置true支持兩個指頭向X、Y軸的縮放,如果爲false,只能支持X或者Y軸的當方向縮放
        setDrawGridBackground(false);//設置背景是否網格顯示
        // chart.setDrawYLabels(false);
        // TODO 把這個設置爲false,禁用所有手勢和圖表上的觸摸,默認:true
//        setTouchEnabled(false);
        //設置是否可以縮放。false不能放大縮小。但是如果顯示不全可以左右滑動
        setScaleEnabled(false);
        // TODO 設置圖標拖動爲允許
//        chart.setDragEnabled(false);

        //TODO 這個控制橫座標的顯示內容
//        mXAxisFormatter = new StringDataAxisValueFormatter();

        XAxis xAxis = getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setTypeface(tfLight);
        xAxis.setDrawGridLines(false);
//        xAxis.setTextSize(9);
        xAxis.setGranularity(1f); // only intervals of 1 day
//        xAxis.setValueFormatter(mXAxisFormatter);
        xAxis.setLabelRotationAngle(-60);//設置x座標的文字傾斜。爲傾斜60°
//        xAxis.setAxisMinimum(0f);


        ValueFormatter custom = new MyValueFormatter("$");//這裏是y軸的顯示內容

        YAxis leftAxis = getAxisLeft();
        leftAxis.setTypeface(tfLight);
        leftAxis.setLabelCount(8, true);//這裏設置y軸座標數的個數。包含0點,後面設爲true,纔可固定左邊y軸有幾個座標值
//        leftAxis.setValueFormatter(custom);
        leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
        leftAxis.setSpaceTop(15f);
        leftAxis.setAxisMinimum(0f); //保證y軸從0開始 不然會上移一點 this replaces setStartAtZero(true)
//        leftAxis.setDrawGridLines(false);//去掉中間橫線
//有座標軸顯示內容
        YAxis rightAxis = getAxisRight();
        rightAxis.setEnabled(false);

        /** 圖例的屬性 */
        Legend l = getLegend();
        l.setEnabled(false);  //不顯示圖例 底部的什麼顏色代表什麼的說明
        //決定底部圖例的位置。
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
        l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        l.setDrawInside(false);
        l.setForm(Legend.LegendForm.SQUARE);
        l.setFormSize(9f);
        l.setTextSize(11f);
        l.setXEntrySpace(10f);

//        XYMarkerView mv = new XYMarkerView(context, mXAxisFormatter);
//        mv.setChartView(this); // For bounds control
//        setMarker(mv); // Set the marker to the chart

//        setExtraBottomOffset(20);
    }

    public void setBarDataSet(List<BarEntry> values, String label, String[] StackLabels ) {
        BarDataSet set1;
//TODO  這裏去掉此種方法賦值是因爲遇到如果第一次無數據,第二次再有數據的情況會導致柱狀圖顏色不疊加。不是2個顏色。官方demo也是這樣。
//        if (getData() != null &&
//                getData().getDataSetCount() > 0) {
//            set1 = (BarDataSet) getData().getDataSetByIndex(0);
//            set1.setValues(values);
//            getData().notifyDataChanged();
//            notifyDataSetChanged();
//
//        } else {
            set1 = new BarDataSet(values, label);
            set1.setDrawIcons(true);
//TODO 這裏是設置顏色的。
            int startColor1 = ContextCompat.getColor(context, R.color.yiban_color);
            int startColor2 = ContextCompat.getColor(context, R.color.xiaoguimo_color);
            List<Integer> colors = new ArrayList<>();
            colors.add(startColor1);
            colors.add(startColor2);
            set1.setColors(colors);
//            set1.setStackLabels(new String[]{"一般人","小規模"});
            set1.setStackLabels(StackLabels);
            ArrayList<IBarDataSet> dataSets = new ArrayList<>();
            dataSets.add(set1);

            BarData data = new BarData(dataSets);
            data.setValueTextSize(10f);
            data.setValueTypeface(tfLight);
            data.setBarWidth(0.4f);//這個是個百分百比,1表示佔滿100%, 0.5表示50%  代表柱狀圖的寬度。值越大柱狀圖越寬
            data.setDrawValues(false); // 設置是否顯示數據點的值
            //設置數據
            setData(data);
//        }
        invalidate();
        //TODO 設置完數據後。必須設置完數據後纔有效設置最大顯示11個。多的話需要滑動查看, 這樣固定住了 12個少的話。也不會放大
        setVisibleXRangeMaximum(12);
        setVisibleXRangeMinimum(12);

    }
}

2.在佈局文件裏,引入我們剛纔自定義的MyBarChart

       <com.lyf.demo.view.MPChart.MyBarChart
            android:id="@+id/barChart"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/rl_title"
            android:layout_marginBottom="10dp" />


​

3.在Acitivity裏面。我們拿到MyBarChart對象。然後給MyBarChart設置數據。

(1)看一下我們的網絡數據是一個list,裏面的BarDateBean內容

public class BarDataBean  implements Serializable {
  
   private String ssdsmc;//城市,或者區縣  x軸內容
   private float ybr;//  訂單個數  y軸內容
   private float xgm;//  訂單個數  y軸內容
   private float hj;//合計

    public BarDataBean(String ssdsmc, float ybr, float xgm, float hj) {
        this.ssdsmc = ssdsmc;
        this.ybr = ybr;
        this.xgm = xgm;
        this.hj = hj;
    }

   //set,get方法我這裏就不粘貼了。
}

(2)得到網絡數據後我們如何給柱狀圖設置數據代碼如下。

private String[] mSsLable = new String[]{"手機", "電腦"};//圖例

 ArrayList<BarEntry> values = new ArrayList<>();//柱狀圖需要的數據,values是網絡得到的數據。得到數據後調用setChartData方法設置數據就可以。(values的數據可以自己模擬幾條感受一下)



  /**
     * 設置柱狀圖和折線圖的數據。x軸和y軸的數據
     */
    private void setChartData() {
        getBarChartData();//把網絡數據轉爲柱狀圖需要的數據類型
        setXAxis(barChart.getXAxis());//設置x軸的數據
        barChart.setBarDataSet(values, "", mSsLable);//設置y軸的數據,和圖例
        
    }


 /**
     * 把得到的網絡是數據轉爲BarChart需要的數據類型。
     */
    private void getBarChartData() {
        values.clear();
        //下面是設置Y軸的數據,自己得到的數據類型轉爲chart需要的數據類型
        for (int i = 0; i < valueList.size(); i++) {
            values.add(new BarEntry(i, new float[]{valueList.get(i).getYbr(), valueList.get(i).getXgm()}));//兩個是float類型的
        }
    }


  private void setXAxis(XAxis xAxis) {
        /**  (1)第一種就是先給x軸設置ValueFOrmatter,然後這裏直接刷新。(2)或者就是不設置。這裏直接設置。
         第一種更新一下,x軸的數據。這樣到x軸得到了更新,點擊某個彈出的懸浮框內容也得到了更新。或者懸浮框也在這裏設置market*/
//        ((StringDataAxisValueFormatter)mXAxisFormatter).refreshList(valueList);

        StringDataAxisValueFormatter xFormatter = new StringDataAxisValueFormatter() {  //設置每個x軸的內容
            @Override
            public String getFormattedValue(float value) {//這個value是那邊BarEntry得到的x的值。
                try {
                   String cityName= (valueList.get((int) value)).getSsdsmc();
                   if(cityName.length()>4){//這裏是如果x軸文字長,就3個字後面用省略號
                           String bb = cityName.substring(0, 3);
                           cityName=bb+"...";
                   }
                    return cityName;
                } catch (Exception e) {
                    e.printStackTrace();
                    return "";
                }

            }
        };
        xAxis.setValueFormatter(xFormatter);
        int barLayoutId=R.layout.my_custom_marker_view;
      
        MyCustomMarkerView barMv = new MyCustomMarkerView(this, valueList,barLayoutId);
        
//        mv.setChartView(barChart); // For bounds control

        barChart.setMarker(barMv); // 柱狀圖設置market
      
        xAxis.setLabelCount(valueList.size());//TODO 這裏決定者x軸顯示的個數  拿到數據庫再設置顯示個數,也不確定起作用了沒,反正後面加上true。就都亂了
    }
4.在上圖setXAxis方法中。用到了自己寫的MarkerView。就是點擊柱狀圖彈出的marketView.效果如下。

實現方式很簡單。就是自己寫個類似的佈局。然後在自定義MarkerView。下面上代碼MyCustomMarkerView

public class MyCustomMarkerView extends MarkerView {

    private final TextView tvContent;
    private final TextView tv_yiban;
    private final TextView tv_xiaoguimo;
    List<BarDataBean> valueList;

    public MyCustomMarkerView(Context context, List<BarDataBean> valueList,int layoutId) {
//        super(context, R.layout.my_custom_marker_view);
        super(context, layoutId);
        tvContent = findViewById(R.id.tvContent);
        tv_yiban = findViewById(R.id.tv_yiban);
        tv_xiaoguimo = findViewById(R.id.tv_xiaoguimo);
        this.valueList=valueList;
    }

    // runs every time the MarkerView is redrawn, can be used to update the
    // content (user-interface)
    @Override
    public void refreshContent(Entry e, Highlight highlight) {
        try {
//            tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX()), format.format(e.getY())));
            float index = e.getX();//因爲沒有用formatter轉。所有這裏e.getX得到的索引號
            int pos = (int) index;
            tvContent.setText(valueList.get(pos).getSsdsmc());
//            Log.e("marker",e.getData().toString());e.mYVals[0]
            tv_yiban.setText((int)(valueList.get(pos).getYbr())+"");
            tv_xiaoguimo.setText((int)(valueList.get(pos).getXgm())+"");

        }catch (Exception ex){
           ex.printStackTrace();
        }
        super.refreshContent(e, highlight);
    }

    @Override
    public MPPointF getOffset() {
        return new MPPointF(-(getWidth() / 2), -getHeight());
    }
}

總結一下:

1.由於我的需求是根據時間段查詢數據。顯示柱狀圖。所以選擇時間後。柱狀圖數據不停的在改變包括x軸,遇到問題,當從無數據到有數據的時候。x軸內容文字會遮蓋,解決辦法是:拿到數據之後,從無到有數據狀態,調用兩遍setChartData()就可了。

2.從無到有數據適合。會出現柱狀圖不疊加了。而是顏色間隔顯示。已經在封裝的MyBarChart解決了。

3.設置完數據之後。setVisibleXRangeMaximum(12);        setVisibleXRangeMinimum(12); 設置可見最大最小都是12條,意思就是固定12條了。這樣多餘數據可以滑動查看。 當數據少的時候,柱狀圖也不會被放大。固定了寬度了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章