该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html
一、如何判断点击的是哪个方向键按钮
在上篇教程中我们实现了左边的三角形按钮效果,本篇教程我们将左、上、右、下四个三角形按钮都一起实现了。
能做出一个来,另外三个应该不难了吧?但实际并非怎么简单哦。
首先我们来解决一下上节课遗留的一个问题,如何判断当前手指点击的是哪个三角形按钮?
这个需要用解析几何大法来解决。
假设我们的控件是边长为1的正方形,建立平面直角坐标系(注意:计算机中坐标系原点在左上角哦),如下图:
正方形的对角线将控件分成了4个三角形区域,也就是我们的4个方向键按钮。
据上图可知:
左上角到右下角对角线的方程为y=x;
y>x的区域包含左和下三角形
y<x的区域包含右和上三角形
右上角到左下角的对角线方程为y=-x+1;
y>1-x的区域包含右和下三角形
y<1-x的区域包含左和上三角形
综上可得:
y>x 且 y<1-x 表示左三角
y<x 且 y<1-x 表示上三角
y<x 且 y>1-x 表示右三角
y>x 且 y>1-x 表示下三角
以上是按照边长为1的正方形得到的结论,但实际中,我们的控件不一定是正方形,边长也不是1,而是一个不确定的矩形,这该怎么办呢?
这就需要经过一定的转换,将普通的矩形转换为边长为1的正方形。
这个转变也简单,如下:
设画布上被触摸到的点的坐标为(x,y),则:
float relativeX = x / width;//0<=relativeX<=1
float relativeY = y / height;//0<=relativeY<=1
我们将画布上被触摸的点的横纵坐标分别除以画布的宽和高,这样就得到了一个相对坐标,而这个相对坐标的取值一定在0到1之间。这样就相当于把一个不确定的矩形简化成了一个边长为1的正方形处理。
二、程序代码
有了上面的了解,下面就可以写代码了。由于有4个三角形按钮,而每个按钮又有两种状态,代码会稍微长点。但每个按钮的逻辑都是一样的,都是按哪个那个高亮,不按时都恢复正常状态。代码中的注释比较详细,相信大家如果看了前面的教程内容,看这个应该问题不大。唯一需要注意的是每次调用invalidate方法重绘界面时,是需要对整个画布都重绘的,而不能只重绘一个三角形。
这里我们需要先引入一个表示方向的枚举:Direction
package net.chengyujia.happysnake;
/**
* 用来表示方向的枚举
* Created by ChengYuJia on 2016/8/21.
*/
public enum Direction {
//none表示没有方向键按下
none,
//左
left,
//上
up,
//右
right,
//下
down;
}
下面是当前DirectionKeys的完整代码:
package net.chengyujia.happysnake;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* 屏幕上的虚拟方向键
* Created by ChengYuJia on 2016/8/19.
*/
public class DirectionKeys extends View {
//左三角形按压时的颜色(较亮)
private int leftPressedColor = 0xFFFF0000;
//左三角形正常显示的颜色(较暗)
private int leftNormalColor = 0xFFAA0000;
//上三角形按压时的颜色(较亮)
private int upPressedColor = 0xFF00FF00;
//上三角形正常显示的颜色(较暗)
private int upNormalColor = 0xFF00AA00;
//右三角形按压时的颜色(较亮)
private int rightPressedColor = 0xFF0000FF;
//右三角形正常显示的颜色(较暗)
private int rightNormalColor = 0xFF0000AA;
//下三角形按压时的颜色(较亮)
private int downPressedColor = 0xFFFFFF00;
//下三角形正常显示的颜色(较暗)
private int downNormalColor = 0xFFAAAA00;
//画笔
private Paint paint = new Paint();
//画左三角形的路径
private Path pathLeft = new Path();
//画上三角形的路径
private Path pathUp = new Path();
//画右三角形的路径
private Path pathRight = new Path();
//画下三角形的路径
private Path pathDown = new Path();
//画布的宽
private int width;
//画布的高
private int height;
//初始化方法是否执行过,确保初始化方法只执行一次。
private boolean initDone = false;
//记录当前哪个方向键被按下
private Direction currentDirection = Direction.none;
//只有一个参数的构造方法是我们在程序中通过“new”关键字创建实例时调用。
public DirectionKeys(Context context) {
super(context);
}
//有两个参数的构造方法是系统在XML布局文件中创建实例时调用。
public DirectionKeys(Context context, AttributeSet attrs) {
super(context, attrs);
}
//初始化方法
private void init(Canvas canvas) {
/*获取画布的长和宽*/
width = canvas.getWidth();
height = canvas.getHeight();
/*
(小提示:在计算机中一般都是将左上角作为坐标原点的)
画布上四个顶点和中心点的坐标如下:
左上点 0,0
左下点 0,height