自定义View如何响应点击事件从而刷新view

今天项目中遇到一个问题:“如何在自定义的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()方法,官方的解释是这样的:

public voidinvalidate()

Since: API Level 1

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().


搜索关键字:“Android之View重绘”

得到重要参考资料: 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(){
public void handleMessage(Message msg){ // run in UI thread.
switch(msg.what){
case 1:
MyView.this.invalidate();
break;
}
}
};



然后再在

@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;
}

}


至此可以收工啦!





你可能感兴趣的:(view)