ScrollView嵌套ListView滑动冲突解决

        在一些特殊界面的设计里面,使用ScrollView嵌套ListView的情况还是比较常见的。由于ScrollView和ListView都有对滑动事件的监听和处理,所以两者嵌套肯定会存在滑动冲突的问题。我们知道Android事件是根据“冒泡”机制层层传递的,既从父View到子View层层处理,因此我们思考从ListView的“View父”ScrollView进行冲突处理。

        从网上查阅资料和对ScrollView的源码分析,找到了ViewGroup里面有个方法requestDisallowInterceptTouchEvent,通过此方法可以阻止父层的View截获touch事件。也就是当我们设置ScrollView.requestDisallowInterceptTouchEvent(true),ScrollView不会拦截touch事件,并将其交由ListView处理,这正是我们想要的。

        关键代码在下面......


public class ScrollViewInnerListView extends ListView{
    ……
    private float mPrevMotionY;
    
    private ScrollView scrollView;
    public void setScrollView(ScrollView scrollView){
		this.scrollView = scrollView;
	}
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
	    switch (ev.getAction()) {
			case MotionEvent.ACTION_DOWN:
			    //交由子ListView处理,父scrollview不能滑动
				setScrollAble(true); 
			case MotionEvent.ACTION_MOVE:
				break;
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_CANCEL:
			    //由父ScrollView处理onTouch
				setScrollAble(false);
				break;
			default:
				break;
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	/**
	 * 处理父scrollview的requestDisallowInterceptTouchEvent()
	 *
	 * @param flag
	 */
	private void setScrollAble(boolean flag) {
		if(scrollView != null){
			scrollView.requestDisallowInterceptTouchEvent(flag);
		}
	}
	
	/**
	 * 当ListView滑动到最顶部时,交回由ScrollView滑动;
	 * 当ListView滑动到最底部时,交回由ScrollView滑动。
	 *
	 * @param ev
	 */
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {

		final int action = MotionEventCompat.getActionMasked(ev);
		final float y = ev.getY();

		if (action == MotionEvent.ACTION_DOWN) {
			mPrevMotionY = y;
		} else if (action == MotionEvent.ACTION_MOVE) {
			float dy = y - mPrevMotionY;
			mPrevMotionY = y;
			if(dy > 0){
				View firstChild = this.getChildAt(0);
				if(firstChild == null || (firstChild != null && (this.getFirstVisiblePosition() == 0 && firstChild.getTop() == 0))){
					setScrollAble(true);
				}
			}else if(dy < 0){
				View lastChild = this.getChildAt(this.getChildCount() - 1);
				if(lastChild == null || (lastChild != null && (lastChild.getBottom() <= this.getHeight()))){
					setScrollAble(true);
				}
			}
		}

		return super.dispatchTouchEvent(ev);
	}

    ……

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值