RecylerViewd的Item高度自适应,Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

scrollview 嵌套recyclerview 时,recyclerview不显示,这就需要我们自己计算recyclerview的高度,比如:

<span style="font-size:14px;"><code class="hljs avrasm has-numbering"> ViewGroup<span class="hljs-preprocessor">.LayoutParams</span> mParams = recyclerView<span class="hljs-preprocessor">.getLayoutParams</span>()<span class="hljs-comment">;</span>
        mParams<span class="hljs-preprocessor">.height</span> = (CommonUtils<span class="hljs-preprocessor">.getScreenWidthPX</span>(getActivity()) * <span class="hljs-number">480</span> / <span class="hljs-number">720</span> + CommonUtils<span class="hljs-preprocessor">.dipToPixels</span>(<span class="hljs-number">40</span>)) * num + CommonUtils<span class="hljs-preprocessor">.dipToPixels</span>(<span class="hljs-number">8</span>)<span class="hljs-comment">;</span>
        mParams<span class="hljs-preprocessor">.width</span> = CommonUtils<span class="hljs-preprocessor">.getScreenWidthPX</span>(getActivity())<span class="hljs-comment">;</span>
        recyclerView<span class="hljs-preprocessor">.setLayoutParams</span>(mParams)<span class="hljs-comment">;</span></code></span>

这中方法适合item高度比较好计算的情形,但要遇到里面的item高度不一定这就需要我们重写recyclerview的高度了,以前嵌套listview的时候我们只需重写listview 然后重写

<span style="font-size:14px;"><code class="hljs java has-numbering"><span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(<span class="hljs-keyword">int</span> widthMeasureSpec, <span class="hljs-keyword">int</span> heightMeasureSpec) {
        <span class="hljs-comment">// TODO Auto-generated method stub</span>
        <span class="hljs-keyword">int</span> expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> <span class="hljs-number">2</span>,
                MeasureSpec.AT_MOST);
        <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, expandSpec);
    }</code></span>

但是这种方法在recyclerview重写不管用。
我们此时要重写的的是LinearLayoutManager或GridLayoutManager

<span style="font-size:14px;"><code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FullyLinearLayoutManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LinearLayoutManager</span> {</span>

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = FullyLinearLayoutManager.class.getSimpleName();

    <span class="hljs-keyword">public</span> <span class="hljs-title">FullyLinearLayoutManager</span>(Context context) {
        <span class="hljs-keyword">super</span>(context);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-title">FullyLinearLayoutManager</span>(Context context, <span class="hljs-keyword">int</span> orientation, <span class="hljs-keyword">boolean</span> reverseLayout) {
        <span class="hljs-keyword">super</span>(context, orientation, reverseLayout);
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span>[] mMeasuredDimension = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">2</span>];

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(RecyclerView.Recycler recycler, RecyclerView.State state,
                          <span class="hljs-keyword">int</span> widthSpec, <span class="hljs-keyword">int</span> heightSpec) {

        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> widthMode = View.MeasureSpec.getMode(widthSpec);
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> heightMode = View.MeasureSpec.getMode(heightSpec);
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> widthSize = View.MeasureSpec.getSize(widthSpec);
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> heightSize = View.MeasureSpec.getSize(heightSpec);

        Log.i(TAG, <span class="hljs-string">"onMeasure called. \nwidthMode "</span> + widthMode
                + <span class="hljs-string">" \nheightMode "</span> + heightSpec
                + <span class="hljs-string">" \nwidthSize "</span> + widthSize
                + <span class="hljs-string">" \nheightSize "</span> + heightSize
                + <span class="hljs-string">" \ngetItemCount() "</span> + getItemCount());

        <span class="hljs-keyword">int</span> width = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> height = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < getItemCount(); i++) {
            measureScrapChild(recycler, i,
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);

            <span class="hljs-keyword">if</span> (getOrientation() == HORIZONTAL) {
                width = width + mMeasuredDimension[<span class="hljs-number">0</span>];
                <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>) {
                    height = mMeasuredDimension[<span class="hljs-number">1</span>];
                }
            } <span class="hljs-keyword">else</span> {
                height = height + mMeasuredDimension[<span class="hljs-number">1</span>];
                <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>) {
                    width = mMeasuredDimension[<span class="hljs-number">0</span>];
                }
            }
        }
        <span class="hljs-keyword">switch</span> (widthMode) {
            <span class="hljs-keyword">case</span> View.MeasureSpec.EXACTLY:
                width = widthSize;
            <span class="hljs-keyword">case</span> View.MeasureSpec.AT_MOST:
            <span class="hljs-keyword">case</span> View.MeasureSpec.UNSPECIFIED:
        }

        <span class="hljs-keyword">switch</span> (heightMode) {
            <span class="hljs-keyword">case</span> View.MeasureSpec.EXACTLY:
                height = heightSize;
            <span class="hljs-keyword">case</span> View.MeasureSpec.AT_MOST:
            <span class="hljs-keyword">case</span> View.MeasureSpec.UNSPECIFIED:
        }

        setMeasuredDimension(width, height);
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">measureScrapChild</span>(RecyclerView.Recycler recycler, <span class="hljs-keyword">int</span> position, <span class="hljs-keyword">int</span> widthSpec,
                                   <span class="hljs-keyword">int</span> heightSpec, <span class="hljs-keyword">int</span>[] measuredDimension) {
        <span class="hljs-keyword">try</span> {
            View view = recycler.getViewForPosition(<span class="hljs-number">0</span>);<span class="hljs-comment">//fix 动态添加时报IndexOutOfBoundsException</span>

            <span class="hljs-keyword">if</span> (view != <span class="hljs-keyword">null</span>) {
                RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();

                <span class="hljs-keyword">int</span> childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                        getPaddingLeft() + getPaddingRight(), p.width);

                <span class="hljs-keyword">int</span> childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                        getPaddingTop() + getPaddingBottom(), p.height);

                view.measure(childWidthSpec, childHeightSpec);
                measuredDimension[<span class="hljs-number">0</span>] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
                measuredDimension[<span class="hljs-number">1</span>] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
                recycler.recycleView(view);
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            e.printStackTrace();
        } <span class="hljs-keyword">finally</span> {
        }
    }
}
</code></span>

=======

<span style="font-size:14px;"><code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FullyGridLayoutManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">GridLayoutManager</span> {</span>

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mwidth = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mheight = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-title">FullyGridLayoutManager</span>(Context context, <span class="hljs-keyword">int</span> spanCount) {
        <span class="hljs-keyword">super</span>(context, spanCount);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-title">FullyGridLayoutManager</span>(Context context, <span class="hljs-keyword">int</span> spanCount, <span class="hljs-keyword">int</span> orientation, <span class="hljs-keyword">boolean</span> reverseLayout) {
        <span class="hljs-keyword">super</span>(context, spanCount, orientation, reverseLayout);
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span>[] mMeasuredDimension = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">2</span>];

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getMwidth</span>() {
        <span class="hljs-keyword">return</span> mwidth;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setMwidth</span>(<span class="hljs-keyword">int</span> mwidth) {
        <span class="hljs-keyword">this</span>.mwidth = mwidth;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getMheight</span>() {
        <span class="hljs-keyword">return</span> mheight;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setMheight</span>(<span class="hljs-keyword">int</span> mheight) {
        <span class="hljs-keyword">this</span>.mheight = mheight;
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(RecyclerView.Recycler recycler, RecyclerView.State state, <span class="hljs-keyword">int</span> widthSpec, <span class="hljs-keyword">int</span> heightSpec) {
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> widthMode = View.MeasureSpec.getMode(widthSpec);
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> heightMode = View.MeasureSpec.getMode(heightSpec);
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> widthSize = View.MeasureSpec.getSize(widthSpec);
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> heightSize = View.MeasureSpec.getSize(heightSpec);

        <span class="hljs-keyword">int</span> width = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> height = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> count = getItemCount();
        <span class="hljs-keyword">int</span> span = getSpanCount();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < count; i++) {
            measureScrapChild(recycler, i,
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);

            <span class="hljs-keyword">if</span> (getOrientation() == HORIZONTAL) {
                <span class="hljs-keyword">if</span> (i % span == <span class="hljs-number">0</span>) {
                    width = width + mMeasuredDimension[<span class="hljs-number">0</span>];
                }
                <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>) {
                    height = mMeasuredDimension[<span class="hljs-number">1</span>];
                }
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">if</span> (i % span == <span class="hljs-number">0</span>) {
                    height = height + mMeasuredDimension[<span class="hljs-number">1</span>];
                }
                <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>) {
                    width = mMeasuredDimension[<span class="hljs-number">0</span>];
                }
            }
        }

        <span class="hljs-keyword">switch</span> (widthMode) {
            <span class="hljs-keyword">case</span> View.MeasureSpec.EXACTLY:
                width = widthSize;
            <span class="hljs-keyword">case</span> View.MeasureSpec.AT_MOST:
            <span class="hljs-keyword">case</span> View.MeasureSpec.UNSPECIFIED:
        }

        <span class="hljs-keyword">switch</span> (heightMode) {
            <span class="hljs-keyword">case</span> View.MeasureSpec.EXACTLY:
                height = heightSize;
            <span class="hljs-keyword">case</span> View.MeasureSpec.AT_MOST:
            <span class="hljs-keyword">case</span> View.MeasureSpec.UNSPECIFIED:
        }
        setMheight(height);
        setMwidth(width);
        setMeasuredDimension(width, height);
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">measureScrapChild</span>(RecyclerView.Recycler recycler, <span class="hljs-keyword">int</span> position, <span class="hljs-keyword">int</span> widthSpec,
                                   <span class="hljs-keyword">int</span> heightSpec, <span class="hljs-keyword">int</span>[] measuredDimension) {
        <span class="hljs-keyword">if</span> (position < getItemCount()) {
            <span class="hljs-keyword">try</span> {
                View view = recycler.getViewForPosition(<span class="hljs-number">0</span>);<span class="hljs-comment">//fix 动态添加时报IndexOutOfBoundsException</span>
                <span class="hljs-keyword">if</span> (view != <span class="hljs-keyword">null</span>) {
                    RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
                    <span class="hljs-keyword">int</span> childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                            getPaddingLeft() + getPaddingRight(), p.width);
                    <span class="hljs-keyword">int</span> childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                            getPaddingTop() + getPaddingBottom(), p.height);
                    view.measure(childWidthSpec, childHeightSpec);
                    measuredDimension[<span class="hljs-number">0</span>] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
                    measuredDimension[<span class="hljs-number">1</span>] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
                    recycler.recycleView(view);
                }
            } <span class="hljs-keyword">catch</span> (Exception e) {
                e.printStackTrace();
            }
        }
    }
}</code></span>

重写完之后,用就好说了,在adapter的onBindview和平常一样用就可以了

<span style="font-size:14px;"><code class="hljs avrasm has-numbering"> final FullyGridLayoutManager manager = new FullyGridLayoutManager(context<span class="hljs-preprocessor">.getActivity</span>(), <span class="hljs-number">3</span>)<span class="hljs-comment">;</span>
        manager<span class="hljs-preprocessor">.setOrientation</span>(GridLayoutManager<span class="hljs-preprocessor">.VERTICAL</span>)<span class="hljs-comment">;</span>
        manager<span class="hljs-preprocessor">.setSmoothScrollbarEnabled</span>(true)<span class="hljs-comment">;</span>
        viewHolder<span class="hljs-preprocessor">.recyclerView</span><span class="hljs-preprocessor">.setLayoutManager</span>(manager)<span class="hljs-comment">;</span></code></span>

此种方法在4.x系统上好用,能显示滑动也流畅,但是在5.x上虽然显示正常,但是滑动的时候好像被粘住了,没有惯性效果。。。。然后郁闷了一下午。。。。
最后解决方法是重写最外层的Scrollview

<span style="font-size:14px;"><code class="hljs java has-numbering">**
 * 屏蔽 滑动事件
 * Created by fc on <span class="hljs-number">2015</span>/<span class="hljs-number">7</span>/<span class="hljs-number">16.</span>
 */
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyScrollview</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ScrollView</span> {</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> downX;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> downY;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mTouchSlop;

    <span class="hljs-keyword">public</span> <span class="hljs-title">MyScrollview</span>(Context context) {
        <span class="hljs-keyword">super</span>(context);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-title">MyScrollview</span>(Context context, AttributeSet attrs) {
        <span class="hljs-keyword">super</span>(context, attrs);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-title">MyScrollview</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) {
        <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">onInterceptTouchEvent</span>(MotionEvent e) {
        <span class="hljs-keyword">int</span> action = e.getAction();
        <span class="hljs-keyword">switch</span> (action) {
            <span class="hljs-keyword">case</span> MotionEvent.ACTION_DOWN:
                downX = (<span class="hljs-keyword">int</span>) e.getRawX();
                downY = (<span class="hljs-keyword">int</span>) e.getRawY();
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> MotionEvent.ACTION_MOVE:
                <span class="hljs-keyword">int</span> moveY = (<span class="hljs-keyword">int</span>) e.getRawY();
                <span class="hljs-keyword">if</span> (Math.abs(moveY - downY) > mTouchSlop) {
                    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
                }
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.onInterceptTouchEvent(e);
    }
}
</code></span><ul style="display: block;" class="pre-numbering"><li><span style="font-size:14px;">
</span></li></ul>
这样就可以了,暴力屏蔽。。。。5以上的事件直接传递给了内层的recyclerview,所以我们把滑动事件拦截就好
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值