自定义View之网格布局

网格

最近有个需求是为课表控件TimetableView添加一个网格背景,大致整理了一下该需求的实现思路

  • 自定义一个网格的View
  • 将该View添加到课表的底层布局中

实现效果如下,(不得不吐槽一下这个需求真的是很鸡肋,加上网格反而难看了):

这里写图片描述

本篇博文主要介绍如何自定义底层的网格View,课表控件的实现原理可以参考一起实现一个健壮的课程表控件

网格布局

1.创建自定义View
创建的类需要继承自View基类,如下:

public class SubjectGridView extends View {
    //...
}

2.参数初始化
所谓画网格,其实就是画横线和竖线,只要找到画线的起始坐标即可。要画线,那么肯定需要一支画笔Paint吧,布局的宽度、高度、课程项的宽度、高度、间距用来确定线条的位置,属性如下:

    //画笔、线条颜色
    Paint paint = new Paint();
    int lineColor=Color.GRAY;

    //布局的宽度、高度
    float width,height;

    //课程项的宽度、高度、间距
    int itemHeight;
    int itemWidth;
    int marTop,marLeft;

在构造方法中进行参数的初始化,课程项的宽度、高度、间距采用默认值,需要转化为像素值

/**
     * 使用默认的参数构造网格
     * @param context
     * @param attrs
     */
    public SubjectGridView(Context context,AttributeSet attrs) {
        super(context, attrs);
        LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        setLayoutParams(lp);
        itemHeight=OtherUtils.dip2px(context,55);
        marTop=OtherUtils.dip2px(context,3);
        marLeft=OtherUtils.dip2px(context,3);
    }

布局的宽度、高度在构造函数中是获取不到的,所以应该在onMeasure()中初始化布局的宽度、高度

    //计算参数
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        width=MeasureSpec.getSize(widthMeasureSpec);
        height=MeasureSpec.getSize(heightMeasureSpec);

        //课程项分为了15等分,第一列占一份,其余七列每列占两份
        float each=width/15.0f;
        itemWidth=(int)each*2;
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    }

3.开始绘制

参数初始化完成后,就应该绘制网格线了,绘制过程非常简单,直接看代码吧

@Override
    protected void onDraw(Canvas canvas) {
        paint.setColor(lineColor);
        paint.setStrokeWidth(1);

        //第一条横线
        canvas.drawLine(0,itemHeight+1,width,itemHeight+1,paint);
        //剩余横线
        for(int i=2;i<=12;i++){
            float startY=itemHeight*i+(i-1)*marTop+2;
            float stopY=startY;
            canvas.drawLine(0,startY,width,stopY,paint);
        }

        //竖线
        canvas.drawLine(itemWidth/2,0,itemWidth/2,height,paint);

        for(int j=1;j<=8;j++){
            float startX=itemWidth*j+itemWidth/2-1;
            float stopX=startX;
            canvas.drawLine(startX,0,stopX,height,paint);
        }
    }

小结

这个自定义View不算复杂,顶多算是个自定义View中入门级的小例子了,之后的文章中将涉及到自定义属性的知识

猜你喜欢

转载自blog.csdn.net/lzhuangfei/article/details/80190698