在本例子中,以两个小动物为例,上层的为cat,下层为rabbit这两个小动物为自定义的view,可以根据点击位置实时更改其位置。

首先就是触摸监听事件的设置。
setOnTouchListener中的OnTouch方法。
**注意:**该方法只要有手在屏幕上就会调用,比如按下,滑动,抬起,会时刻调用该函数的。
然后我再说一下,屏幕操作。
屏幕操作:只要你的手在屏幕上都会触发屏幕操作,比如点一下,抬起来,滑动等等。

屏幕操作在framelayout布局中的的传递顺序:
我们知道,framelayout布局是分层的,每层只有一个控件。
假如该framelayout上有多层,每次对屏幕的操作会从顶层开始向下判断,如果其中某一层的onTouch 方法return true,那么下面的层将不会接收到这些操作事件,也就是下面层对应的onTouch方法不会被调用。只有上层的返回false,底层的才能接收到屏幕事件。

了解了这些概念,OnTouch方法就不是问题了。

对于函数:public boolean onTouch(View view, MotionEvent motionEvent)

一些操作:
motionEvent.getAction() //获取状态值,就是上面的action_xx
motionEvent.getX()//获取按下的x坐标
motionEvent.getY()//获取按下的y坐标

可以看到其形参有一个motionEvent,其就是当用户对屏幕进行操作时的操作类型,比如我们按屏幕滑动时,分为三个步骤大概,比如按下一瞬间ACTION_DOWN,按下后的滑动ACTION_MOVE
,以及抬起ACTION_UP。我们可以通过motionEvent.getAction()函数来获得此事件。
再次注意:手只要没离开屏幕,ontouch方法会一直不停的调用!!!
我们可以在ontouch中设置一个switch()对该值进行判断。每次调用该方法都会触发一次判断。
综上所述,要控制framelayout中,多层控件的触摸就变得非常清晰了。

判断有没有按到该图片:利用ACTION_DOWN在按下的一瞬间才会被判断的性质,设置两个变量记录下初始的按压位置,可以通过motionEvent.getX(),motionEvent.getY()两个函数获得该位置。如果该位置与该对象的位置相差较为大的时候,就可以认为该对象没有被点击。可以设置一个全局变量,ismove,若判断成功则ismove=true,判断失败则继续false。

**手指滑动时的判断:**当手指在屏幕上滑动时,motionEvent.getAction()返回的状态为ACTION_MOVE,此时如果通过ismove判断是在对目前图片进行操作,则可以进行一些位置的更新操作,操作完成后根据具体情况判断需不需要将事件向下层传递,本次实验显然不用向下层传递

**抬起时ismove的恢复:**利用ACTION_UP只有抬起时才会被判断到,如果ismove为true则恢复为false;

下面代码为上层控件的触摸判断,下层的类似,可以照着写。注释也很详细

cat.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:   //按下时记录初始位置,若与图片差距过大,则不是点的他,向下传递
                starx = motionEvent.getX();
                stary = motionEvent.getY();
                if (Math.pow((starx - cat.bitmapx), 2) + Math.pow((stary - cat.bitmapy), 2) > 30000)   //没有点击他,直接返回,并传递下去
                {
                    return false;
                }
                ismove=true;   //点击到了该图片,可以移动
            case MotionEvent.ACTION_MOVE:   //当第一次没有按到他,则ismove为false,此时判断该状态时无任何操做
                //点击到猫就停止传递
                if(ismove) {   //如果判断目前正在操作该图片,则为了符合题意更新位置后返回true,不让事件朝着下一层传递
                    cat.bitmapx = motionEvent.getX();    //设置猫显示的X坐标
                    cat.bitmapy = motionEvent.getY();    //Y
                    cat.invalidate();  //重绘cat组件
                    return true;  //停止向下层传递
                }
                break;
            case MotionEvent.ACTION_UP:   //抬起来的时候恢复标志位
                if (ismove)
                {
                    ismove=false;
                    break;
                }
        }
        //传递下去
        return false;
    }
});