概述

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

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

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

先看看效果:

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转pxprivate ArrayList<VisitSummaryData> 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<VisitSummaryData> 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();}@Overrideprotected 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;@Overrideprotected 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;i<dataNum;i++){startY += tableItemHeight;canvas.drawRect(startX, startY, startX + tableItemWidth, startY + tableItemHeight, mPaintLightGrey);if(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<VisitSummaryData> dataList;@Overrideprotected 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:这个布局文件并不是原布局文件,我删除了一些东西,可以根据自己的需要,自定义布局文件,只要声明了自定义控件并能显示在恰当位置就行了。

<?xml version="1.0" encoding="utf-8"?>
<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自定义控件之美观的实用型统计表的制作相关推荐

  1. Android自定义控件开发系列(一)——第一次动手做自定义控件

    Android系统提供的控件多种多样,以至于很多初学者经常忘了还有这样那样的控件没用过甚至没听过.尽管如此,但是系统控件大多比较死板,而且不够美观,很多多样化的显示或是交互方式都没法完成.每每遇到这种 ...

  2. Android自定义控件开发系列(零)——基础原理篇

    在后边的文章中发现在说Android自定义时,有时候要重复解释很多东西,所以想想返回来增加一篇"基础原理篇",直接进入正题吧-- 首先的问题是:在Android项目开发中,什么时候 ...

  3. Android自定义控件:打造自己的QQ空间主页

    前面已经实现过仿QQ的List抽屉效果以及仿QQ未读消息拖拽效果,具体请见: Android自定义控件:类QQ抽屉效果 Android自定义控件:类QQ未读消息拖拽效果 趁热打铁,这次我们实现QQ空间 ...

  4. Android自定义控件NumberCircleProgressBar(圆形进度条)的实现

    Android自定义控件NumberCircleProgressBar(圆形进度条)的实现

  5. android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...

    转载:http://blog.csdn.net/xiabing082/article/details/48781489 1.  大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...

  6. android里的editText怎么用,Android自定义控件EditText使用详解

    本文实例为大家分享了Android自定义控件EditText的具体代码,供大家参考,具体内容如下 自定义控件分三种: 1. 自绘控件 2. 组合控件 3. 继承控件 代码已上传到 github 以后的 ...

  7. android汽车之家顶部滑动菜单,Android自定义控件之仿汽车之家下拉刷新

    关于下拉刷新的实现原理我在上篇文章Android自定义控件之仿美团下拉刷新中已经详细介绍过了,这篇文章主要介绍表盘的动画实现原理 汽车之家的下拉刷新分为三个状态: 第一个状态为下拉刷新状态(pull ...

  8. Android 自定义控件打造史上最简单的侧滑菜单

    侧滑菜单在很多应用中都会见到,最近QQ5.0侧滑还玩了点花样~~对于侧滑菜单,一般大家都会自定义ViewGroup,然后隐藏菜单栏,当手指滑动时,通过Scroller或者不断的改变leftMargin ...

  9. Android绘制自定义控件,Android自定义控件绘制基本图形基础入门

    本文讲述绘制android自定义各种图形效果,为自定义控件的入门篇 相关视频链接: android自定义控件系列 android视频全系列 绘制点–这个控件只需要在布局中引用或者代码中new 即可,下 ...

最新文章

  1. ajax 阻止默认提交,jQuery验证插件:在对ajax调用servlet时,submitHandler不会阻止默认提交-返回false无效...
  2. Asp.net 中 OnClientClick 与 OnClick 的执行顺序
  3. orcal 数据库密码修改(表密码,sys密码,system密码)
  4. 导数,微积分,牛顿运动学制作创意地图
  5. Oracle数据库LOGGINGNOLOGGING模式概述
  6. 11 Python - dict
  7. VS 2010 OpenGL 配置与实例开发
  8. 翰文进度计划软件横道图不显示文字_作为工程新人总是加班?这份工程软件+算量套表直接帮助你,共享...
  9. opencv图像分析与处理(7)- 频率域滤波的基础公式、步骤与C++实现
  10. http协议学习系列(转)
  11. 数据助力防疫,疫情密切接触人员追踪算法赛期待你的加入
  12. Microsoft Office 2010 中的 Office 检测到此文件有问题
  13. vue插件集合17:vue获取国家以及地区的方法
  14. 斯嘉丽约翰逊60张pdf什么时间的?_巩俐入围威尼斯电影节的作品叫什么?巩俐为什么被称为女皇?...
  15. Silverlight MMORPG WebGame游戏设计(五)-----Client的嫁妆
  16. 用上就不会停下的效率利器—Automator
  17. 用计算机弹发如雪,计算器弹音乐谱子
  18. 高一计算机精英班班徽,高一8班班徽设计图案素材大全
  19. 百度网盘_SEARCH
  20. 自动控制原理知识点梳理——6.线性系统的校正方法

热门文章

  1. Bootstrap5 导航栏
  2. 齐向东:人类社会已迈入DT时代,安全必须经营
  3. MIPS 架构的 AR9331芯片 编译链相关内容
  4. 创业周之行——公开课《商业模式的创新》
  5. 学了拓扑学,我猛然领悟到了儿时游戏的真谛……
  6. 一行代码实现Android App指引
  7. 经典算法之顺序查找法
  8. python抢拼多多_python:拼多多订单接口api
  9. cloudreve 使用阿里云 oss 和 cdn 加速
  10. 2018-12 文献阅读:Boosting for Transfer Learning(2007)--迁移学习