天天看點

CombinedChart 實作單個柱形圖+折線圖

  • 實作預設選中
  • 實作選中不可取消
  • 實作漸變色
  • 等等不慢慢看api還真不好搞啊
package com.xxmassdeveloper.mpchartexample;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.github.mikephil.charting.charts.CombinedChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.CombinedData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.Fill;
import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ManagerChartActivity extends DemoBase {

    private CombinedChart dataChart;//圖表
    private CombinedData data; //組合圖表資料
    private Highlight mHighlight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manager_chart);

        setContentView(R.layout.activity_manager_chart);
        dataChart = (CombinedChart) findViewById(R.id.manager_chart);
        showDataOnChart();//設定資料
        Legend legend = dataChart.getLegend();
        legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
        legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);

        dataChart.setTouchEnabled(true);
        dataChart.getLegend().setEnabled(false);//隐藏圖例
        dataChart.setDoubleTapToZoomEnabled(false);//不能輕按兩下放大
        dataChart.setScaleYEnabled(false);

        dataChart.setHighlightPerDragEnabled(true);//禁止通過拖拽高亮

        dataChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, Highlight h) {

                Log.d("點選"," "+e.getX()+" H : "+h.toString()+" 位置 ");


//                dataChart.highlightValue(h);
                mHighlight = h;

            }

            @Override
            public void onNothingSelected() {
                Log.d("點選 onNothingSelected"," ");
                //不允許取消
                if (mHighlight != null)
                    dataChart.highlightValue(mHighlight);
            }
        });

        IBarDataSet iBarDataSet = data.getBarData().getDataSetByIndex(0);
        BarEntry barEntry = iBarDataSet.getEntryForIndex(8);//預設選中九月柱形圖
        //擷取柱形圖資料
        dataChart.highlightValue(barEntry.getX(),barEntry.getY(),0,1,true);

    }

    @Override
    protected void saveToGallery() {

    }

    /**
     * 展示資料
     */
    private void showDataOnChart() {
        //繪制圖表資料
        data = new CombinedData();
        //設定柱狀圖資料
        data.setData(getBarData());
        //設定折線圖資料
        data.setData(getLineData());

        dataChart.setData(data);
        //設定橫坐标資料
        setAxisXBottom();
        //設定右側縱坐标資料
        setAxisYRight();
        //設定左側縱坐标資料
        setAxisYLeft();
//        dataChart.setTouchEnabled(false);
        dataChart.getDescription().setEnabled(false);
        dataChart.setDrawGridBackground(false);
        dataChart.setDrawBarShadow(false);

//        dataChart.setHighlightFullBarEnabled(true);
        dataChart.animateX(2000);
    }

    /**
     * 設定橫坐标資料
     */
    private void setAxisXBottom() {
        String[] date = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
        List<String> valuesX = new ArrayList<>(Arrays.asList(date));

        XAxis bottomAxis = dataChart.getXAxis();
        bottomAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        bottomAxis.setCenterAxisLabels(true);//标簽繪制在中間
        bottomAxis.setDrawGridLines(false);//不️繪制網格線
        bottomAxis.setValueFormatter(new IndexAxisValueFormatter(valuesX));//設定底部資料
        bottomAxis.setAxisMinimum(data.getXMin());          //設定x軸最小值
        bottomAxis.setAxisMaximum(data.getXMax() + 0.5f);   //設定x軸最大值
        bottomAxis.setLabelCount(date.length);              //設定标簽的數量
        bottomAxis.setAxisLineColor(Color.parseColor("#F6F8FA"));//設定軸線顔色
        bottomAxis.setAxisLineWidth(3); //設定軸線寬度
        bottomAxis.setTextColor(Color.parseColor("#364258"));
        //在放大時為軸設定最小的間隔。坐标軸不允許低于這個極限。這可以用來避免标簽複制時,放大。
        bottomAxis.setGranularity(1f);

    }

    /**
     * 設定右側縱坐标資料
     */
    private void setAxisYRight() {
        YAxis right = dataChart.getAxisRight();
        right.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                return value + "℃";
            }
        });
        right.setAxisMinimum(0f);//為坐标軸設定最小值
        right.setDrawGridLines(false);
        right.setEnabled(false);
    }

    /**
     * 設定左側縱坐标資料
     */
    private void setAxisYLeft() {
        YAxis left = dataChart.getAxisLeft();
        left.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                return value + "ml";
            }
        });
        left.setDrawGridLines(false);
        left.setAxisMinimum(0f);//為坐标軸設定最小值
        left.setEnabled(false);
    }

    /**
     * 設定折線圖繪制資料
     * 溫度
     * @return
     */
    public LineData getLineData() {
        LineData lineData = new LineData();
        List<Entry> customCounts = new ArrayList<>();
        float[] data = {10.0f, 2.2f, 3.3f, 4.5f, 6.3f, 10.2f, 20.3f, 23.4f, 25.0f, 16.5f, 12.0f, 6.2f};
        //人數
        for (int i = 0; i < data.length; i++) {
            customCounts.add(new Entry(i + 0.5f,data[i]));
        }
        LineDataSet lineDataSet = new LineDataSet(customCounts,"平均溫度");
        lineDataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
        lineDataSet.setColor(Color.parseColor("#44D7C8"));
        lineDataSet.setCircleColor(Color.parseColor("#44D7C8"));
        lineDataSet.setCircleRadius(4);
        lineDataSet.setLineWidth(2);
        lineDataSet.setValueTextSize(12);
        lineDataSet.setValueTextColor(Color.parseColor("#44D7C8"));
        lineDataSet.setDrawVerticalHighlightIndicator(true);  //去除十字線
        lineDataSet.setDrawHorizontalHighlightIndicator(true);//去除十字線

        lineDataSet.setMode(LineDataSet.Mode.LINEAR);//設定曲線連結
        lineDataSet.setDrawValues(false);

        lineData.addDataSet(lineDataSet);
        lineData.setHighlightEnabled(false);//關閉折線圖的高亮
        return lineData;
    }

    /**
     * 設定柱狀圖繪制資料
     *
     * @return
     */
    public BarData getBarData() {
        BarData barData = new BarData();
        //總量金額
        List<BarEntry> amounts = new ArrayList<>();
        float[] z = {12.0f, 4.9f, 7.0f, 23.2f, 25.6f, 76.7f, 135.6f, 162.2f, 32.6f, 20.0f, 6.4f, 3.3f};
        //平均金額
        List<BarEntry> averages = new ArrayList<>();
        float[] j = {80f, 80f, 80f, 80f, 80f, 80f, 80f, 80f, 80f, 80f, 80f, 80f};
        //添加資料
        for (int i = 0; i < z.length; i++) {
            amounts.add(new BarEntry(i,z[i]));
            averages.add(new BarEntry(i,j[i]));

        }

        int startColor1 = ContextCompat.getColor(this, R.color.red_start);
//        int startColor2 = ContextCompat.getColor(this, R.color.red_start2);
        int endColor1 = ContextCompat.getColor(this, R.color.red_end);
//        int endColor2 = ContextCompat.getColor(this, R.color.red_end2);

        List<Fill> gradientFills = new ArrayList<>();
        gradientFills.add(new Fill(startColor1, endColor1));
//        gradientFills.add(new Fill(startColor2, endColor2));

        //設定總數的柱狀圖
        BarDataSet amountBar = new BarDataSet(amounts,"蒸發量");
        amountBar.setAxisDependency(YAxis.AxisDependency.LEFT);
//        amountBar.setColor(Color.parseColor("#C23531"));
        amountBar.setDrawValues(false);
        amountBar.setFills(gradientFills);//設定柱狀圖顔色
        amountBar.setHighLightColor(ContextCompat.getColor(this,R.color.red_end));//設定高亮顔色
        amountBar.setHighLightAlpha(200);

        //設定平均的柱狀圖
        BarDataSet averageBar = new BarDataSet(averages,"降水量");
        averageBar.setAxisDependency(YAxis.AxisDependency.LEFT);
        averageBar.setColor(Color.parseColor("#2F4554"));
//        amountBar.setFills(gradientFills);//設定柱狀圖顔色
        averageBar.setDrawValues(false);

        amountBar.setValueTextSize(10);
        averageBar.setValueTextSize(10);


        barData.addDataSet(amountBar);//添加一個柱狀圖的資料
//        barData.addDataSet(averageBar);//暫時不加第二個柱子
        //設定柱狀圖顯示的大小
        float groupSpace = 0.4f;
        float barSpace = 0.4f;
        float barWidth = 0.2f;
        barData.setBarWidth(barWidth);

        barData.groupBarsNew(0, groupSpace, barSpace);
        return barData;
    }
}
           

BarData.java 新加方法

其實隻是把前三行代碼去掉

public void groupBarsNew(float fromX, float groupSpace, float barSpace) {

//        int setCount = mDataSets.size();
//        if (setCount <= 1) {
//            throw new RuntimeException("BarData needs to hold at least 2 BarDataSets to allow grouping.");
//        }

        IBarDataSet max = getMaxEntryCountSet();//擷取數量最多柱狀圖資料集

        int maxEntryCount = max.getEntryCount();//擷取數量

        float groupSpaceWidthHalf = groupSpace / 2f;// 組間距
        float barSpaceHalf = barSpace / 2f; //狀态條間距
        float barWidthHalf = mBarWidth / 2f;//一半的寬度

        float interval = getGroupWidth(groupSpace, barSpace);//繪制一組資料需要的長度
        //周遊最大數量
        for (int i = 0; i < maxEntryCount; i++) {

            float start = fromX;
            fromX += groupSpaceWidthHalf;//加一半groupSpace
            //周遊資料集
            for (IBarDataSet set : mDataSets) {

                fromX += barSpaceHalf;//加上一半的barSpace
                fromX += barWidthHalf;//加上一半的barWidth

                if (i < set.getEntryCount()) {

                    BarEntry entry = set.getEntryForIndex(i);//擷取對應的柱狀圖條

                    if (entry != null) {
                        entry.setX(fromX);//設定起點
                    }
                }

                fromX += barWidthHalf;//加上一半的barWidth
                fromX += barSpaceHalf;//加上一半的barSpace
            }

            fromX += groupSpaceWidthHalf;//加一半groupSpace
            float end = fromX;
            float innerInterval = end - start; //一組資料的長度

            float diff = interval - innerInterval;//剩餘空間

            // correct rounding errors
            if (diff > 0 || diff < 0) {
                fromX += diff;
            }
        }

        notifyDataChanged();
    }
           

這是一個不錯的教程