Android自己定义组件系列【6】——进阶实践(3)

上一篇《Android自己定义组件系列【5】——进阶实践(2)》继续对任老师的《可下拉的PinnedHeaderExpandableListView的实现》进行了分析,这一篇计划中间插一段“知识点”,对Android中的事件分发机制进行解析。细心的朋友可能会发现,打开大牛写的Android项目,里面非常多组件都是自己定义的(这就是为什么界面和体验这么吸引你的原因),可是要灵活的去自己定义组件就必须对手势(也就是各种监听)必须熟悉,能处理好事件之间的关系。

先看一段代码:

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

        button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				Log.i(TAG, "onClick");
			}
		});

        button.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					Log.i(TAG, "onTouch  down");
					break;
				case MotionEvent.ACTION_MOVE:
					Log.i(TAG, "onTouch move");
					break;
				case MotionEvent.ACTION_UP:
					Log.i(TAG, "onTouch up");
					break;
				default:
					break;
				}
				return false;
			}
		});
    }

能够看到onTouch方法会被先调用。然后才调用onClick方法,假设我们将上面onTouch方法的返回值改为true,则onClick方法不会被调用,事件将被onTouch方法消费。

还记得前几篇文章中都会使用一个dispatchTouchEvent的方法吗.

public boolean dispatchTouchEvent(MotionEvent event) {
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}

能够看到在dispatchTouchEvent中调用了onTouch方法,所以会先于onClick方法调用。假设onTouch返回true后dispatcheTouchEvent就会直接返回true则不会再运行其它方法。

在Android系统中每一个ViewGroup子类都具有例如以下三个方法:

public boolean dispatchTouchEvent(MotionEvent event)  :用来分发TouchEvent

public boolean onInterceptTouchEvent(MotionEvent event) :用来拦截TouchEvent

public boolean onTouchEvent(MotionEvent event) :处理TouchEvent

<?xml version="1.0" encoding="utf-8"?

>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <com.kris.touch.widget.TouchView
        android:id="@+id/view_out"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#fff"
        android:gravity="center">
            <com.kris.touch.widget.TouchView
                android:id="@+id/view_mid"
                android:layout_width="300px"
                android:layout_height="400px"
                android:background="#f00"
                android:gravity="center">
            <com.kris.touch.widget.TouchView
                android:id="@+id/view_center"
                android:layout_width="150px"
                android:layout_height="150px"
                android:background="#000"
                android:gravity="center"
                android:clickable="true">
            </com.kris.touch.widget.TouchView>
            </com.kris.touch.widget.TouchView>
    </com.kris.touch.widget.TouchView>
</LinearLayout>

首先触摸事件(ACTION_DOWN)发生后,系统调用Activity的dispatchTouchEvent方法。分发事件。

依据触摸事件的坐标,将此事件传递给out(最外层)的dispatchTouchEvent处理。out则调用onInterceptTouchEvent方法推断事件是否由自己来处理。还是向下传递给子View.假设out不处理该事件会依据事件产生坐标分发给它的直接子View.

图中center组件是可点击的(clickable)组件,表示能处理Touch事件,所以center中的onInterceptTouchEvent方法将事件传递给center

TouchEvent中,假设返回值是true,则说明消耗(消费)了这个事件,不会再向下传递。假设返回值是false,则没有消耗事件,会继续传递下去。假设center中不会处理事件(android:clickable="false")。事件不会被center的onTouchEvent消费,则事件会层层逆向回到activity。

关于事件分发机制就先了解到这里。下一篇接着分析......

时间: 2024-08-07 19:09:25

Android自己定义组件系列【6】——进阶实践(3)的相关文章

Android自己定义组件系列【5】——进阶实践(2)

上一篇<Android自己定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一篇我们来看看ExpandableListView的使用并实现剩下的部分. 原文出处:http://blog.csdn.net/singwhatiwanna/article/details/25546871 一.ExpandableListView的使用方法 ExpandableListView是ListVi

Android自己定义组件系列【4】——自己定义ViewGroup实现双側滑动

在上一篇文章<Android自己定义组件系列[3]--自己定义ViewGroup实现側滑>中实现了仿Facebook和人人网的側滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示意图: 2.核心代码 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth

Android自己定义组件系列【3】——自己定义ViewGroup实现側滑

有关自己定义ViewGroup的文章已经非常多了,我为什么写这篇文章,对于刚開始学习的人或者对自己定义组件比較生疏的朋友尽管能够拿来主义的用了,可是要一步一步的实现和了解当中的过程和原理才干真真脱离别人的代码,举一反三却不easy,非常多博主事实上不愿意一步一步的去写,这样非常耗时,可是假设能对读者有帮助,能从这篇文章中学会自己定义组件就达到我的目的了. 第一步:搭建框架来实现一个3/5和2/5分屏的界面,效果例如以下: 最外层是一个自己定义的ViewGroup布局文件例如以下: package

Android自己定义组件系列【5】——高级实践(1)

在接下来的几篇文章将任老师的博文<您可以下拉PinnedHeaderExpandableListView实现>骤来具体实现.来学习一下大神的代码并记录一下. 原文出处:http://blog.csdn.net/singwhatiwanna/article/details/25546871 先看一下终于效果: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luZ3doYXRpd2FubmE=/font/5a6L5L2T/fontsize/400/f

Android自己定义组件系列【1】——自己定义View及ViewGroup

View类是ViewGroup的父类,ViewGroup具有View的全部特性.ViewGroup主要用来充当View的容器.将当中的View作为自己孩子,并对其进行管理.当然孩子也能够是ViewGroup类型. View类一般用于画图操作,重写它的onDraw方法,但它不能够包括其它组件,没有addView(View view)方法. ViewGroup是一个组件容器,它能够包括不论什么组件,但必须重写onLayout(boolean changed,int l,int t,int r,int

Android自己定义组件系列【8】——面膜文字动画

我们掩盖文字动画Flash中非经货共同体共同,由于Android应用程序开发人员做你想要做这个动画在应用程序中去?本文中,我们看的是如何自己的定义ImageView来实现让一张文字图片实现文字的遮罩闪烁效果,以下先来看看效果吧. (录屏幕延时导致效果看起来不是非常好) 一.实现原理 实现原理是重写View的onCreate方法.获取图片资源后对每一个像素的透明度进行改动来实现,再启动一个线程来循环改变某个区域中的像素透明度. RGBA基础知识:(以下几段介绍文字引用自维基百科) RGBA是代表R

Android自己定义组件系列【2】——Scroller类

在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实现了视图的偏移,可是却没有更好的控制移动过程,移动是瞬间进行的.Scroller类就是为解决问题而设计的. 打开Scroller的源码,能够看到startScroll方法: /** * Start scrolling by providing a starting point and the distance

Android自定义组件系列【7】——进阶实践(4)

上一篇<>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpandableListView的实现>. 一.StickyLayout中的OnGiveUpTouchEventListener接口的作用是什么? public interface OnGiveUpTouchEventListener { public boolean giveUpTouchEvent(MotionEvent event); } 在Sticky

Android自定义组件系列【5】——进阶实践(1)

简介 项目开发中发现问题.解决问题这个过程中会出现很多问题,比如重复出现.某个问题的遗留,这些问题的本质就是设计模式.今天记录设计模式的知识点. 内容 在java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖.关联.聚合.组合.继承.实现.它们的耦合度依次增强. 依赖关系:对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系.关联关系:分为单向关联和双向关联.在java中,单向关联表现为:类A当中使用了