通过2048学习自定义view(一)

简介

在刚学安卓的时候就尝试着用TextView和LinearLayout写过一个没有动画的2048,现在自学了快半年了,想着写一个2048View来巩固一下之前学的自定义view的知识。(写这篇文章时只完成了开始部分,后面的下一篇文章再补)

在这里强烈推荐 :HenCoder 的自定义view教程

本篇目标

作为自定义view,所有的绘制过程都应该在onDraw()里完成,而且应该满足各种尺寸。效果如下:
这里写图片描述 这里写图片描述

正片

几个重要的属性:(Coordinate是一个存放坐标的类下文给出)

    private int length;//view的长宽
    private int[][] numOfGrid = new int[4][4];//记录每一个格中的数字
    private Coordinate[][] coor;//坐标
    private int padding;//方格之间的距离

首先为了保持整个view一直是正方形,重写onMeasure()方法:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthSize < heightSize) {
            length = widthSize;
        } else {
            length = heightSize;
        }
        setMeasuredDimension(length, length);//使长和宽相等,且为二者最小的那个
        coor = Coordinate.CreateCoordinate(length);//创建坐标,计算各个方格的坐标
        padding = length / 50;
    }

Coordinate类:

public class Coordinate {
    public final int X;
    public final int Y;
    public Coordinate(int y, int x) {
        X = x;
        Y = y;
    }
    //创建16个方块对应的坐标
    public static Coordinate[][] CreateCoordinate(int width) {
        Coordinate[][] res = new Coordinate[4][4];
        int part = width / 4;
        for (int i = 0; i < 4; i++) {   //j是x,i是y
            for (int j = 0; j < 4; j++) {
                res[i][j] = new Coordinate(part * i, part * j);
            }
        }
        return res;
    }
}

之后就是重头戏onDraw()
我的想法是自底向上一层一层地铺。首先画一个大正方形作为背景,然后换颜色画16个小的空白的带圆角的正方形(通过循环画的,用到了之前计算出来的各个方格的坐标),一个空的棋盘就画好了。

 @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.paint));
        //画背景 and 16个格子
        canvas.drawRect(0, 0, length, length, paint);
        paint.setColor(getResources().getColor(R.color.background));
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                canvas.drawRoundRect(coor[i][j].X + padding, coor[i][j].Y + padding,
                        coor[i][j].X + length / 4 - padding, coor[i][j].Y + length / 4 - padding,
                        padding, padding, paint);
            }
        }
        drawGrid(canvas, paint);//根据 numOfGrid 画每一个格子
    }

之后便是画带数字的格子了:
首先随机生成两个数字‘2’,即令numOfGrid数组中的两个随机位置的值等于2(默认为0)。接着循环遍历一遍numOfGrid,当里面的值不为0的时候,在对应的xy坐标的位置画一个正方形(颜色与数字相关,通过color.set.get(2-2048)得到,相关代码请脑补)。

数字是用canvas.drawText()画的,这个方法与其他draw方法不一样,起始坐标是从左下角开始算的(其他的drawXXX()是从左上角开始算的),请务必注意。为了满足所有尺寸都可以,数字的size必须与总长度相关,试了几次感觉size为总长度的1/8最好。

    private void drawGrid(Canvas canvas, Paint paint) {
        int num = 0;
        for (int i = 0; i < 4; i++) {   //j是x,i是y
            for (int j = 0; j < 4; j++) {
                num = numOfGrid[i][j];
                if (num == 0) continue;
                paint.setColor(Color.parseColor(color.set.get(num)));
                canvas.drawRoundRect(coor[i][j].X + padding, coor[i][j].Y + padding,
                        coor[i][j].X + length / 4 - padding, coor[i][j].Y + length / 4 - padding,
                        padding, padding, paint);
                //画数字
                paint.setColor(Color.parseColor(color.set.get(0)));
                paint.setTextSize(length / 8);//这个8是试出来的。。
                canvas.drawText(num + "", coor[i][j].X + length / 11, coor[i][j].Y + length / 6, paint);
            }
        }
    }

剩下的内容下篇再见。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值