今天项目中遇到一个问题:“如何在自定义的View中添加点击事件?”
这应该是属于游戏开发中基础技能吧。
最初想到的,在onTouchEvent当中捕捉用户点击的位置,根据位置的不同来设置不同的标志,然后调用invalidate()方法来执行这个自定义view的刷新
在自定义的View类中,
@Override
public boolean onTouchEvent(MotionEvent event) {
float pointx = event.getX();
float pointy = event.getY();
// RectF(0,0,159,135); so the center point is (80,66)
if(pointy >= 66){
System.out.println("SA: you touch the Number region");
}else if(pointx < 80){
System.out.println("SA: you touch the Mail region");
// refresh view...
haveMail = true;
this.invalidate();
}else{
System.out.println("SA: you touch the Package region");
havePackage = true;
this.invalidate();
}
return super.onTouchEvent(event);
}
结果发现,根本不能及时刷新页面,因为当前view已经处于visible状态了。
对于 invalidate()方法,官方的解释是这样的:
Invalidate the whole view. If the view is visible,onDraw(android.graphics.Canvas)
will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, callpostInvalidate()
.
得到重要参考资料: http://qaohao.iteye.com/blog/478314
看了半天,原来问题出在:
invalidate和postInvalidate方法需要使用android提供的handler,才能实现重绘,而在文档的说明中却只字没提,真是坑爹啊。
具体是在需要重绘的地方调用handler的sendMessage方法发送消息,紧接着会os会触发handler中的handlerMessage方法,在handlerMessage方法中再调用view的invalidate或者postInvalidate方法就能实现重绘。
根据这种思路:简单处理如下:
在MyView类(extends View)中添加:
private Handler updateViewHandler = new Handler(){
然后再在
@Override
public boolean onTouchEvent(MotionEvent event) {
float pointx = event.getX();
float pointy = event.getY();
// RectF(0,0,159,135); so the center point is (80,66)
if(pointy >= 66){
System.out.println("SA: you touch the Number region");
}else if(pointx < 80){
System.out.println("SA: you touch the Mail region");
// refresh view...
haveMail = true;
updateViewHandler.obtainMessage(1).sendToTarget();
}else{
System.out.println("SA: you touch the Package region");
havePackage = true;
}
return super.onTouchEvent(event);
}
问题暂时解决了!!!哈哈
----------------------------------------------------
发现新的问题:
经过测试发现,当页面全是这种自定义组件时候,会发它太敏感了,轻轻一碰就响应事件了。
所以需要重新去响应它的单击事件:
解决方法:使用 GestureDetector类来处理单击事件。
GestureDetector gd = new GestureDetector(context,new LearnGestureListener());
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return gd.onTouchEvent(event);
}
public class LearnGestureListener implements GestureDetector.OnGestureListener {
/* (non-Javadoc)
* @see android.view.GestureDetector.OnGestureListener#onDown(android.view.MotionEvent)
*/
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return true;
}
/* (non-Javadoc)
* @see android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return true;
}
/* (non-Javadoc)
* @see android.view.GestureDetector.OnGestureListener#onLongPress(android.view.MotionEvent)
*/
@Override
public void onLongPress(MotionEvent e) {
}
/* (non-Javadoc)
* @see android.view.GestureDetector.OnGestureListener#onScroll(android.view.MotionEvent, android.view.MotionEvent, float, float)
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return true;
}
/* (non-Javadoc)
* @see android.view.GestureDetector.OnGestureListener#onShowPress(android.view.MotionEvent)
*/
@Override
public void onShowPress(MotionEvent e) {
}
/* (non-Javadoc)
* @see android.view.GestureDetector.OnGestureListener#onSingleTapUp(android.view.MotionEvent)
*/
@Override
public boolean onSingleTapUp(MotionEvent e) {
//这里来放 处理单击事件的代码 ,把以前的代码移步到这里就行了
//.....
return true;
}
}
至此可以收工啦!