写过自定义控件的大家都知道invalidate方法是Android请求重绘的方法。所以会调用到我们自己重写的onDraw方法。
但是在我最近写的一个控件时却没有调用他的onDraw方法。我所重写的控件需求是在触发事件后控件可以展开或是缩回
准确的说 是在我展开他的时候没有触发他的onDraw方法。
测试时的效果是我在点击展开时,没有反应。再次点击触发缩回 却会开到控件直接变为最大 之后再次收回。
public Handler updateHandler = new Handler(){ @Override public void handleMessage(Message msg){ switch (slideFlag){ case HORIZONTAL_SLIDE: AutoMoveX(); if(xcloseTask) closeTask(); break; case VERTICAL_SLIDE: AutoMoveY(); if(ycloseTask) closeTask(); break; case ALL_SLIDE: AutoMoveX(); AutoMoveY(); if(xcloseTask || ycloseTask){ if(ViewShowFlag){ nowViewHeight = maxViewHeight; nowViewWidth = maxViewWidth; }else{ nowViewHeight = minViewHeight; nowViewWidth = minViewWidth; } closeTask(); } break; } invalidate(); } };
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);switch (slideFlag){ case HORIZONTAL_SLIDE: this.setLayoutParams(new LayoutParams(nowViewWidth, maxViewHeight)); break; case VERTICAL_SLIDE: this.setLayoutParams(new LayoutParams(maxViewWidth, nowViewHeight)); break; case ALL_SLIDE: this.setLayoutParams(new LayoutParams(nowViewWidth, nowViewHeight)); break; default: this.setLayoutParams(new LayoutParams(maxViewWidth, maxViewHeight)); }}
之后为了 更好的了解到发生了什么,我吧每次调用重绘的时间间隔加长,吧展开与缩回的控制分离。再次测试后发现
如果我连续触发两次张开的事件就可以正常打开。现在的问题就是为什么只有在打开控件的时候不能触发
这个时候我注意到这个情况是控件从0开始一步一步到完全打开。这就是问题所在:
Android的机制中在绘制前会判断控件是否需要重新绘制的。条件是不透明且大小不为0。
而在我的程序中控件大小改变(告知给系统)是在onDraw方法内。这就导致了控件一直是0的大小不会触发onDraw方法
知道原因后处理就简单了,我们只需要把大小的修改完成在invalidate之前就可以避免了。
switch (slideFlag){ case HORIZONTAL_SLIDE: this.setLayoutParams(new LayoutParams(nowViewWidth, maxViewHeight)); break; case VERTICAL_SLIDE: this.setLayoutParams(new LayoutParams(maxViewWidth, nowViewHeight)); break; case ALL_SLIDE: this.setLayoutParams(new LayoutParams(nowViewWidth, nowViewHeight)); break; default: this.setLayoutParams(new LayoutParams(maxViewWidth, maxViewHeight)); }修改后控件就可以正常运行了。invalidate();
吧大小修改写在onDraw中没有任何问题 但是要保证控件当前的大小不是0并且你没有隐藏他
invalidate();