zoukankan      html  css  js  c++  java
  • 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。


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


  • 相关阅读:
    如何用SQL命令修改字段名称
    两个sql server 2000的通用分页存储过程
    Tomcat 6 连接 MS SQL 2005
    log4net 配置与应用
    如何去除Google搜索结果病毒提示
    Windows 2003远程桌面连接数限制
    ntext replace sql
    FCKeditor详细的设置
    SQL Server 自增字段归零等问题
    SQLServer2005数据库还原到SQLServer2000
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468969.html
Copyright © 2011-2022 走看看