该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html
一、知识点讲解
当我们点击系统自带的按钮时,按钮的外观会发生变化。上篇博文中我们画了一个三角形按钮,但点击还不能变色,下面我们就来实现点击变色功能。
从知识体系上我们需要了解以下两个知识点
- 1.如何知道手指点击了我们的控件?
办法是重写View中的onTouchEvent方法。当手指触摸到我们的控件时,系统会通过该方法告诉我们。该方法还有一个类型为MotionEvent的参数,通过该参数我们就能知道当前触摸事件的具体类型,比如按下、移动、抬起等。
我们可以让按钮在正常情况下显示一个较暗的颜色,按下时显示一个较亮的颜色,抬起后再恢复到较暗的颜色。这样就实现了点击变色的效果了。
- 2.如何变色?
View中提供了一个叫invalidate的方法,每次调用该方法,系统都会重新调用onDraw方法来重绘本控件。我们要做的就是在onDraw中判断当前的触摸动作,如果是按下就画一个高亮的三角形,没有触摸或按下抬起后就画一个较暗的三角形。
了解了相关的知识点,下面我们就通过代码来实现。
二、代码实现
以下是当前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; //手触摸屏幕的动作,初始值用一个MotionEvent中没有用到的action值,比如-10,表示还没有任何触屏动作发生。 private int action = -10; //画布的宽 private int width; //画布的高 private int height; //画左三角形的路径 private Path pathLeft = new Path(); //画笔 private Paint paint = new Paint(); //初始化方法是否执行过,确保初始化方法只执行一次。 private boolean initDone = false; //只有一个参数的构造方法是我们在程序中通过“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 右上点 width,0 右下点 width,height 中心点 width/2,height/2 */ /*设置左三角形的路径数据*/ //从画布左上点开始 pathLeft.moveTo(0, 0); //画直线到画布中心点 pathLeft.lineTo(width / 2, height / 2); //再画直线到画布左下点 pathLeft.lineTo(0, height); //自动闭合图形。从最后一个点(左下点)画直线到第一个点(左上点)。 pathLeft.close(); } /** * 通过重写父类的onDraw方法来绘制我们需要的图形 * 该方法会在控件第一次显示时被系统调用,并在之后每次调用invalidate方法后被系统调用。 * * @param canvas 这里的canvas是系统提供的一块矩形画布,我们要做的就是在这块画布上画我们想要的东西。 */ @Override protected void onDraw(Canvas canvas) { if (!initDone) { init(canvas); //确保初始化方法只执行一次 initDone = true; } if (action == MotionEvent.ACTION_DOWN) { //手按压时高亮显示 paint.setColor(leftPressedColor); } else { //没有按或按下抬起后显示较暗的颜色 paint.setColor(leftNormalColor); } //画左三角形 canvas.drawPath(pathLeft, paint); } /** * 如果手触摸到我们的控件,系统会通过该方法告诉我们 * * @param event 系统给我们传递的触摸事件参数 * @return 如果该触摸事件被我们处理了返回true,反之返回false。 */ @Override public boolean onTouchEvent(MotionEvent event) { action = event.getAction(); //ACTION_DOWN表示手按到屏幕,ACTION_UP表示手从屏幕上抬起。我们只处理这两种动作。 if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) { //invalidate方法是告诉系统当前控件需要重绘,系统会再次调用onDraw方法来实现重绘。 invalidate(); return true; } return false; } }
上面注释比较详细,主要就3个方法onDraw(绘图)、onTouchEvent(监听触摸事件)、invalidate(让系统调用onDraw方法实现重绘)。
另外Path对象和Paint对象只要初始化一次就可以了,没必要每次onDraw的时候重新创建,提高程序性能。
三、运行效果
正常时显示暗色:
按下时显示亮色:
测试的时候会发现,点击非三角形区域也会变色,这因为我们还没有对点击的位置做判断,这个会在后面讲解。
先到这里,下文继续。:)