您的位置:首页 > 移动开发 > Android开发

android scrollview listview的嵌套问题

2015-01-20 15:42 323 查看
android scrollview和listview的嵌套问题

在实际的项目中,我们可能会碰到scrollview嵌套listview的情况,最好的解决方法是如果能把这个元素放到listview的headview是最好的。如果必须得嵌套在scrollview中,我们应该怎么做呢?

1、首先,在xml中将listview的高度设置为0;

2、在scrollview渲染之后,设置listview的高度为scrollview的高度,这样会形成一个吸顶效果;

ViewTreeObserver viewTreeObserver = mScrollView.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int viewHeight = mScrollView.getHeight();
mListView.getLayoutParams().height = viewHeight;
}
});
}

3、需要调整scrollview的触屏事件处理模块,dispatchTouchEvent(MotionEvent ev),具体的参考下面的demo代码;

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mImitateTouch = false;
mIsBeingDragged = false;
mLastMotionY = (int) ev.getY();
mOriInterupt = mInterupt;
final float offsetX = getScrollX() - mListView.getLeft();
final float offsetY = getScrollY() - mListView.getTop();

// 表示scrollview仍有部分可见,同时点击事件是在嵌套的view中(如listview、viewpager),模拟一个点击事件
if ((int)(offsetX+ev.getX()) >= 0 && (int)(offsetY+ev.getY()) >= 0 && canScrollDown(1)) {
imitateTouchEvent(ev, mListView);
mImitateTouch = true;
}
break;
case MotionEvent.ACTION_MOVE:
final int y = (int) ev.getY();
int deltaY = mLastMotionY - y;
boolean isSrollDown;
if (deltaY > 0) {
isSrollDown = true;
} else {
isSrollDown = false;
}

if (!mIsBeingDragged) {
if (Math.abs(deltaY) > mTouchSlop) {
mIsBeingDragged = true;
deltaY = deltaY > 0 ? deltaY-mTouchSlop : deltaY+mTouchSlop;
} else {
break;
}
}

// 如果有模拟事件,因为有move事件,需要发送一个cancel事件给嵌套的view(这里是listview,viewpager情况会更加复杂一些)
if (mImitateTouch) {
imitateTouchEvent(MotionEvent.ACTION_CANCEL, ev.getX(), ev.getY(), mListView);
mImitateTouch = false;
}

if (!isSrollDown) {
// 从上向下滑动,同时listview不能继续滑动
if (!canScrollList(-1, mListView)) {
mInterupt = true;
// 从listview滑向scrollview,由于scrollview没有获取事件响应,需要手动控制
if (!mOriInterupt) {
mDisable = true;
scrollBy(0, deltaY);
} else {
mDisable = false;
}
} else {
mDisable = true;
if (mImitateClicked) {
imitateTouchEvent(ev, mListView);
}
}
} else {
// 从下向上滑动,同时scrollview不能继续滑动
if (!canScrollDown(1)) {
// 通过scrollview滑动到listview,由于嵌套的listview没有获取事件响应,需要为listview模拟一个down事件
if (mOriInterupt && mInterupt) {
imitateTouchEvent(MotionEvent.ACTION_DOWN, ev.getX(), ev.getY(), mListView);
mImitateClicked = true;
}
// 继续为listview模拟后续的move事件
if (mOriInterupt) {
imitateTouchEvent(ev, mListView);
}
mInterupt = false;
mDisable = true;
} else {
mInterupt = true;
// 嵌套的view获取了事件响应,需要为外层的scrollview手动触发滑动
if (canScrollDown(-1) && !mOriInterupt) {
mDisable = true;
scrollBy(0, deltaY);
} else  {
mDisable = false;
}
}
}
mLastMotionY = y;
break;
case MotionEvent.ACTION_UP:
mOriInterupt = mInterupt;
if (mImitateTouch || mImitateClicked) {
imitateTouchEvent(ev, mListView);
mImitateTouch = mImitateClicked = false;
}
break;

}
return super.dispatchTouchEvent(ev);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mInterupt;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mDisable) {
return true;
} else {
return super.onTouchEvent(ev);
}
}


代码示例:https://github.com/xsbupt/nestscrollview

后续会继续更新scrollview嵌套webview,viewpager等的嵌套问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐