ScrollView内嵌ListView或GridView的滑动处理
開發(fā)過程中經(jīng)常會遇到使用scrollview嵌套listview或gridview的情況,這時由于scrollview攔截消費了滑動事件,所以在listview或gridview區(qū)域滑動時該區(qū)域無法滑動,而是scrollview整體滑動?
正確的處理應(yīng)該是當焦點在listview或gridview區(qū)域該區(qū)域滑動,在區(qū)域外則scrollview滑動。
想要解決這個問題,加上如下代碼即可:
listView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View arg0, MotionEvent arg1) {scrollView.requestDisallowInterceptTouchEvent(true); return false;}}下面我們通過源碼來看看requestDisallowInterceptTouchEvent是怎么起作用的?
requestDisallowInterceptTouchEvent函數(shù)實際上是ListView的父類AbsListView的一個函數(shù),這個函數(shù)的源碼如下:
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {if (disallowIntercept) {recycleVelocityTracker();}super.requestDisallowInterceptTouchEvent(disallowIntercept); }可以看到是調(diào)用了父類的同名函數(shù),即ViewGroup的requestDisallowInterceptTouchEvent函數(shù),源碼如下:
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 保存的是二進制值,控制了幾個開關(guān)。
在這里如果disallowIntercept為true的話,則為mGroupFlags添加FLAG_DISALLOW_INTERCEPT標志。同時如果有父view,調(diào)用父view的同名函數(shù)。因為父view也是ViewGroup,所以會一層層調(diào)用直到根布局。
那么FLAG_DISALLOW_INTERCEPT這個標志是如何影響滑動事件的呢?
這個標志使用在ViewGroup的dispatchTouchEvent函數(shù)中,由于代碼較多,我們只截取有關(guān)的部分,如下:
// 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函數(shù)的后續(xù)代碼中intercepted為false則為所有的子view分發(fā)touch事件。
回到之前的問題中,當listview或gridview的區(qū)域touch時,設(shè)置requestDisallowInterceptTouchEvent為true,這樣scrollview的touch就會分發(fā)下去,這樣listview或gridview就可以響應(yīng)滑動事件了。
總結(jié)
以上是生活随笔為你收集整理的ScrollView内嵌ListView或GridView的滑动处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++学习笔记之继承和多态
- 下一篇: 多线程同步中sleep与wait区别