fragment中 ScrollView 同時巢狀viewpager banner和 listview, scrollview 滑動異常·
阿新 • • 發佈:2018-11-20
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()); } }