美文网首页
自定义表格控件

自定义表格控件

作者: Richile | 来源:发表于2017-04-01 22:44 被阅读0次
    Paste_Image.png

    一、背景
    在做一些测试的时候经常会用到一些数据用于对比,或者显示多个字段在不同情况下的信息,这时用表格显示非常直观,所以就自定义了一个表格控件。

    二、原理
    绘制表格需要画直线,设置单元格的背景颜色,设置单元格中字体大小,设置单元格的高度,根据这些需求,我们可以使用View的onDraw()方法中的canvas快速实现,画直线使用canvas.drawLine(),设置单元格背景颜色可以使用canvas.drawRect()和设置Paint对象的填充颜色,设置字体大小可以使用canvas.drawText()和设置Paint对象的颜色,设置单元格宽度和高度要设置两条线起点之间的距离了。

    三、实现
    demo下载
    3.1 继承View,并且重写3个View类的构造方法,最主要的是带3个参数的构造方法

        public FormView(Context context) {
            this(context, null, 0);
        }
    
        public FormView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public FormView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            Resources resources = context.getResources();
            /* 获取自定义属性,R.styleable.FormView是自定义attr */
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FormView);
    
            /* 获取行和列的资源ID,如果没有就为0 */
            int fieldsResourceId = typedArray.getResourceId(R.styleable.FormView_fields, 0);
            int titlesResourceId = typedArray.getResourceId(R.styleable.FormView_titles, 0);
    
            if(fieldsResourceId != 0) {
                String[] strFieleds = resources.getStringArray(fieldsResourceId);
                for(String field : strFieleds){
                    fields.add(field);
                }
                /* 要增加一行用来显示列标题 */
                line = fields.size() + 1;
            }
    
            if(titlesResourceId != 0) {
                String[] strTitles = resources.getStringArray(titlesResourceId);
                for(String title : strTitles){
                    titles.add(title);
                }
                column = titles.size();
            }
    
            textSize = typedArray.getDimension(R.styleable.FormView_textSize, 20);
    
            /* 初始化列表中每一个单元格的值,都初始化为空 */
            for(int j=0; j<fields.size(); j++){
                ArrayList<String> values = new ArrayList<>();
                /* 第一列是用来显示属性的,所以列表数据列数=titles.size()-1 */
                for(int i=0; i<(titles.size() - 1); i++){
                    values.add("");
                }
                /* 用一个map保存起来 */
                datas.put(fields.get(j), values);
            }
            /* 用完记得回收 */
            typedArray.recycle();
    
        }
    

    R.styleable.FormView来自文件form_view_attr.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="FormView">
            <attr name="titles" format="reference" /><!--显示在第一行的标题-->
            <attr name="fields" format="reference" /><!--显示在第一列的属性-->
            <attr name="textSize" format="dimension" /><!--文字大小-->
        </declare-styleable>
    </resources>
    

    3.2 重写onDraw()方法,开始画表格了

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            /* 取平均高度和宽度 */
            lineHeight = getHeight() / line;
            columeWeight = getWidth() / column;
    
            /* 用于画线的画笔 */
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            paint.setStyle(Paint.Style.FILL);
            /* 设置线的宽度 */
            paint.setStrokeWidth(1);
    
            /* 用于写列表中数据的画笔 */
            Paint paintText = new Paint();
            paintText.setColor(Color.BLACK);
            paintText.setStyle(Paint.Style.FILL);
            paintText.setTextSize(textSize);
    
            /* 获取字体信息 */
            Paint.FontMetricsInt fontMetricsInt = paintText.getFontMetricsInt();
            /* 文字为水平居中*/
            paintText.setTextAlign(Paint.Align.CENTER);
    
            /* 给第一行画上背景颜色 */
            Paint paintTitles = new Paint();
            paintTitles.setColor(0xffd3f0e0);
            canvas.drawRect(new Rect(0, 0, columeWeight*column, lineHeight), paintTitles);
    
            /* 给第一列画上背景颜色 */
            Paint painFields = new Paint();
            painFields.setColor(0xff9fd5b7);
            canvas.drawRect(new Rect(0, lineHeight, columeWeight, lineHeight*line), painFields);
    
            /* 开始画线 */
            for(int i=0; i<line+1; i++){
                /* 画水平线 */
                canvas.drawLine(0, i*lineHeight, columeWeight*column, i*lineHeight, paint);
            }
    
            for(int i=0; i<column+1; i++){
                /* 画竖直线 */
                canvas.drawLine(i*columeWeight, 0, i*columeWeight, line*lineHeight, paint);
            }
    
            /* 填充文字 */
            for(int j=0; j<line; j++) {
                /* 写列的文字 */
                for(int i=0; i<column; i++){
                    Rect targetRect = new Rect(i * columeWeight, j * lineHeight,
                            (i + 1) * columeWeight, (j + 1) * lineHeight);
                    /* 基线 =(目标区域中心点的y值-字体中心的y值) */
                    int baseline = (targetRect.bottom + targetRect.top - fontMetricsInt.bottom - fontMetricsInt.top) / 2;
                    if(j == 0){
                        /* 第一行显示标题 */
                        canvas.drawText(titles.get(i), targetRect.centerX(), baseline, paintText);
                    }else{
                        /* 第一列显示字段 */
                        if(i == 0){
                            canvas.drawText(fields.get(j-1), targetRect.centerX(), baseline, paintText);
                        }
                        /* 其他列显示字段值 */
                        else{
                            try {
                                String str = datas.get(fields.get(j-1)).get(i-1);
                                canvas.drawText((str == null)?"":str, targetRect.centerX(), baseline, paintText);
                            }catch (NullPointerException e){
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    

    3.3 在布局文件中引用

        <com.richile.liu.formview.FormView
            android:layout_width="match_parent"
            android:layout_height="300dp"
            formview:fields="@array/FormViewFields"
            formview:titles="@array/FormViewTitles"
            formview:textSize="12sp"/>
    

    @array/FormViewFields和@array/FormViewTitles来源于文件form_titles_fields_array.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string-array name="FormViewTitles">
            <item>姓名/学科</item>
            <item>语文</item>
            <item>数学</item>
            <item>英语</item>
        </string-array>
    
        <string-array name="FormViewFields" >
            <item>张三</item>
            <item>李四</item>
            <item>王五</item>
            <item>王麻子</item>
        </string-array>
    </resources>
    

    相关文章

      网友评论

          本文标题:自定义表格控件

          本文链接:https://www.haomeiwen.com/subject/sffbottx.html