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

转载 2015年11月17日 17:20:27

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,所以我们把滑动事件拦截就好

RecyclerView GridLayoutManager 使用遇到的问题

(1)item不居中的问题,请看下面的文章 http://www.jianshu.com/p/a6cd97d8646c (2)从实际情况来看,item中的内容是自动垂直居中的。...

RecyclerView自适应高度的LayoutManager

RecyclerView原生的LayoutManager并不能自适应宽高,此处实现了一个LayoutManager的子类,实现了自适应。留作备份。...

RecyclerView高度随Item自适应 GridLayoutManager和LinearLayoutManager都适用

ScrollView嵌套RecyclerView时,android:layout_height=”wrap_content”并不起作用,RecyclerView会填充剩余的整个屏幕空间,也就相当于an...

RecyclerView--GridLayoutManager设置某个item占据的列数

/** * 设置瀑布流布局中的某个item,独占一行、占一列、占两列、等等 * @param mStaggeredGridLayoutManager * @param p...

解决Scrollview 嵌套recyclerview不能显示,高度不正常的问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 我们先看一个效果,问题说的就是中间的Grid效果在Scrollview 嵌套recyclerview显示问题,在Android Api 24...

ScrollView里嵌套Recycleview使用StaggeredGridLayoutManager高度不正确的问题

http://frank-zhu.github.io/android/2015/02/26/android-recyclerview-part-3/ 作者的这个文章中给出了ScrollView中嵌套...

Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

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

Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

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

Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

scrollview 嵌套recyclerview 时,recyclerview不显示,这就需要我们自己计算recyclerview的高度,比如: ViewGroup.LayoutParams m...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:RecylerViewd的Item高度自适应,Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题
举报原因:
原因补充:

(最多只允许输入30个字)