scrollview嵌套recycle人view显示不全的问题解决

解决scrollview嵌套recycle人view显示不全的问题

最近在开发的项目的时候遇到这样的需求效果图是这样的

使用的布局是 scrollview嵌套recycle人view ,说实话这样的开发需求很的常见吧,高高兴兴开发完成,但是测试的时候发现,完蛋了,完美采坑,recycle人view的条目遇到现实不全的bug ,查阅资料,最后杀出了一条血路 ,在这里记录一下

1.显示不全怎样解决

很简单只需要在recyclerview的外层单独套一层viewgroup就像我这样

  <ScrollView
        android:id="@+id/sc"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">


        ....

        <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="300px"
                android:descendantFocusability="blocksDescendants"
                >

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/rv_repair"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="30px"
                    android:background="#fff" />
        </RelativeLayout>
    </ScrollView>

好了问题到这里已经完美的解决了尽情的享受好了

2.解决使用 ImageButton,Button,CheckBox 等 adapter的父条目无法点击的情况

细心的你会问怎么在增加的布局中增加了 android:descendantFocusability=”blocksDescendants” 这个属性啊。

其实这个就是细节操作了

android的源码告诉我们,在我们的可滑动控件的adapter中如果出现了 clickable=true 的控件 比如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

这时候就可以使用descendantFocusability来解决啦,API描述如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

    beforeDescendants:viewgroup会优先其子类控件而获取到焦点

    afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

    blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)。

好了现在是不是可以开开森森的写代码了,因为你已经完美的解决了button或者CheckBox抢夺父条目焦点,导致父控件无法点击的情况了

3.解决recyclerview滑动和父控件scrollview冲突

一句话直接禁止recyclerview的滑动

    mRrecyclerview.setNestedScrollingEnabled(false);

好了到此这个问题已经你完美的解决了

4.优化-解决部分机型不起作用的bug,(不是一般人会遇到这个bug的)

如果上面的方法在部分的机型上面还是存在bug的话,我们可以尝试补丁包方案,是问题达到100% 的解决

1.创建FullyLinearLayoutManager.java 的文件,代码如下
2.使用这个布局管理器

    FullyLinearLayoutManager linearLayoutManager = new FullyLinearLayoutManager(this);
    mRrecyclerview.setLayoutManager(linearLayoutManager);

3.enjoy it

    import android.content.Context;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;

    /**
     * Created by benchengzhou on 2017/12/9  14:29 .
     * 作者邮箱: [email protected]
     * 功能描述: recyclerviewmanger (线性布局)解决和scrollviewview 嵌套显示不全的问题
     * 类    名: FullyLinearLayoutManager
     * 备    注:
     */

    public class FullyLinearLayoutManager extends LinearLayoutManager {


        private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();

        public FullyLinearLayoutManager(Context context) {
            super(context);
        }

        public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super(context, orientation, reverseLayout);
        }

        private int[] mMeasuredDimension = new int[2];

        @Override
        public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                              int widthSpec, int heightSpec) {

            final int widthMode = View.MeasureSpec.getMode(widthSpec);
            final int heightMode = View.MeasureSpec.getMode(heightSpec);
            final int widthSize = View.MeasureSpec.getSize(widthSpec);
            final int heightSize = View.MeasureSpec.getSize(heightSpec);

            Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode
                    + " \nheightMode " + heightSpec
                    + " \nwidthSize " + widthSize
                    + " \nheightSize " + heightSize
                    + " \ngetItemCount() " + getItemCount());

            int width = 0;
            int height = 0;
            for (int i = 0; i < getItemCount(); i++) {
                measureScrapChild(recycler, i,
                        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                        mMeasuredDimension);

                if (getOrientation() == HORIZONTAL) {
                    width = width + mMeasuredDimension[0];
                    if (i == 0) {
                        height = mMeasuredDimension[1];
                    }
                } else {
                    height = height + mMeasuredDimension[1];
                    if (i == 0) {
                        width = mMeasuredDimension[0];
                    }
                }
            }
            switch (widthMode) {
                case View.MeasureSpec.EXACTLY:
                    width = widthSize;
                case View.MeasureSpec.AT_MOST:
                case View.MeasureSpec.UNSPECIFIED:
            }

            switch (heightMode) {
                case View.MeasureSpec.EXACTLY:
                    height = heightSize;
                case View.MeasureSpec.AT_MOST:
                case View.MeasureSpec.UNSPECIFIED:
            }

            setMeasuredDimension(width, height);
        }

        private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                       int heightSpec, int[] measuredDimension) {
            try {
                View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException

                if (view != null) {
                    RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();

                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                            getPaddingLeft() + getPaddingRight(), p.width);

                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                            getPaddingTop() + getPaddingBottom(), p.height);

                    view.measure(childWidthSpec, childHeightSpec);
                    measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
                    measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
                    recycler.recycleView(view);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            }
        }


    }

猜你喜欢

转载自blog.csdn.net/bencheng06/article/details/79140154