android開發步步為營之65:解決ScrollView和ListView觸摸事件onInterceptTouchEvent相互衝突問題,
最近項目裡面有個需求,一個頁面放了一個ScrollView,整個頁面可以向上滾動,然後ScrollView裡面又嵌套了一個ListView,ListView裡面的資料也是可以上下滑動的,理論上ListView被包在ScrollView裡面,TouchEvent肯定是被ScrollView攔截了,那我們可以採取什麼思路呢,我看網上很多做法說是將整個ListView的高度計算出來,感覺這樣很不優雅,如果ListView資料超多,那麼頁面不是超長嗎?其中一個思路就是當我們滑動ListView地區的時候,ScrollView不要響應OnTouch事件。觸摸ListView地區外的點才可以滑動整個頁面。給出核心代碼。
自訂ScrollView
package com.figo.study.view;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.ScrollView;public class MyScrollView extends ScrollView { private OnScrollListener onScrollListener; private List<View> views = new ArrayList<View>(); public MyScrollView(Context context) { this(context, null); } public MyScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (onScrollListener != null) { onScrollListener.onScroll(t); } } public interface OnScrollListener { public void onScroll(int scrollY); } //是否攔截觸摸事件 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (views != null && checkAllViews(views, ev)) { return false; } return super.onInterceptTouchEvent(ev); } public void addUnTouchableView(View view) { try { if (!views.contains(view)) { views.add(view); } } catch (Exception e) { if (e != null) { e.printStackTrace(); } } } public void delUnTouchableView(View view) { try { if (views.contains(view)) { views.remove(view); } } catch (Exception e) { if (e != null) { e.printStackTrace(); } } } public void delAllUnTouchableView() { try { if (views.size() > 0) { views.clear(); } } catch (Exception e) { if (e != null) { e.printStackTrace(); } } } private boolean checkAllViews(List<View> views, MotionEvent event) { for (View view : views) { if (checkInLvArea(view, event)) { return true; } } return false; } private boolean checkInLvArea(View v, MotionEvent event) { try { float x = event.getRawX(); float y = event.getRawY(); int[] locate = new int[2]; v.getLocationOnScreen(locate); int l = locate[0]; int r = l + v.getWidth(); int t = locate[1]; int b = t + v.getHeight(); if (l < x && x < r && t < y && y < b) { return true; } return false; } catch (Exception e) { if (e != null) { e.printStackTrace(); } } return false; }}
滑動ScrollView後,顯示新的頁面head的技巧:
MyScrollView scrollView = (MyScrollView) findViewById(R.id.scrollView); scrollView.setOnScrollListener(new OnScrollListener() { @Override public void onScroll(int scrollY) { int top = Math.max(scrollY, mLayoutHead.getTop()/2); mLayoutHeadNew.layout(0, top, mLayoutHeadNew.getWidth(), top + mLayoutHeadNew.getHeight()); if(scrollY>=canScrollHeight) {// mLayoutHead.setVisibility(View.GONE); mLayoutHeadNew.setVisibility(View.VISIBLE); }else {// mLayoutHead.setVisibility(View.VISIBLE); mLayoutHeadNew.setVisibility(View.GONE); } } });