天天看點

關于ScrollView嵌套RecyclerView高度,焦點,滑動,setOnScrollChangeListener問題的解決

1 RecyclerView高度設定不起作用

解決方法:

a)重寫tLayoutManager 太麻煩,有興趣可以查查

b)代碼裡給RecyclerView設定一個高度

ViewGroup.LayoutParams params = rvMused.getLayoutParams();
        params.height = *;//條目的高度*顯示多少條 這裡注意不要把條目的布局高度設為match_parent 可以是wrap_cotent或者直接寫固定高度
        recyclerView.setLayoutParams(params);
           

注:自定義的條目布局 R.layout.item 的高度也可以代碼獲得

c)神奇的相對布局

有上面問題一般是因為你用了

<ScrollView>
    <LinearLayout>
        <!--其他布局-->
        <RecyclerView
        android:layout_height="YOURHHEIGHTVALUE"/>
    <LinearLayout/>
</ScrollView>
           

上述布局就會有嵌套高度設定”YOURHHEIGHTVALUE”不起作用的情況,然而隻要簡單的換成相對布局,一切就好了

<ScrollView>
    <RelativeLayout>
        <!--其他布局-->
        <RecyclerView
         android:layout_height="YOURHHEIGHTVALUE"/>
    <RelativeLayout/>
</ScrollView>
           

這樣就沒問題了 ,是不是很神奇!!!

2 RecyclerView搶占焦點是的頁面顯示位置是RecyclerView的第一條

解決方法:

代碼設定ScorllView滑動到最上面

3 讓RecyclerView不滑動

代碼裡添加

recyclerView.setNestedScrollingEnabled(false);
           

4 ScrollView的setOnScrollChangeListener()方法 requires api23 的問題

a)重寫ScrollView,

對比api19和最新的 onScrollChanged源碼

protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            postSendViewScrolledAccessibilityEventCallback();
        }

        mBackgroundSizeChanged = true;

        final AttachInfo ai = mAttachInfo;
        if (ai != null) {
            ai.mViewScrollChanged = true;
        }
    }
           
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        notifySubtreeAccessibilityStateChangedIfNeeded();

        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            postSendViewScrolledAccessibilityEventCallback();
        }

        mBackgroundSizeChanged = true;
        if (mForegroundInfo != null) {
            mForegroundInfo.mBoundsChanged = true;
        }

        final AttachInfo ai = mAttachInfo;
        if (ai != null) {
            ai.mViewScrollChanged = true;
        }
//以下是新增的代碼
        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
        }
    }
           

可以看出原理是父控件view裡一直都有 (api1開始)

protected void onScrollChanged

這個方法,而api23以前沒有提供

public interface OnScrollChangeListener

這個接口以及它的set方法–

setOnScrollChangeListener

,使得不能從外部直接獲得(this, l, t, oldl, oldt)這四個參數并進行響應操作,是以我們繼承ScrollView同時暴漏出他的父控件view的onScrollChanged方法就可以了

b)利用 sv.setOnTouchListener();方法,但是無法監聽慣性

@Override
    public boolean onTouch(View v, MotionEvent event) {
//利用v和event的getScrollY(),getX,getY,getAction等方法一樣可以達到setOnTouchListener的目的
//http://blog.csdn.net/sinat_29912455/article/details/51073537這個網址有介紹各個方法的差別
        return false;
    }
           

加強版的b方法: 獲得 ScrollView 慣性滑動後的位置

缺點:MotionEvent.ACTION_UP後後的getScrollY的時間不好确定

參考 http://lmx227.iteye.com/blog/1007533

@Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        switch (action) {

            case MotionEvent.ACTION_MOVE:
                scrollY = sv.getScrollY();
                changeTextSwicher(scrollY);
              break;
            case MotionEvent.ACTION_UP:
                scrollY = sv.getScrollY();
                changeTextSwicher(scrollY);
                detectScrollY();
                break;
        }
        return false;

    }


    public void detectScrollY() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                int tempScrollY = sv.getScrollY();
                if (tempScrollY != scrollY) {
                    scrollY = tempScrollY;
                    changeTextSwicher(tempScrollY);
                } else {
                    Log.e("TAG", "scrollX = " + scrollY);
                    return;
                }
            }
        }, );
    }


    public void changeTextSwicher(int scroll) {

    }

           

c ) 利用scrollView.getViewTreeObserver().addOnScrollChangedListener

但是慣性問題依然沒解決

scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {  
    @Override  
    public void onScrollChanged() {  

    }  
}); 
           

繼續閱讀