Recyclerview列表,item嵌套横向Gridview 解决滑动冲突,数据加载问题

来源:互联网 发布:js设置表单action 编辑:程序博客网 时间:2024/05/01 22:51


recyclerview列表数据,每个item 嵌套横向滑动GridView的问题,

这几天新需求,列表加载用户关注的人物,一页15条数据,,,,,,。然后每个人物 都有自己的一系列作品,要在人物头像之后 ,放一个可以横着滑动,又支持分页加载的横向列表。

刚开始觉得挺容易的,动手就开始写,,recyclerview 垂直布局,item布局嵌套一个横向的GridView,看源码xml

<LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:padding="10dp">        <LinearLayout            android:layout_width="110dp"            android:layout_height="110dp"            android:gravity="center"            android:orientation="vertical">            <com.test.testrecyclerview.weight.RoundImageView                android:id="@+id/item_engineer_headerimg"                android:layout_width="80dp"                android:layout_height="80dp"                android:src="@drawable/ease_default_avatar" />            <TextView                android:id="@+id/tv_author_name"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginTop="5dp"                android:text="名字"                android:textSize="14sp" />        </LinearLayout>         <HorizontalScrollView             android:id="@+id/horizontalScrollView"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:fillViewport="true"             android:scrollbars="none">            <LinearLayout                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:orientation="horizontal">                <GridView                    android:id="@+id/item_engineer_work_grid"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_marginLeft="5dp"                    android:gravity="center"                    android:scrollbars="none" />            </LinearLayout>         </HorizontalScrollView>    </LinearLayout>

recyclerview适配器里 拿到数据源 初始化GridView 适配器 并加载数据,


 
size = list.size();
DisplayMetrics dm2 = context.getResources().getDisplayMetrics(); float density = dm2.density; int allWidth = (int) (110 * size * density); int itemWidth = (int) (100 * density); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( allWidth, LinearLayout.LayoutParams.MATCH_PARENT); holder.mGridview.setLayoutParams(params);// 设置GirdView布局参数 holder.mGridview.setColumnWidth(itemWidth);// 列表项宽 holder.mGridview.setHorizontalSpacing(10);// 列表项水平间距 holder.mGridview.setStretchMode(GridView.NO_STRETCH); holder.mGridview.setNumColumns(size);
holder.mGridview.setAdapter(mGriddapter);



动态的根据GridView的 list的size 大小 设置item个数,,运行出来之后 发现,横向的GridView 滑动 监听不到滑动到最后一个,item点击倒是正常,,,找了各种问题,有自定义了一个LoadMoreHorizontalScrollView,拦截滑动坐标,判断是否滑动到了最右边

public class LoadMoreHorizontalScrollView extends HorizontalScrollView {    private ScrollViewListener scrollViewListener = null;    private boolean isNeedBreakNet;//这里加了个字段,用于判断 划到最右边 请求数据,不然滑到了最右边,如果手还没离开屏幕,(坐标值一直在左右边)会多次请求数据    public LoadMoreHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public LoadMoreHorizontalScrollView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public LoadMoreHorizontalScrollView(Context context) {        super(context);    }    public boolean isNeedBreakNet() {        return isNeedBreakNet;    }    public void setNeedBreakNet(boolean needBreakNet) {        isNeedBreakNet = needBreakNet;    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_MOVE:                int scrollX = getScrollX();                Log.i("GFH", "scrollX=" + scrollX + ";getScrollX()==" + getScrollX());                //最右边                if (scrollX >= getChildWidth()) {                    if (null != scrollViewListener) {                        scrollViewListener.onNextPage();                    }                }                //在最左边                if (scrollX == 0) {                    if (null != scrollViewListener) {                        scrollViewListener.onPrePage();                    }                }                break;        }        return super.onTouchEvent(ev);    }    public void setScrollViewListener(ScrollViewListener scrollViewListener) {        this.scrollViewListener = scrollViewListener;    }    /**     * 获取当前HorizontalScrollView最大能滑动的距离     */    private int getChildWidth() {        int maxScrollX = 0;        try {            maxScrollX = getChildAt(0).getMeasuredWidth() - getMeasuredWidth();        } catch (Exception e) {            Log.e("GFH", "测量最大滑动距离发生异常:" + e.toString());        }        return maxScrollX;    }    ;    public interface ScrollViewListener {        void onPrePage();        void onNextPage();    }}




,自定义控件 拦截手势之后,发现还是不对,数据请求过来了,list.size 也变大了,但是,GridView的适配器 数据源没有更新, 就是横着的item 始终是5 个(分页加载的 ,每页5条数据,),




holder.horizontalScrollView.setScrollViewListener(new LoadMoreHorizontalScrollView.ScrollViewListener() {            @Override            public void onPrePage() {                //滑动到最左边                Log.i("SNN", "滑动到最左边,上一页数据请求");            }            @Override            public void onNextPage() {                boolean isNeedBreakNet = holder.horizontalScrollView.isNeedBreakNet();                //滑动到最右边,下一页数据请求                Log.e("SNN", "滑动到最右边,下一页数据请求");                Log.e("SNN", list.get(position).getName());                if (!isNeedBreakNet) {                    //请求新数据   加载而更多                  }                holder.horizontalScrollView.setNeedBreakNet(true);            }        });



头疼了 大半天,才发现,list  和 GridViewAdapter 用的是全局变量,,而recyclerview 的 onBindViewHolder 方法 是每个item都会创建执行一次,,所以现在的情况是 GridViewadapter 只创建了一次,数据更新了 list.size 次,每次横向滑动去加载数据的时候,数据都会被加载到 recyclerview的最后一个item里边的GridView上面。

找到了 问题,就好解决了,,,就是把  list  和 GridView 都放到Map 集合中,,recyclerview加载数据的时候,根据item索引 ,去map集合中取 与position对应的 list  和 GridViewadapter

map集合 ,存放 list集合  和GridviewAdapter




private Map<Integer,GridviewAdapter> GridViewAdapterMap = new HashMap<>();    private Map<Integer, List<WorkInfoBean>> workInfoBeanMap = new HashMap<>();    private Map<Integer, Integer> pageNumMap = new HashMap<>();




然后在onBindViewHolder  中 绑定position 和数据




List<WorkInfoBean> workList = null;        if (null != workInfoBeanMap.get(position)) {            // workList.get(position);        } else {            workList = list.get(position).getPots();            workInfoBeanMap.put(position, workList);        }


GridviewAdapter  mGriddapter = null;        if (null != engineerWorkInfoGridViewAdapterMap.get(position)) {            mGriddapter = GridViewAdapterMap.get(position);        } else {            mGriddapter = new GridViewAdapter(context, workList);            GridViewAdapterMap.put(position, mGriddapter);        }




最后得注意 GridView item个数额计算,不能放在onBindViewHolder 中,单独提取个方法出来,,




 /**     * // 获取屏幕宽高  动态设置 mGridview item     *     * @param size     * @param holder     */    public void newSize(int size, MyViewHolder holder) {        DisplayMetrics dm2 = context.getResources().getDisplayMetrics();        float density = dm2.density;        int allWidth = (int) (110 * size * density);        int itemWidth = (int) (100 * density);        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(                allWidth, LinearLayout.LayoutParams.MATCH_PARENT);        holder.mGridview.setLayoutParams(params);// 设置GirdView布局参数        holder.mGridview.setColumnWidth(itemWidth);// 列表项宽        holder.mGridview.setHorizontalSpacing(10);// 列表项水平间距        holder.mGridview.setStretchMode(GridView.NO_STRETCH);        holder.mGridview.setNumColumns(size);    }



在 onBindViewHolder 中 setadapter 之前 调用一次,然后在 请求新数据之后  再调用一次,,重新计算item个数。

问题就解决了


阅读全文
2 0