Android自定义控件之美观的实用型统计表的制作

概述

绘制统计表,势必要用到自定义控件,一个统计表,看起来单元项很多,但实际上做起来并不复杂。
  • 要传递数据进来,用集合类最好。

  • 要确定每个表格单元的宽和高,并根据数据数目和表格每列的高来决定自定义控件的高。

  • 绘制表格线和表格单元背景的颜色,同时,绘制每个表格单元的文本。

先看看效果:

Android自定义控件之美观的实用型统计表的制作_第1张图片

Demo

自定义一个控件:

/**
 * Created by Administrator on 2015/10/20.
 */
public class ChartTableView extends View {

    private int width;//控件宽
    private int height;//控件高
    private int dataNum;//数据量

    private Paint mPaintText;//用于绘制文本
    private Paint mPaintWhiteBg;//用于绘制白色背景
    private Paint mPaintGreyBg;//用于绘制灰色背景
    private Paint mPaintLightGrey;//用于绘制浅灰色背景
    private Paint mPaintLine;//用于画表格的列线

    private int visitSum;//总访问量
    private int workerSum;//员工总数目
    private float visitAverage;//平均访问量
    private int textSize = SizeConvert.dip2px(getContext(), 13);//文本尺寸,dp转px

    private ArrayList dataList;//总数据

    public ChartTableView(Context context) {
        super(context);
    }

    public ChartTableView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaintLine = new Paint();
        mPaintLine.setColor(Color.LTGRAY);
        mPaintLine.setStrokeWidth(1);
        mPaintLine.setAntiAlias(true);

        mPaintText = new Paint();
        mPaintText.setColor(Color.BLACK);
        mPaintText.setTextSize(textSize);
        mPaintText.setTextAlign(Paint.Align.CENTER);
        mPaintText.setAntiAlias(true);

        mPaintWhiteBg = new Paint();
        mPaintWhiteBg.setColor(Color.WHITE);
        mPaintWhiteBg.setStyle(Paint.Style.FILL);
        mPaintWhiteBg.setAntiAlias(true);


        mPaintGreyBg = new Paint();
        mPaintGreyBg.setColor(Color.argb(255, 240, 240, 240));
        mPaintGreyBg.setStyle(Paint.Style.FILL);
        mPaintGreyBg.setAntiAlias(true);

        mPaintLightGrey = new Paint();
        mPaintLightGrey.setColor(Color.argb(255, 250, 250, 250));
        mPaintLightGrey.setStyle(Paint.Style.FILL);
        mPaintLightGrey.setAntiAlias(true);

        dataList = new ArrayList<>();

    }

    /**
     * 得到dataList并确定一部分变量的值
     * @param dataList
     */
    public void setDataList(ArrayList dataList) {
        this.dataList = dataList;
        dataNum = dataList.size();
        for(VisitSummaryData data:dataList){
            visitSum += data.getVisitTotal();
            workerSum += data.getWorkerTotal();
            visitAverage += data.getVisitDaily();
        }
        visitAverage /= dataNum;
        visitAverage = (float)(Math.round(visitAverage*10))/10;//让平均访问量只保留一位小数
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        //根据数据数量来得到控件高
        if (dataNum != 0) {
            height = (dataNum+1)*tableItemHeight;
        }
        //表格单元宽
        tableItemWidth = width/4;
        setMeasuredDimension(width, height);
    }

    private int tableItemWidth;
    private int tableItemHeight = SizeConvert.dip2px(getContext(),36);//表格单元高
    /**
     * 表格左上角的横纵坐标
     */
    private float startX;
    private float startY;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制统计表表第一列
        canvas.drawRect(startX, startY, startX + tableItemWidth, startY + tableItemHeight, mPaintLightGrey);
        canvas.drawRect(startX + tableItemWidth, startY, width, startY + tableItemHeight, mPaintGreyBg);
        canvas.drawText("合计(" + dataNum + ")", startX + tableItemWidth / 2, startY + tableItemHeight / 2+textSize/2, mPaintText);
        canvas.drawText(visitSum+"",startX+tableItemWidth*3/2,startY+tableItemHeight/2+textSize/2,mPaintText);
        canvas.drawText(workerSum+"",startX+tableItemWidth*5/2,startY+tableItemHeight/2+textSize/2,mPaintText);
        canvas.drawText(visitAverage+"",startX+tableItemWidth*7/2,startY+tableItemHeight/2+textSize/2,mPaintText);

        for(int i=0;iif(i%2==1) {
                canvas.drawRect(startX + tableItemWidth, startY, width, startY + tableItemHeight, mPaintGreyBg);
            }else {
                canvas.drawRect(startX + tableItemWidth, startY, width, startY + tableItemHeight, mPaintWhiteBg);
            }
            canvas.drawText(dataList.get(i).getName(), startX + tableItemWidth / 2, startY + tableItemHeight / 2+textSize/2, mPaintText);
            canvas.drawText(dataList.get(i).getVisitTotal()+"",startX+tableItemWidth*3/2,startY+tableItemHeight/2+textSize/2,mPaintText);
            canvas.drawText(dataList.get(i).getWorkerTotal()+"",startX+tableItemWidth*5/2,startY+tableItemHeight/2+textSize/2,mPaintText);
            canvas.drawText(dataList.get(i).getVisitDaily()+"",startX+tableItemWidth*7/2,startY+tableItemHeight/2+textSize/2,mPaintText);

            canvas.drawLine(0, tableItemHeight * (i + 1), width, tableItemHeight * (i + 1), mPaintLine);
        }

        startX=0;
        startY=0;

    }

尺寸转换工具类:

public class SizeConvert {

    /**
     * 将dp转换为sp
     */
    public static int dip2px(Context context, float dipValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(dipValue * scale + 0.5f);
    }

    /**
     * sp转dp
     */
    public static int px2dip(Context context, float pxValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(pxValue / scale + 0.5f);
    }
}

数据类,包含列表列单元的数据:

public class VisitSummaryData {
    private int id;
    private String name;
    private int visitTotal;
    private int workerTotal;
    private float visitDaily;

    public VisitSummaryData(int id, String name, int visitTotal, int workerTotal, float visitDaily) {
        this.id = id;
        this.name = name;
        this.visitTotal = visitTotal;
        this.workerTotal = workerTotal;
        this.visitDaily = visitDaily;
    }

    public VisitSummaryData(String name, int visitTotal, int workerTotal, float visitDaily) {
        this.name = name;
        this.visitTotal = visitTotal;
        this.workerTotal = workerTotal;
        this.visitDaily = visitDaily;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getVisitTotal() {
        return visitTotal;
    }

    public void setVisitTotal(int visitTotal) {
        this.visitTotal = visitTotal;
    }

    public int getWorkerTotal() {
        return workerTotal;
    }

    public void setWorkerTotal(int workerTotal) {
        this.workerTotal = workerTotal;
    }

    public float getVisitDaily() {
        return visitDaily;
    }

    public void setVisitDaily(int visitDaily) {
        this.visitDaily = visitDaily;
    }
}

主活动:

public class VisitSumTableActivity extends Activity {
    private ChartTableView chartTableView;
    private ArrayList dataList;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_visit_summary);

        chartTableView = (ChartTableView) findViewById(R.id.chartTableView_visitSummary);
        initChartTable();
    }

    private void initChartTable() {
        dataList = new ArrayList<>();
        dataList.add(new VisitSummaryData("涛涛",23,35,3.5f));
        dataList.add(new VisitSummaryData("萌萌",22,42,2.5f));
        dataList.add(new VisitSummaryData("秀秀",14,24,5.5f));
        dataList.add(new VisitSummaryData("光光",66,347,3.0f));
        dataList.add(new VisitSummaryData("瑞瑞",42,34,3.9f));
        dataList.add(new VisitSummaryData("美美",24,44,0.5f));
        dataList.add(new VisitSummaryData("笑笑",24,77,2.3f));
        dataList.add(new VisitSummaryData("狒狒",87,69,9.8f));
        dataList.add(new VisitSummaryData("飞飞",97,45,3.2f));
        dataList.add(new VisitSummaryData("肥肥",69,38,4.5f));
        dataList.add(new VisitSummaryData("小明",28,68,7.5f));
        dataList.add(new VisitSummaryData("小红",27,34,9.5f));
        //将数据传入自定义控件里
        chartTableView.setDataList(dataList);
    }

}

布局文件layout_visit_summary.xml:这个布局文件并不是原布局文件,我删除了一些东西,可以根据自己的需要,自定义布局文件,只要声明了自定义控件并能显示在恰当位置就行了。


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <RelativeLayout
        android:id="@+id/relativeLayout_top"
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <LinearLayout
            android:id="@+id/linearlayout_backChart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="5dp"
            android:gravity="center"
            android:orientation="horizontal">
            <Button
                android:layout_width="25dp"
                android:layout_height="25dp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="报表"/>
        LinearLayout>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="拜访汇总"
            android:textSize="20dp"/>

        <TextView
            android:id="@+id/textView_ranking"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="10dp"
            android:text="排名"
            android:textSize="16dp"/>

    RelativeLayout>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="昨日,快消体验版"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="#818297">
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="12dp"
            android:text="部门/人员"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:textSize="12dp"
            android:gravity="center"
            android:text="拜访总数"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="12dp"
            android:text="总工作人数"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="12dp"
            android:text="日人均拜访"/>
    LinearLayout>
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scrollbars="none">
        <com.test.shiweiwei.myproject.widget.ChartTableView
            android:id="@+id/chartTableView_visitSummary"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    ScrollView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:gravity="center">
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingRight="10dp">
            <ImageButton
                android:id="@+id/button_visitSum_refresh"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/button_visitSum_refresh"
                android:padding="5dp"
                android:textSize="10dp"
                android:text="刷新"/>
        RelativeLayout>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="20dp">
            <ImageButton
                android:id="@+id/button_visitSum_sift"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/button_visitSum_sift"
                android:padding="5dp"
                android:textSize="10dp"
                android:text="筛选"/>
        RelativeLayout>
    LinearLayout>

LinearLayout>

如果这篇博客帮助到您,您可以完成以下操作:
在网易云搜索“星河河”->歌手->点击进入(您将进入我的网易云音乐人账号星河河)->关注我->多听听我的歌。
其它各大平台可能都能搜到我。

你可能感兴趣的:(android,Android拾荒记)