See the content of load_data_waiting_layout.xml, RelativeLayout, ProgressBar, TextView, and other controls. After clickable is set to true, the ProgramListFragment sliding event is no longer supported. If you do not set the clickable attribute or set it to false, the ProgramListFragment sliding event is supported.
programListFragment.getView().setOnTouchListener(programTouchListener);
Is the onTouch method of programListFragment. getView () not executed after the clickable attribute is set to true?
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_waiting" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" android:background="#00ffff" > <ProgressBar android:id="@+id/waiting" style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:clickable="true" android:background="#ff00ff" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/waiting" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:text="@string/loading_data" android:textSize="22sp" android:clickable="true" android:background="#0000ff" /></RelativeLayout>
Setting the clickable attribute in an xml file is equivalent to calling the setClickable method in a program. Use the setClickable method of android. view. View to analyze the impact of the clickable attribute on the touch event.
Void setClickable (boolean clickable)
public void setClickable(boolean clickable) { setFlags(clickable ? CLICKABLE : 0, CLICKABLE);}
Void setFlags (int flags, int mask)
/** * Set flags controlling behavior of this view. * * @param flags Constant indicating the value which should be set * @param mask Constant indicating the bit range that should be changed */void setFlags(int flags, int mask) { int old = mViewFlags; mViewFlags = (mViewFlags & ~mask) | (flags & mask); int changed = mViewFlags ^ old; if (changed == 0) { return; } int privateFlags = mPrivateFlags; /* Check if the FOCUSABLE bit has changed */ if (((changed & FOCUSABLE_MASK) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) { if (((old & FOCUSABLE_MASK) == FOCUSABLE) && ((privateFlags & PFLAG_FOCUSED) != 0)) { /* Give up focus if we are no longer focusable */ clearFocus(); } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) && ((privateFlags & PFLAG_FOCUSED) == 0)) { /* * Tell the view system that we are now available to take focus * if no one else already has it. */ if (mParent != null) mParent.focusableViewAvailable(this); } if (AccessibilityManager.getInstance(mContext).isEnabled()) { notifyAccessibilityStateChanged(); } } if ((flags & VISIBILITY_MASK) == VISIBLE) { if ((changed & VISIBILITY_MASK) != 0) { /* * If this view is becoming visible, invalidate it in case it changed while * it was not visible. Marking it drawn ensures that the invalidation will * go through. */ mPrivateFlags |= PFLAG_DRAWN; invalidate(true); needGlobalAttributesUpdate(true); // a view becoming visible is worth notifying the parent // about in case nothing has focus. even if this specific view // isn't focusable, it may contain something that is, so let // the root view try to give this focus if nothing else does. if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { mParent.focusableViewAvailable(this); } } } /* Check if the GONE bit has changed */ if ((changed & GONE) != 0) { needGlobalAttributesUpdate(false); requestLayout(); if (((mViewFlags & VISIBILITY_MASK) == GONE)) { if (hasFocus()) clearFocus(); clearAccessibilityFocus(); destroyDrawingCache(); if (mParent instanceof View) { // GONE views noop invalidation, so invalidate the parent ((View) mParent).invalidate(true); } // Mark the view drawn to ensure that it gets invalidated properly the next // time it is visible and gets invalidated mPrivateFlags |= PFLAG_DRAWN; } if (mAttachInfo != null) { mAttachInfo.mViewVisibilityChanged = true; } } /* Check if the VISIBLE bit has changed */ if ((changed & INVISIBLE) != 0) { needGlobalAttributesUpdate(false); /* * If this view is becoming invisible, set the DRAWN flag so that * the next invalidate() will not be skipped. */ mPrivateFlags |= PFLAG_DRAWN; if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) { // root view becoming invisible shouldn't clear focus and accessibility focus if (getRootView() != this) { clearFocus(); clearAccessibilityFocus(); } } if (mAttachInfo != null) { mAttachInfo.mViewVisibilityChanged = true; } } if ((changed & VISIBILITY_MASK) != 0) { if (mParent instanceof ViewGroup) { ((ViewGroup) mParent).onChildVisibilityChanged(this, (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK)); ((View) mParent).invalidate(true); } else if (mParent != null) { mParent.invalidateChild(this, null); } dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK)); } if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { destroyDrawingCache(); } if ((changed & DRAWING_CACHE_ENABLED) != 0) { destroyDrawingCache(); mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; invalidateParentCaches(); } if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { destroyDrawingCache(); mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; } if ((changed & DRAW_MASK) != 0) { if ((mViewFlags & WILL_NOT_DRAW) != 0) { if (mBackground != null) { mPrivateFlags &= ~PFLAG_SKIP_DRAW; mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND; } else { mPrivateFlags |= PFLAG_SKIP_DRAW; } } else { mPrivateFlags &= ~PFLAG_SKIP_DRAW; } requestLayout(); invalidate(true); } if ((changed & KEEP_SCREEN_ON) != 0) { if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { mParent.recomputeViewAttributes(this); } } if (AccessibilityManager.getInstance(mContext).isEnabled() && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) { notifyAccessibilityStateChanged(); }}
Extended TextView, override onTouchEvent method, and return false.
public class MyTextView extends TextView { public MyTextView(Context context) { super(context); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); } public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); return false; }}
Debugging result: if false is returned, the TextView parameter is invalid.
Trace touch event execution
11-08 15:22:57.524: D/MyLinearLayout(22210): ++onInterceptTouchEvent++11-08 15:22:57.524: D/MyLinearLayout(22210): result:false11-08 15:22:57.524: D/MyRelativeLayout(22210): ++onInterceptTouchEvent++11-08 15:22:57.524: D/MyRelativeLayout(22210): result:false11-08 15:22:57.524: D/MyLinearLayout(22210): ++onInterceptTouchEvent++11-08 15:22:57.534: D/MyLinearLayout(22210): result:false11-08 15:22:57.534: D/MyTextView(22210): ++onTouchEvent++11-08 15:22:57.534: D/MyTextView(22210): result:true
The above log shows that MyText is in the ViewTree level 4th, level 1, 2, and level 3 are MyLinearLayout, MyRelativeLayout, and MyLinearLayout. when a touch event occurs, the onInterceptTouchEvent method of level 1, 2, and 3 is called for processing. If onInterceptTouchEvent returns false, the onTouchEvent of the lower-level View or the onInterceptTouchEvent of the lower-level ViewGoup will be called for processing.
11-08 15:52:56.374: D/MyLinearLayout(23972): ++onInterceptTouchEvent++11-08 15:52:56.374: D/MyLinearLayout(23972): result:false11-08 15:52:56.374: D/MyRelativeLayout(23972): ++onInterceptTouchEvent++11-08 15:52:56.374: D/MyRelativeLayout(23972): result:false11-08 15:52:56.374: D/MyLinearLayout(23972): ++onInterceptTouchEvent++11-08 15:52:56.374: D/MyLinearLayout(23972): result:false11-08 15:52:56.374: D/MyTextView(23972): ++onTouchEvent++11-08 15:52:56.374: D/MyTextView(23972): result:true11-08 15:52:56.374: D/MyTextView(23972): ++dispatchTouchEvent++11-08 15:52:56.374: D/MyTextView(23972): result:true11-08 15:52:56.374: D/MyLinearLayout(23972): ++dispatchTouchEvent++11-08 15:52:56.374: D/MyLinearLayout(23972): result:true11-08 15:52:56.374: D/MyRelativeLayout(23972): ++dispatchTouchEvent++11-08 15:52:56.374: D/MyRelativeLayout(23972): result:true11-08 15:52:56.374: D/MyLinearLayout(23972): ++dispatchTouchEvent++11-08 15:52:56.374: D/MyLinearLayout(23972): result:true
The preceding log shows that the onInterceptTouchEvent method of level 1, 2, and 3 and the onTouchEvent method of level 4th are called sequentially. Then, the dispatchTouchEvent method of Level 4, 3, and 2 is called sequentially.
Call toString () to identify the current View
11-08 16:08:38.424: D/WatchTvFragment(25580): programListFragment.getView():android.support.v4.app.NoSaveStateFrameLayout{421799f0 V.E..... ........ 427,0-986,703 #7f070077 app:id/program_list_fragment}11-08 16:09:18.994: D/MyLinearLayout(25580): ++onInterceptTouchEvent++11-08 16:09:18.994: D/MyLinearLayout(25580): com.tvie.ivideo.pad.live.MyLinearLayout{42188478 V.E..... ........ 0,0-559,703}11-08 16:09:18.994: D/MyLinearLayout(25580): result:false11-08 16:09:18.994: D/MyRelativeLayout(25580): ++onInterceptTouchEvent++11-08 16:09:18.994: D/MyRelativeLayout(25580): com.tvie.ivideo.pad.live.MyRelativeLayout{4216cfd0 V.E..... ........ 0,0-559,43}11-08 16:09:18.994: D/MyRelativeLayout(25580): result:false11-08 16:09:18.994: D/MyLinearLayout(25580): ++onInterceptTouchEvent++11-08 16:09:18.994: D/MyLinearLayout(25580): com.tvie.ivideo.pad.live.MyLinearLayout{4216d1f8 V.E..... ........ 0,0-524,43}11-08 16:09:18.994: D/MyLinearLayout(25580): result:false11-08 16:09:18.994: D/MyTextView(25580): ++onTouchEvent++11-08 16:09:18.994: D/MyTextView(25580): com.tvie.ivideo.pad.live.MyTextView{4216e750 V.ED..C. ...P.... 321,7-412,36 #7f07014b app:id/tomorrow}11-08 16:09:18.994: D/MyTextView(25580): result:true11-08 16:09:18.994: D/MyTextView(25580): ++dispatchTouchEvent++11-08 16:09:18.994: D/MyTextView(25580): com.tvie.ivideo.pad.live.MyTextView{4216e750 V.ED..C. ...P.... 321,7-412,36 #7f07014b app:id/tomorrow}11-08 16:09:18.994: D/MyTextView(25580): result:true11-08 16:09:18.994: D/MyLinearLayout(25580): ++dispatchTouchEvent++11-08 16:09:18.994: D/MyLinearLayout(25580): com.tvie.ivideo.pad.live.MyLinearLayout{4216d1f8 V.E..... ........ 0,0-524,43}11-08 16:09:18.994: D/MyLinearLayout(25580): result:true11-08 16:09:18.994: D/MyRelativeLayout(25580): ++dispatchTouchEvent++11-08 16:09:18.994: D/MyRelativeLayout(25580): com.tvie.ivideo.pad.live.MyRelativeLayout{4216cfd0 V.E..... ........ 0,0-559,43}11-08 16:09:18.994: D/MyRelativeLayout(25580): result:true11-08 16:09:18.994: D/MyLinearLayout(25580): ++dispatchTouchEvent++11-08 16:09:18.994: D/MyLinearLayout(25580): com.tvie.ivideo.pad.live.MyLinearLayout{42188478 V.E..... ........ 0,0-559,703}11-08 16:09:18.994: D/MyLinearLayout(25580): result:true
The above log shows:
The root layout of programListFragment. getView () and R. layout. watchtv_program_list is not the same view.
11-08 17:02:35.134: D/MyLinearLayout(25580): ++onInterceptTouchEvent++11-08 17:02:35.134: D/MyLinearLayout(25580): result:false11-08 17:02:35.134: D/MyRelativeLayout(25580): ++onInterceptTouchEvent++11-08 17:02:35.134: D/MyRelativeLayout(25580): result:false11-08 17:02:35.134: D/MyLinearLayout(25580): ++onInterceptTouchEvent++11-08 17:02:35.134: D/MyLinearLayout(25580): result:false11-08 17:02:35.134: D/MyLinearLayout(25580): ++onTouchEvent++11-08 17:02:35.134: D/MyLinearLayout(25580): result:false11-08 17:02:35.134: D/MyLinearLayout(25580): ++dispatchTouchEvent++11-08 17:02:35.134: D/MyLinearLayout(25580): result:false11-08 17:02:35.134: D/MyRelativeLayout(25580): ++onTouchEvent++11-08 17:02:35.134: D/MyRelativeLayout(25580): result:false11-08 17:02:35.134: D/MyRelativeLayout(25580): ++dispatchTouchEvent++11-08 17:02:35.134: D/MyRelativeLayout(25580): result:false11-08 17:02:35.134: D/MyLinearLayout(25580): ++onTouchEvent++11-08 17:02:35.134: D/MyLinearLayout(25580): result:false11-08 17:02:35.134: D/MyLinearLayout(25580): ++dispatchTouchEvent++11-08 17:02:35.134: D/MyLinearLayout(25580): result:false11-08 17:02:35.134: D/WatchTvFragment(25580): ++programTouchListener.onTouch++
When the touch event occurs in MyLinearLayout outside MyTextView, the fragment can slide left and right. View logs: MyLinearLayout outside MyTextView returns false in the dispatchTouchEvent method. Previously, MyTextView returned true in the dispatchTouchEvent method, so that all the xxxLayout statements returned true.
If the returned value is false in the MyLinearLayout. dispatchTouchEvent method, the click Event of the lower-level MyTextView is invalid. It indicates that the return value of dispatchTouchEvent plays an important role.
11-08 17:27:55.144: D/MyLinearLayout(32017): ++onInterceptTouchEvent++11-08 17:27:55.144: D/MyLinearLayout(32017): result:false11-08 17:27:55.144: D/MyRelativeLayout(32017): ++onInterceptTouchEvent++11-08 17:27:55.144: D/MyRelativeLayout(32017): result:false11-08 17:27:55.144: D/MyLinearLayout(32017): ++onInterceptTouchEvent++11-08 17:27:55.144: D/MyLinearLayout(32017): result:false11-08 17:27:55.144: D/MyTextView(32017): ++onTouchEvent++11-08 17:27:55.144: D/MyTextView(32017): result:true11-08 17:27:55.144: D/MyTextView(32017): ++dispatchTouchEvent++11-08 17:27:55.144: D/MyTextView(32017): result:false11-08 17:27:55.154: D/MyLinearLayout(32017): ++onTouchEvent++11-08 17:27:55.154: D/MyLinearLayout(32017): result:false11-08 17:27:55.154: D/MyLinearLayout(32017): ++dispatchTouchEvent++11-08 17:27:55.154: D/MyLinearLayout(32017): result:false11-08 17:27:55.154: D/MyRelativeLayout(32017): ++onTouchEvent++11-08 17:27:55.154: D/MyRelativeLayout(32017): result:false11-08 17:27:55.154: D/MyRelativeLayout(32017): ++dispatchTouchEvent++11-08 17:27:55.154: D/MyRelativeLayout(32017): result:false11-08 17:27:55.154: D/MyLinearLayout(32017): ++onTouchEvent++11-08 17:27:55.154: D/MyLinearLayout(32017): result:false11-08 17:27:55.154: D/MyLinearLayout(32017): ++dispatchTouchEvent++11-08 17:27:55.154: D/MyLinearLayout(32017): result:false11-08 17:27:55.154: D/WatchTvFragment(32017): ++programTouchListener.onTouch++
Row 8th: The dispatchTouchEvent method of MyTextView of level 4th returns false. Next, call the onTouchEvent and dispatchTouchEvent methods at level 3, 2, and 1. In the preceding log, the dispatchTouchEvent method returns true, and the onTouchEvent method will not be called.
Void android. view. View. setOnClickListener (OnClickListener l)
Register a callback to be invoked when this view is clicked. If this view is not clickable, it becomes clickable.
Parameters:
LThe callback that will run
public void setOnClickListener(OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l;}
When setOnClickListener is called, if clickable is set to false, it is set to true.
Reference link:
1. http://www.aslibra.com/blog/post/android_GestureDetector.php
2. http://blog.csdn.net/lyb2518/article/details/7889169