在安卓中,对于事件的处理往往是最麻烦的一部分。
首先,ontouch方法的返回值有true和false两种,如果布局如下:
<span style="font-size:14px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/re" tools:context="com.example.ontouch.MainActivity" > <TextView android:id="@+id/tv" android:background="#ff00ff88" android:layout_width="fill_parent" android:layout_height="200dp" android:text="@string/hello_world" /> </RelativeLayout></span>
Java代码如下:
public class MainActivity extends Activity implements OnTouchListener { private RelativeLayout relativeLayout; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); relativeLayout = (RelativeLayout) findViewById(R.id.re); textView = (TextView) findViewById(R.id.tv); textView.setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("info","down"); break; case MotionEvent.ACTION_MOVE: Log.i("info", "move"); break; case MotionEvent.ACTION_UP: Log.i("info", "up"); break; default: break; } return false; } }
这时如果点击textview,你会发现只会打印"down",原因就是ontouch的返回值。返回值是false,默认的是不拦截当前事件,事件触发后就会传递走,如果改成true,就会发现把事件拦截下来,这是点击移动,就会down,move,move..up。 如果给外层布局和textview都加上监听会:
<pre name="code" class="java">public class MainActivity extends Activity implements OnTouchListener { private RelativeLayout relativeLayout; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); relativeLayout = (RelativeLayout) findViewById(R.id.re); relativeLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("info","re down"); break; case MotionEvent.ACTION_MOVE: Log.i("info", "re move"); break; case MotionEvent.ACTION_UP: Log.i("info", "re up"); break; default: break; } return false; } }); textView = (TextView) findViewById(R.id.tv); textView.setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("info","down"); break; case MotionEvent.ACTION_MOVE: Log.i("info", "move"); break; case MotionEvent.ACTION_UP: Log.i("info", "up"); break; default: break; } return false; } }
先down在re down down re down如果把textview的ontouch改成true
<pre name="code" class="java">public class MainActivity extends Activity implements OnTouchListener { private RelativeLayout relativeLayout; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); relativeLayout = (RelativeLayout) findViewById(R.id.re); relativeLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("info","re down"); break; case MotionEvent.ACTION_MOVE: Log.i("info", "re move"); break; case MotionEvent.ACTION_UP: Log.i("info", "re up"); break; default: break; } return false; } }); textView = (TextView) findViewById(R.id.tv); textView.setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("info","down"); break; case MotionEvent.ACTION_MOVE: Log.i("info", "move"); break; case MotionEvent.ACTION_UP: Log.i("info", "up"); break; default: break; } return true; } }
显示 down move move up..如果都改成ture和上面的一样。现在可以初步得出一个结论了,自控件的ontouch返回值会对父控件产生影响,如果子控件返回的是true,则事件就不会传递到父控件。这样看上去时间的传递像是先从子控件传到父控件,其实并不是这样的,而是事件产生后会先交给父控件,在父控件onInterceptTouchEvent方法中进行分配,大多数控件这个方法会默认的把事件先传递给子控件。如果将其返回值改成true,则事件就会被拦截给父控件。读者有兴趣可以自己试一下。