做一個(gè)統(tǒng)計(jì)分布條昙衅,比如每個(gè)月的支出分布情況,某一類盈利的收入類型粘招。
這里沒(méi)有采用柱狀圖、餅圖的做法偎球,所以想要柱狀圖或者餅圖的可以不用往下看了洒扎,推薦一個(gè)圖表框架MPAndroidChart
,可以實(shí)現(xiàn)柱狀圖衰絮、餅圖等圖表袍冷。
效果圖
20190625120649.png
實(shí)現(xiàn)原理
原理很簡(jiǎn)單,就是繼承一個(gè)LinearLayout猫牡,通過(guò)addView的方式動(dòng)態(tài)去添加View胡诗,每一個(gè)支出類型就是一個(gè)TextView。采用動(dòng)態(tài)添加的原因是淌友,因?yàn)槊總€(gè)占比大小是不一樣的煌恢,我們需要去計(jì)算出并且設(shè)置TextView的寬度。
CoinPosition 封裝的一個(gè)比例分布類震庭,是該控件的一個(gè)靜態(tài)內(nèi)部類瑰抵。
public static class CoinPosition{
//每個(gè)Item的占比以及名字
private String coinName;
private double percent;
public CoinPosition(String coinName, double percent) {
this.coinName = coinName;
this.percent = percent;
}
public String getCoinName() {
return coinName;
}
public void setCoinName(String coinName) {
this.coinName = coinName;
}
public double getPercent() {
return percent;
}
public void setPercent(double percent) {
this.percent = percent;
}
}
核心代碼:
private View getChildView(CoinPosition coinPosition,int index){
LinearLayout.LayoutParams params;
if(index == data.size()-1){//1
params= new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);//2
}else {
params= new LinearLayout.LayoutParams((int) (parentWidth * coinPosition.percent),LayoutParams.MATCH_PARENT);//3
}
TextView textView=new TextView(getContext());
textView.setLayoutParams(params);
textView.setText(coinPosition.coinName);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(12);
textView.setTextColor(Color.parseColor("#FFFFFF"));
if(index<colorRes.length){
textView.setBackgroundColor(colorRes[index]);
}
return textView;
}
getChildView去獲得子View的實(shí)例,并且將相應(yīng)的名字器联、控件寬度已經(jīng)背景顏色配置上去二汛。
注釋1中判斷索引位置婿崭,注釋3在設(shè)定子View寬度的時(shí)候是有丟失精度取整的,所以在注釋1中需要判斷當(dāng)前索引是否為數(shù)據(jù)的最后一個(gè)习贫,最后一個(gè)不用注釋3的方法得到寬度逛球,否則的話會(huì)出現(xiàn)控件會(huì)出現(xiàn)空白,直接傳入LayoutParams.MATCH_PARENT苫昌,利用完剩余的父布局寬度颤绕。
完整的代碼:
package com.beidd.digiccy.myapplication;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* @author Hugh.HYS
* @date 2019/6/24
*/
public class DistributionLine extends LinearLayout {
private List<CoinPosition> data=new ArrayList<>();
private LayoutInflater layoutInflater;
private int parentWidth;
private int[] colorRes=new int[6];
private Handler handler;
public List<CoinPosition> getData() {
return data;
}
public void setData(List<CoinPosition> data) {
if(data.size()==0){
return;
}
this.data.clear();
this.data.addAll(data);
handler.postDelayed(new Runnable() {
@Override
public void run() {
updateView();
}
},500);
}
public DistributionLine(Context context) {
super(context);
initConfig();
}
public DistributionLine(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initConfig();
}
public DistributionLine(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initConfig();
}
public DistributionLine(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initConfig();
}
private void initConfig(){
setOrientation(LinearLayout.HORIZONTAL);
if(handler==null){
handler=new Handler();
}
if(layoutInflater==null){
layoutInflater= LayoutInflater.from(getContext());
}
//初始化顏色配置
colorRes[0]= Color.parseColor("#DC143C");
colorRes[1]= Color.parseColor("#4B0082");
colorRes[2]= Color.parseColor("#FF0000");
colorRes[3]= Color.parseColor("#00FFFF");
colorRes[4]= Color.parseColor("#2E8B57");
colorRes[5]= Color.parseColor("#DAA520");
}
private void updateView(){
removeAllViews();
parentWidth=getMeasuredWidth();
for (int i=0;i<data.size();i++){
addView(getChildView(data.get(i),i));
}
}
private View getChildView(CoinPosition coinPosition,int index){
LinearLayout.LayoutParams params;
if(index == data.size()-1){
params= new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
}else {
params= new LinearLayout.LayoutParams((int) (parentWidth * coinPosition.percent),LayoutParams.MATCH_PARENT);
}
TextView textView=new TextView(getContext());
textView.setLayoutParams(params);
textView.setText(coinPosition.coinName);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(12);
textView.setTextColor(Color.parseColor("#FFFFFF"));
if(index<colorRes.length){
textView.setBackgroundColor(colorRes[index]);
}
return textView;
}
public static class CoinPosition{
//每個(gè)Item的占比以及名字
private String coinName;
private double percent;
public CoinPosition(String coinName, double percent) {
this.coinName = coinName;
this.percent = percent;
}
public String getCoinName() {
return coinName;
}
public void setCoinName(String coinName) {
this.coinName = coinName;
}
public double getPercent() {
return percent;
}
public void setPercent(double percent) {
this.percent = percent;
}
}
}
測(cè)試:
package com.beidd.digiccy.myapplication;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
/**
* @author Hugh.HYS
* @date 2019/4/3
*/
public class TestActivity extends AppCompatActivity {
private DistributionLine distributionLine;
final List<DistributionLine.CoinPosition> data=new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act);
distributionLine=findViewById(R.id.dis);
data.clear();
data.add(new DistributionLine.CoinPosition("投資",0.3));
data.add(new DistributionLine.CoinPosition("衣服",0.2));
data.add(new DistributionLine.CoinPosition("吃喝",0.2));
data.add(new DistributionLine.CoinPosition("玩樂(lè)",0.1));
data.add(new DistributionLine.CoinPosition("出行",0.1));
data.add(new DistributionLine.CoinPosition("其它",0.1));
distributionLine.setData(data);
}
}