(android) 自定义View中代码流程问题

具体代码在最下方给出

点击 CHECK 后 就是图二的效果
但是不太明白他这个绘制过程 所以用Log.e调试 还是没看懂
点击包含这个View的activity时 log打印为

不明白为什么是两次onDraw的打印

然后点击CHECK Log.e打印为只发了一部分截图

不明白为什么 又打印了两次onDraw
然后进行sendEmptyMessageDelayed的递归操作不知道有没有说错
在invalidate前后分别设置log
然后每次在handleMessage中判断的时候 为什么 又要打印onDraw还是两次

E/AAA: onDraw
E/AAA: onDraw
E/AAA: invalidate 1 + 0
E/AAA: invalidate 1 + 1
E/AAA: Count=1
public class CheckView extends View { private static final int ANIM_NULL = 0; //动画状态-没有 private static final int ANIM_CHECK = 1; //动画状态-开启 private static final int ANIM_UNCHECK = 2; //动画状态-结束 private Context mContext; // 上下文 private int mWidth, mHeight; // 宽高 private Handler mHandler; // handler private Paint mPaint; private Bitmap okBitmap; private int animCurrentPage = -1; // 当前页码 private int animMaxPage = 13; // 总页数 private int animDuration = 500; // 动画时长 private int animState = ANIM_NULL; // 动画状态 private boolean isCheck = false; // 是否只选中状态 public CheckViewContext context, AttributeSet attrs { supercontext, attrs; Log.e"AAA","构造方法CheckView + 0"; initcontext; Log.e"AAA","构造方法CheckView + 1"; } /** * 初始化 * @param context */ private void initContext context { mContext = context; mPaint = new Paint; mPaint.setColor0xffFF5317;//设置画笔颜色 mPaint.setStylePaint.Style.FILL;//设置画笔风格 mPaint.setAntiAliastrue;//抗锯齿 okBitmap = BitmapFactory.decodeResourcemContext.getResources, R.drawable.checkes;//从资源文件获取Bitmap mHandler = new Handler { @Override public void handleMessageMessage msg { super.handleMessagemsg; if animCurrentPage < animMaxPage && animCurrentPage >= 0 {// 点击之前-1 <13 && -1>=0 点击后 0 < 13 && 0 >=0 Log.e"AAA","invalidate 1 + 0"; invalidate;//重绘 ==> 调用onDraw方法,重绘View中变化的部分 Log.e"AAA","invalidate 1 + 1"; if animState == ANIM_NULL// 动画状态==没有 return; if animState == ANIM_CHECK {//动画状态==开启 animCurrentPage++;//当前页数++ } else if animState == ANIM_UNCHECK {//动画状态==关闭 animCurrentPage--;//当前页数-- } this.sendEmptyMessageDelayed0, animDuration / animMaxPage; Log.e"AAA", "Count=" + animCurrentPage; } else { if isCheck { //isCheck==false animCurrentPage = animMaxPage - 1;// -1 = 13-1 } else { animCurrentPage = -1; } Log.e"AAA","invalidate 2 + 0"; invalidate;//重绘 ondraw中 使用invalidate 非UI线程中 使用 postInvalidate Log.e"AAA","invalidate 2 + 1"; animState = ANIM_NULL;// 动画状态==没有 } } }; } /** * View大小确定 * @param w * @param h * @param oldw * @param oldh */ @Override protected void onSizeChangedint w, int h, int oldw, int oldh { super.onSizeChangedw, h, oldw, oldh; mWidth = w; mHeight = h; Log.e"AAA","onSizeChanged"; } /** * 绘制内容 * @param canvas */ @Override protected void onDrawCanvas canvas { super.onDrawcanvas; Log.e"AAA","onDraw"; // 移动坐标系到画布中央 canvas.translatemWidth / 2, mHeight / 2; // 绘制背景圆形 canvas.drawCircle0, 0, 240, mPaint; // 得出图像边长 int sideLength = okBitmap.getHeight; // 得到图像选区 和 实际绘制位置 Rect src = new RectsideLength * animCurrentPage, 0, sideLength * animCurrentPage + 1, sideLength; Rect dst = new Rect-200, -200, 200, 200; // 绘制 canvas.drawBitmapokBitmap, src, dst, null; } /** * 选择 */ public void check { if animState != ANIM_NULL || isCheck return; animState = ANIM_CHECK; animCurrentPage = 0; Log.e"AAA","check + 1"; mHandler.sendEmptyMessageDelayed0, animDuration / animMaxPage; // 0,500/13 isCheck = true; Log.e"AAA","check + 2"; } /** * 取消选择 */ public void unCheck { if animState != ANIM_NULL || !isCheck return; animState = ANIM_UNCHECK; animCurrentPage = animMaxPage - 1; mHandler.sendEmptyMessageDelayed0, animDuration / animMaxPage; isCheck = false; } /** * 设置动画时长 * @param animDuration */ public void setAnimDurationint animDuration { if animDuration <= 0 return; this.animDuration = animDuration; } /** * 设置背景圆形颜色 * @param color */ public void setBackgroundColorint color{ mPaint.setColorcolor; }
}

这是系统的机制,
绘制几次你不用去关心.
你只应该关心, 什么状态, 应该绘制什么样的图.
用试图使用绘制次数来作精确的参考. 当然, 某些动画可以使用这个onDraw的同时改变状态

首先,我对我的答案并不是特别肯定,甚至希望他是错的

产生这种问题的罪魁祸首是下面的两个BUTTON…Button继承于TextView,然后TextView有这样一个特性,当为他设置Text或者他的Text变化的时候,他会调用父ViewGroup的onLayout方法,这样父ViewGroup会再一次layout,再一次drawChild,从而再次执行onDraw,将button换成ImageView之后,就不会出现题问中的情况了。

至于为什么之前onDraw执行了两次而不是三次就不知道了

发表评论

电子邮件地址不会被公开。 必填项已用*标注