码迷,mamicode.com
首页 > 移动开发 > 详细

安卓触摸事件的分发,处理和消费,以及实现图片的拖动效果

时间:2016-08-13 18:14:43      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:

Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。

View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。

ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。

而dispatchTouchEvent是用来分发触摸事件的,onTouchEvent是用来处理触摸事件的()

 

第一步、触摸事件的产生:

触摸事件由用户触摸屏幕,系统会生成一个MotionEvent触摸事件对象,里面封装了此次动作的所用信息,如时间,位置坐标等。

然后系统会将当前这个触摸事件交给当前的Activity来处理。

第二步、触摸事件的分发与处理:

1、系统将触摸事件交给Activity处理后,会调用Activity的dispatchTouchEvent方法进行事件的分发,Activity首先会找到活动对应的布局中的

父ViewGroup,将触摸事件交给他处理。

2、然后这个ViewGroup又会调用自身的dispatchTouchEvent方法对事件进行分发:

这里又分为两种情况:

第一种是ViewGroup分发事件找到了对应的子View进行处理。

交给它的子孩子View来处理,子孩子View得到事件后,也会调用自身的dispatchTouchEvent方法,但是View的分发则是调用View自身的onTouchEvent或者View设置的

OnTouchListener的onTouch方法对事件进行处理(这里值得一提的是,onTouch方法的优先级是比onTouchEvent方法的优先级高,即先执行onTouch方法)。

在onTouchEvent和onTouch方法中,都需要返回一个布尔类型的值,如果返回true,则说明触摸事件已经消费,不在往下传递,有拦触摸截掉事件的意义,其他子

View就不能响应到这个触摸事件,如果返回false,则说明触摸事件没有被消费,需要传递给其他子View处理。如果所有的子View都不消费这个触摸事件

,最后这个触摸事件就会交由Activity的onTouchEvent处理。

一个完整触摸事件由down、move、up组成。

这里值得我注意的是:Activity分发事件是根据该View是否消费了动作为Down的触摸事件,如果没有消费,则不会向它分发动作为UP和MOVE的触摸事件。

 

第二种是ViewGroup分发事件没找到对应的子View进行处理。

这时事件就由ViewGroup自己处理,它会调用自身的onTouchEvent返回false,说明事件没有找到消费者,触摸事件没有被消费,move,up 动作不需要再往下分发了,

直接调用当前Activity的onTouchEvent(ev)方法处理。

只有View消费了动作为Down的触摸事件,这个View才能响应其他两个动作的触摸事件。

 

 

 

说完安卓事件的分发,接下来我们就来说说图片拖动效果的实现。

第一步、为ImageView设置一个OnTouchListener,并实现其onTouch方法

第二步、拖动逻辑的实现:

1、手指按到imageView上会有一个初始位置(startX,startY)

2、手指在屏幕上移动,移动到一个新的位置(nowX,nowY)

3、计算手指在屏幕的偏移量

dx=nowX-startX

dy=nowY-startY

4、重新计算图片的位置,并控制范围,使图片不会超出边框

 int left=miv_show.getLeft()+dx;
 int top=miv_show.getTop()+dy;
 int right=miv_show.getRight()+dx;
 int buttom=miv_show.getBottom()+dy;
            if(left<=0){
                        right+=-left;
                        left=0;
                    }
                    if(top<=0){
                        buttom+=-top;
                        top=0;
                    }
                    if(right>=mRight){
                        left+=-(right-mRight);
                        right=mRight;
                    }
                    if(buttom>=mButtom){
                        top+=-(buttom-mButtom);
                        buttom=mButtom;
                    }
 

5、通过调用imageView.layout(left,top,right,bottom)立即更新imageView的位置

(left指的是图片左上角的x坐标,top指的是图片左上角的y坐标,right指的是右下角的x坐标,bottom知道是图片右下角的y坐标)

6、重新初始化手指的开始位置(startX=nowX,startY=nowY)

7、当手指离开图片的时候记录当前图片的位置,在下次imageView加载完成后回显。

这里问题就来了,imageView什么时候会加载完成呢?当活动创建调用onCreate方法的时候

imageView是还没有加载完成的,如果在onCreate方法中调用imageView.layout方法是不起作用的

,故我们要设置一个监听,当图片加载完成后回调该监听的方法,在这个方法里面调用layout回显图片的位置,

代码如下:

miv_show.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                System.out.println("view加载完成");
                int lastLeft=sp.getInt("lastLeft", 0);
                int lastTop=sp.getInt("lastTop", 0);
                int lastRight=sp.getInt("lastRight", 0);
                int lastButtom=sp.getInt("lastButtom", 0);
                if(!(lastLeft==0&&lastTop==0&&lastRight==0&&lastButtom==0)){
                    //说明保存了位置
                    miv_show.layout(lastLeft, lastTop, lastRight, lastButtom);
                }
            }
        });

 

 

代码实现如下:

miv_show.setOnTouchListener(new OnTouchListener() {
            private int startX;
            private int startY;
            @Override
            public boolean onTouch(View v, MotionEvent event){
                int mRight=rl.getRight();
                int mButtom=rl.getBottom();
                switch(event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    startX=(int) event.getRawX();
                    startY=(int) event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int nowX=(int) event.getRawX();
                    int nowY=(int) event.getRawY();
                    
                    int dx=nowX-startX;
                    int dy=nowY-startY;
                    
                    int left=miv_show.getLeft()+dx;
                    int top=miv_show.getTop()+dy;
                    int right=miv_show.getRight()+dx;
                    int buttom=miv_show.getBottom()+dy;
                    if(left<=0){
                        right+=-left;
                        left=0;
                    }
                    if(top<=0){
                        buttom+=-top;
                        top=0;
                    }
                    if(right>=mRight){
                        left+=-(right-mRight);
                        right=mRight;
                    }
                    if(buttom>=mButtom){
                        top+=-(buttom-mButtom);
                        buttom=mButtom;
                    }
                    miv_show.layout(left,top, right, buttom);
                    
                    startX=nowX;
                    startY=nowY;
                    
                    
                    break;
                    
                case MotionEvent.ACTION_UP:
                    int lastLeft=miv_show.getLeft();
                    int lastTop=miv_show.getTop();
                    int lastRight=miv_show.getRight();
                    int lastButtom=miv_show.getBottom();
                    Editor editor=sp.edit();
                    editor.putInt("lastLeft", lastLeft);
                    editor.putInt("lastTop", lastTop);
                    editor.putInt("lastRight", lastRight);
                    editor.putInt("lastButtom", lastButtom);
                    editor.commit();
                    break;
                }
                
                //返回true代表事件已经消费了,不需要再往下传递
                //代表所有触摸事件都在这里被消费了,不再往下传递
                return true;
            }
        });

 

安卓触摸事件的分发,处理和消费,以及实现图片的拖动效果

标签:

原文地址:http://www.cnblogs.com/Jsako/p/5768418.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!