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);
}
/**
* // 获取屏幕宽高 动态设置 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);
}
问题就解决了