MPAndroidChart的簡單封裝

框架地址:https://github.com/PhilJay/MPAndroidChart

因爲需求中大部分圖表的樣式都差不多,只有裏面的數據做了變化,而使用圖表的時候又需要對圖表進行各種各樣的配置,所以對圖表框架進一步封裝是有必要的。
我這裏將圖表的配置寫在一個類中,將常用的方法(數據,圖表顏色,描述,等等)令寫方法出來設置。。因爲使用的是建造者模式,可以根據需求定義。這裏封裝了線性圖、餅狀圖、柱狀圖、雷達圖。

寫了一個數據類ChartValue用來存放所需數據的XY值,然後將數據設置也封裝到了,配置類中,圖表構建完成後獲得圖表的View對象,填充到想要的佈局中去。

具體實現

ChartView數據類:用來存放X,Y軸值。

package cn.xiaolongonly.mpchartsample.bean;

/**
 * @author xiaolong
 * @version v1.0
 * @function <描述功能>
 * @date 2016/9/22-17:32
 */
public class ChartValue<T> {
    public String xVal;
    public T yVal;

    public ChartValue() {
    }

    public ChartValue(String xVal, T yVal) {
        this.xVal = xVal;
        this.yVal = yVal;
    }
}

Item項:每個需要的圖表構建一個item對象,存放固定配置和數據設置


package cn.xiaolongonly.mpchartsample.chart.item;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;

import com.github.mikephil.charting.charts.LineChart;
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.ChartData;
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.interfaces.datasets.ILineDataSet;

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

import cn.xiaolongonly.mpchartsample.R;
import cn.xiaolongonly.mpchartsample.bean.ChartValue;
import cn.xiaolongonly.mpchartsample.chart.markview.DataMarkView;
import cn.xiaolongonly.mpchartsample.chart.util.ColorTemplate;

public class LineChartItem extends BaseChartItem {
    private String xDesc;
    private String yDesc;
    private DataMarkView dataMarkView;

    public LineChartItem(ChartData cd, Context c, IAxisValueFormatter iAxisValueFormatter) {
        super(cd, c, iAxisValueFormatter);
    }

    public LineChartItem(ChartData cd, Context c, DataMarkView dataMarkView, IAxisValueFormatter iAxisValueFormatter) {
        super(cd, c, iAxisValueFormatter);
        this.dataMarkView = dataMarkView;
    }

    @Override
    public int getItemType() {
        return TYPE_LINECHART;
    }

    public View getView() {
        return getView(null);
    }

    public String getxDesc() {
        return xDesc;
    }

    public void setxDesc(String xDesc) {
        this.xDesc = xDesc;
    }

    public String getyDesc() {
        return yDesc;
    }

    public void setyDesc(String yDesc) {
        this.yDesc = yDesc;
    }

    @Override
    public View getView(View convertView) {

        ViewHolder holder = null;

        if (convertView == null) {

            holder = new ViewHolder();

            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.list_item_linechart, null);
            holder.chart = (LineChart) convertView.findViewById(R.id.chart);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        // apply styling

        LineChart lineChart = (LineChart) holder.chart;
        lineChart.setBackgroundColor(mContext.getResources().getColor(R.color.chart_bg));
        lineChart.getLegend().setPosition(Legend.LegendPosition.ABOVE_CHART_LEFT);
        lineChart.getLegend().setForm(Legend.LegendForm.CIRCLE);
        // 設置無數據文本提示
        lineChart.setDescription(null);
//        lineChart.setNoDataText(mContext.getResources().getString(R.string.chart_no_data));
//        lineChart.setXYDesc(xDesc, yDesc);
        if (!xDesc.equals("") || !yDesc.equals("")) {
            lineChart.setXYDesc(xDesc, yDesc, 10f, mContext.getResources().getColor(R.color.normal_black_color));
        }
        //設置單方向和雙方向縮放 true x,y方向可以同時控制,false只能控制x方向的縮小放大或者Y方向的縮小放大
        lineChart.setPinchZoom(true);
        DataMarkView dataMarkView = new DataMarkView(mContext, 0, "");
        lineChart.setMarkerView(dataMarkView);
        lineChart.setDrawGridBackground(false);
        XAxis xAxis = lineChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //定製X軸是在圖表上方還是下方。
        xAxis.setDrawGridLines(false);
        xAxis.setGranularity(1);//放大的時候X值不增多
        xAxis.setValueFormatter(mIAxisValueFormatter);
        if (dataMarkView != null) {
            lineChart.setMarkerView(dataMarkView);
        }
        YAxis yAxisRight = lineChart.getAxisRight();
        yAxisRight.setEnabled(false);
        YAxis yAxisLeft = lineChart.getAxisLeft();
        yAxisLeft.setAxisMinimum(0);
        // set data
        lineChart.setData((LineData) mChartData);

        // do not forget to refresh the chart
        // holder.chart.invalidate();
        lineChart.animateX(750);
        lineChart.animateY(750);

        return convertView;

    }

    public static class Builder {
        private int[] colors = ColorTemplate.PIE_COLORS;
        private String[] describles = new String[]{""};
        private String xDesc = "";
        private String yDesc = "";
        private List<List<ChartValue>> charValueLists = new ArrayList<>();
        private Context context;
        private boolean isFillColor;
        private ArrayList<String> labels = new ArrayList<>();

        public Builder(Context context) {
            this.context = context;
        }

        public Builder addChartValueList(List<ChartValue> charValueLists) {
            this.charValueLists.add(charValueLists);
            return this;
        }

        public Builder setChartValueList(List<List<ChartValue>> charValueLists) {
            this.charValueLists = charValueLists;
            return this;
        }

        public Builder setyDesc(String yDesc) {
            this.yDesc = yDesc;
            return this;
        }

        public Builder setxDesc(String xDesc) {
            this.xDesc = xDesc;
            return this;
        }

        public Builder setDescribles(String[] describles) {
            this.describles = describles;
            return this;
        }

        public Builder setColorReses(int[] colorReses) {
            this.colors = new int[colorReses.length];
            for (int i = 0; i < colors.length; i++) {
                colors[i] = context.getResources().getColor(colorReses[i]);
            }
            return this;
        }

        public Builder fillColorEnable(boolean isFillColor) {
            this.isFillColor = isFillColor;
            return this;
        }

        public LineChartItem build() {
            return build(null);
        }

        public LineChartItem build(DataMarkView dataMarkView) {
            List<ILineDataSet> lineDataSets = new ArrayList<>();
            for (int listIndexOutside = 0; listIndexOutside < charValueLists.size(); listIndexOutside++) {
                ArrayList<Entry> entries = new ArrayList<Entry>();
                for (int listIndexInside = 0; listIndexInside < charValueLists.get(listIndexOutside).size(); listIndexInside++) {
                    entries.add(new Entry((float) listIndexInside, (float) charValueLists.get(listIndexOutside).get(listIndexInside).yVal));
                    if (listIndexOutside == 0) {
                        labels.add(charValueLists.get(listIndexOutside).get(listIndexInside).xVal);
                    }
                }
                lineDataSets.add(generateLineDataSet(entries, describles[listIndexOutside], colors[listIndexOutside % colors.length]));
            }
            IAxisValueFormatter iAxisValueFormatter = new IAxisValueFormatter() {
                @Override
                public String getFormattedValue(float value, AxisBase axis) {
                    return labels.get((int) value % labels.size());
                }
            };
            LineData cd = new LineData(lineDataSets);
            LineChartItem lineChartItem = null;
            if (dataMarkView != null) {
                lineChartItem = new LineChartItem(cd, context, dataMarkView, iAxisValueFormatter);
            } else {
                lineChartItem = new LineChartItem(cd, context, iAxisValueFormatter);
            }
            lineChartItem.setxDesc(xDesc);
            lineChartItem.setyDesc(yDesc);
            return lineChartItem;
        }

        private ILineDataSet generateLineDataSet(ArrayList<Entry> entries, String describle, int color) {
            LineDataSet dataSet = new LineDataSet(entries, describle);
            dataSet.setLineWidth(2.0f);
            dataSet.setCircleRadius(3.5f);
            dataSet.setDrawCircleHole(true);//填充圓
            dataSet.setValueTextSize(9f);
            dataSet.setHighlightLineWidth(2.0f);
            dataSet.setDrawFilled(isFillColor);
            dataSet.setFillAlpha(51);
            dataSet.setFillColor(color); //填充色
            dataSet.setHighLightColor(color); //選中十字線色
            dataSet.setColor(color); //線條顏色
            dataSet.setCircleColor(color); //圓點顏色
            dataSet.setCircleColorHole(Color.WHITE);
            dataSet.setCircleHoleRadius(2.0f);
            dataSet.setDrawValues(false);
            return dataSet;
        }
    }

}

當然如果需求圖表有其他樣式的的話,我覺得也可以把配置信息抽取出來,通過不同的配置來設置不同的樣式。

在Activity中的使用


package cn.xiaolongonly.mpchartsample.ui;

import android.widget.RelativeLayout;

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

import cn.xiaolongonly.mpchartsample.R;
import cn.xiaolongonly.mpchartsample.base.BaseTitleActivity;
import cn.xiaolongonly.mpchartsample.bean.ChartValue;
import cn.xiaolongonly.mpchartsample.chart.item.LineChartItem;

/**
 * @author xiaolong
 * @version v1.0
 * @function <描述功能>
 * @date 2016/12/5-17:32
 */
public class LineChartActivity2 extends BaseTitleActivity {
    private RelativeLayout rlContent;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_chart;
    }

    @Override
    protected void initView() {
        rlContent = findView(R.id.rlContent);
        List<ChartValue> chartValues = new ArrayList<>();
        chartValues.add(new ChartValue("11月", 110f));
        chartValues.add(new ChartValue("10月", 120f));
        chartValues.add(new ChartValue("9月", 100f));
        List<ChartValue> chartValues2 = new ArrayList<>();
        chartValues2.add(new ChartValue("11月", 155f));
        chartValues2.add(new ChartValue("10月", 133f));
        chartValues2.add(new ChartValue("9月", 122f));
        LineChartItem lineChartItem = new LineChartItem.Builder(this).setxDesc("單位(月)")
                .setyDesc("單位(萬)").setDescribles(new String[]{"項目支出金額"})
                .addChartValueList(chartValues).addChartValueList(chartValues2)
                .build();
        rlContent.addView(lineChartItem.getView());
    }

    @Override
    protected void setListener() {

    }

}

是不是就簡單多了只要構建一個Item對象,然後將item對象的圖表佈局,add到View中去就可以了。

實現效果
實現效果

項目github下載

總結

一直都沒想到有一天我也能這麼寫代碼,感覺代碼寫多了很多東西就懂了。

在最開始的時候老大讓我對圖表框架進行二次封裝,我聽的一臉懵逼,經過一段時間的思考,反覆對照之前的項目,因爲之前的項目的配置都寫在繼承的圖表中,在xml佈局中要將圖表改成繼承的圖表,數據導入也寫在了Activity類中,感覺代碼特別多且雜,後來想到了一句話,多用組合少用繼承,現在看來確實,組合的方式會比繼承好很多。雖然參考了好多代碼,封裝的也不怎麼樣,但是我確實是做到了。

那時候跟同時說我把圖表框架封裝完的時候,同事說,不會啊封裝的不錯。對於我這種渣渣來講就是莫大的安慰了。離自己的目標又近了一步。加油~~

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