自定义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;
        }
        
    }


至此可以收工啦!





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值