1. 程式人生 > >fragment中 ScrollView 同時巢狀viewpager banner和 listview, scrollview 滑動異常·

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());
    }
}