美文网首页Android开发Android开发Android开发经验谈
自定义View(3)-实例分析View与ViewGroup的触摸

自定义View(3)-实例分析View与ViewGroup的触摸

作者: 秦子帅 | 来源:发表于2018-11-10 14:15 被阅读4次

实例分析View与ViewGroup的触摸事件传递机制

今天通过一个demo来分析一下,主要是自定义一个Button和layout,通过点击按钮来测试事件的传递效果。

1.首先建立一个类RTButton继承Button;重写它的dispatchTouchEvent,onTouchEvent方法。分别在DOWN,MOVE,UP时打印句子,方便运行时查看。如下代码:

public class RtButton extends Button{


    public RtButton(Context context) {
        super(context);
    }

    public RtButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RtButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    /**  分发事件
     * @param
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("RtButton---dispatchTouchEvent----DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("RtButton---dispatchTouchEvent----MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("RtButton---dispatchTouchEvent----UP");
                break;
            default:
                break;
        }
        // 获取了MotionEvent各个事件状态
        return super.dispatchTouchEvent(event);
    }
    /**  处理事件
     * @param
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("RtButton----onTouchEvent----DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("RtButton----onTouchEvent----MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("RtButton----onTouchEvent----UP");
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

}

2.首先建立一个类RtLayout继承LinearLayout;重写它的dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent方法。分别在DOWN,MOVE,UP时打印句子,方便运行时查看。如下代码:

public class RtLayout extends LinearLayout {
    public RtLayout(Context context) {
        super(context);
    }

    public RtLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public RtLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    /**  分发事件
     * @param
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("RTLayout---dispatchTouchEvent---DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("RTLayout---dispatchTouchEvent---MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("RTLayout---dispatchTouchEvent---UP");
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
    /**  处理事件
     * @param
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("RtLayout---onInterceptTouchEvent---DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("RtLayout---onInterceptTouchEvent---MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("RtLayout---onInterceptTouchEvent---UP");
                break;
            default:
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("RtLayout---onTouchEvent---DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("RtLayout---onTouchEvent---MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("RtLayout---onTouchEvent---UP");
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);

}

}

3.在布局文件中放入自定义控件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
<com.qzs.event.RtLayout
    android:layout_width="match_parent"
    android:background="@color/colorAccent"
    android:gravity="center"
    android:layout_height="match_parent">

    <com.qzs.event.RtButton
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="自定义Button"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</com.qzs.event.RtLayout>

</android.support.constraint.ConstraintLayout>

4.在MainActivity中添加按钮的点击事件,再添加按钮的触摸事件,并重写Activity的dispatchTouchEvent,onTouchEvent事件

public class MainActivity extends AppCompatActivity {

    private RtButton btn;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn=findViewById(R.id.btn);

        btn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        System.out.println("onTouch----DOWN");
                        break;
                    case MotionEvent.ACTION_MOVE:
                        System.out.println("onTouch----MOVE");
                        break;
                    case MotionEvent.ACTION_UP:
                        System.out.println("onTouch----UP");
                        break;
                    default:
                        break;
                }

                return false;
            }
        });
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                System.out.println("<-onClick->");
            }
        });



    }

    // Activity的dispatchTouchEvent的事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("Activity----dispatchTouchEvent----DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("Activity----dispatchTouchEvent----MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("Activity----dispatchTouchEvent----UP");
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    // 对Activity的ontouchevent的方法事件
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("Activity----ontouchevent----DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("Activity----ontouchevent----MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("Activity----ontouchevent----UP");
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
}

5.测试
都是默认的状态,我们直接运行一下,结果如下:

从运行结果我们会运行顺序如下:

Activity----dispatchTouchEvent----DOWN
RTLayout---dispatchTouchEvent---DOWN
RtLayout---onInterceptTouchEvent---DOWN
RtButton---dispatchTouchEvent----DOWN
onTouch----DOWN
RtButton----onTouchEvent----DOWN
Activity----dispatchTouchEvent----UP
RTLayout---dispatchTouchEvent---UP
RtLayout---onInterceptTouchEvent---UP
RtButton---dispatchTouchEvent----UP
onTouch----UP
RtButton----onTouchEvent----UP
<-onClick->

由此我们印证了触摸事件是由外到内传递的。
大家是不是对onTouch----DOWN比较疑惑,ontouch事件为什么早于onTouchEvent事件?其实我们上一节的View源码分析就已经讲到了,截图如下:

从源码中我们发现onTouch早于onTouchEvent

现在我们把RtLayout中的dispatchTouchEvent直接消费掉,也就是返回true
运行后:


说明了事件只传递到了RtLayout。大家也可以自己去试一试,这样才能深入的了解。大家如果有不懂的可以问我。

相关文章

网友评论

    本文标题:自定义View(3)-实例分析View与ViewGroup的触摸

    本文链接:https://www.haomeiwen.com/subject/dvpzxqtx.html