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

来源:互联网 发布:一搜网络一搜同志0731 编辑:程序博客网 时间:2024/06/05 00:22

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,所以我们把滑动事件拦截就好
0 1
原创粉丝点击