fragment中 ScrollView 同时嵌套viewpager banner和 listview, scrollview 滑动异常·
fragment中 ScrollView 同时嵌套viewpager banner和 listview,
如图所示
在fragment首次加载或 onHiddenChanged事件发生后 scrollview都会滑动到listview的顶部
这破scrollview ,上一个项目也遇到同样的问题 忘了怎么解决的了,这次记录下来 首先用的listview是这样修改过的 以适应scrollview
public class CustomListView extends ListView { public CustomListView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public CustomListView(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (height != 0) { super.onSizeChanged(w, height, oldw, oldh); } else { super.onSizeChanged(w, h, oldw, oldh); } } int height = 0; public void setHeight(int height) { this.height = height; } }
在 fragment onHiddenChanged 事件之后 hidden 为false fragment显示时, scrollview 会调用 onLayout 事件 然后OnScrollChangeListener 才能监听到滑动变化 ,now方法来了
我在 fragment onHiddenChanged hidden 为 true时记录 scrollview的 scrollY值 在scrollview的 onlayout 事件 中调用 scrollTo(0, scrollY); 来设置Y轴滑动距离,完美解决 scrollview代码如下 :
import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ScrollView; public class MyScrollView extends ScrollView { private float xLast, yLast, xDistance, yDistance; // ScrollView的子View, 也是ScrollView的唯一一个子View private View contentView; // 用于记录正常的布局位置 private Rect originalRect = new Rect(); private int scrollY; @Override public void setScrollY(int scrollY) { this.scrollY = scrollY; } @Override public void setOnScrollChangeListener(OnScrollChangeListener l) { super.setOnScrollChangeListener(l); } public MyScrollView(Context context) { super(context); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onFinishInflate() { if (getChildCount() > 0) { contentView = getChildAt(0); } } @Override public void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (contentView == null) return; // ScrollView中的唯一子控件的位置信息, 这个位置信息在整个控件的生命周期中保持不变 originalRect.set(contentView.getLeft(), contentView.getTop(), contentView.getRight(), contentView.getBottom()); scrollTo(0, scrollY); } /** * 在这里解决滑动上下滑动,左右滑动冲突 * * @param ev * @return */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: xDistance = yDistance = 0f; xLast = ev.getX(); yLast = ev.getY(); break; case MotionEvent.ACTION_MOVE: final float curX = ev.getX(); final float curY = ev.getY(); xDistance += Math.abs(curX - xLast); yDistance += Math.abs(curY - yLast); xLast = curX; yLast = curY; if (xDistance > yDistance) { return false; //表示向下传递事件 } } return super.onInterceptTouchEvent(ev); } }
fragment代码简单:
@Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); if (hidden) { sv.setScrollY(sv.getScrollY()); } }