ScrollView内嵌ListView或GridView的滑动处理
開發過程中經常會遇到使用scrollview嵌套listview或gridview的情況,這時由于scrollview攔截消費了滑動事件,所以在listview或gridview區域滑動時該區域無法滑動,而是scrollview整體滑動?
正確的處理應該是當焦點在listview或gridview區域該區域滑動,在區域外則scrollview滑動。
想要解決這個問題,加上如下代碼即可:
listView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View arg0, MotionEvent arg1) {scrollView.requestDisallowInterceptTouchEvent(true); return false;}}下面我們通過源碼來看看requestDisallowInterceptTouchEvent是怎么起作用的?
requestDisallowInterceptTouchEvent函數實際上是ListView的父類AbsListView的一個函數,這個函數的源碼如下:
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {if (disallowIntercept) {recycleVelocityTracker();}super.requestDisallowInterceptTouchEvent(disallowIntercept); }可以看到是調用了父類的同名函數,即ViewGroup的requestDisallowInterceptTouchEvent函數,源碼如下:
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {// We're already in this state, assume our ancestors are tooreturn;}if (disallowIntercept) {mGroupFlags |= FLAG_DISALLOW_INTERCEPT;} else {mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;}// Pass it up to our parentif (mParent != null) {mParent.requestDisallowInterceptTouchEvent(disallowIntercept);} }其中mGroupFlags 保存的是二進制值,控制了幾個開關。
在這里如果disallowIntercept為true的話,則為mGroupFlags添加FLAG_DISALLOW_INTERCEPT標志。同時如果有父view,調用父view的同名函數。因為父view也是ViewGroup,所以會一層層調用直到根布局。
那么FLAG_DISALLOW_INTERCEPT這個標志是如何影響滑動事件的呢?
這個標志使用在ViewGroup的dispatchTouchEvent函數中,由于代碼較多,我們只截取有關的部分,如下:
// Check for interception. final boolean intercepted; if (actionMasked == MotionEvent.ACTION_DOWN|| mFirstTouchTarget != null) {final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;if (!disallowIntercept) {intercepted = onInterceptTouchEvent(ev);ev.setAction(action); // restore action in case it was changed} else {intercepted = false;} } else {// There are no touch targets and this action is not an initial down// so this view group continues to intercept touches.intercepted = true; }當mGroupFlags有FLAG_DISALLOW_INTERCEPT這個標志,則disallowIntercept為true,這時intercepted為false。
在dispatchTouchEvent函數的后續代碼中intercepted為false則為所有的子view分發touch事件。
回到之前的問題中,當listview或gridview的區域touch時,設置requestDisallowInterceptTouchEvent為true,這樣scrollview的touch就會分發下去,這樣listview或gridview就可以響應滑動事件了。
總結
以上是生活随笔為你收集整理的ScrollView内嵌ListView或GridView的滑动处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++学习笔记之继承和多态
- 下一篇: 多线程同步中sleep与wait区别