在垂直 recyclerView 中带有 wrap_content 的水平 recyclerView
Posted
技术标签:
【中文标题】在垂直 recyclerView 中带有 wrap_content 的水平 recyclerView【英文标题】:horizontal recyclerView with wrap_content in vertical recyclerView 【发布时间】:2015-12-17 19:48:40 【问题描述】:在我的应用程序中,我必须在垂直 RecyclerView 中创建水平 RecyclerView。它们是一些将显示随意细节的行,在某些行中将显示一个水平的 RecyclerView。
我已将水平 RecyclerView 的高度设置为不可见的 wrap_content。但是当我向它添加硬编码高度时,RecyclerView 是可见的。关于这个问题,我进行了很多搜索,但没有找到任何有效或令人信服的解决方案。
这是我的适配器类
public class HomeRVAdapter extends RecyclerView.Adapter<HomeRVAdapter.HomeViewHolder>
private ArrayList<LinkedHashMap<String, Object>> data;
private Context ctx;
private int selectedIndex;
public HomeRVAdapter(Context ctx, ArrayList<LinkedHashMap<String, Object>> val)
data = val;
this.ctx = ctx;
selectedIndex = -1;
@Override
public HomeViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
LayoutInflater inflater = ((Activity) ctx).getLayoutInflater();
View view = inflater.inflate(R.layout.custom_home_recycler, null);
return new HomeViewHolder(view);
@Override
public int getItemCount()
return data.size();
@Override
public void onBindViewHolder(final HomeViewHolder holder, final int position)
if (getItemCount() == position+1)
holder.categoryLL.setVisibility(View.GONE);
holder.productLL.setVisibility(View.VISIBLE);
LinearLayoutManager manager = new LinearLayoutManager(ctx);
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
ArrayList<SubCategoryDetails> list = new ArrayList<>();
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
holder.subCatRV.setAdapter(new PromoProductAdapter(list, holder.subCatRV));
holder.subCatRV.setLayoutManager(manager);
else
holder.categoryLL.setVisibility(View.VISIBLE);
holder.productLL.setVisibility(View.GONE);
if (selectedIndex == position)
holder.subCatGrid.setVisibility(View.VISIBLE);
showGrid(holder);
else
holder.subCatGrid.setVisibility(View.GONE);
holder.catTR.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
if (selectedIndex == position)
holder.subCatGrid.setVisibility(View.GONE);
selectedIndex = -1;
else
selectedIndex = position;
showGrid(holder);
);
private void showGrid(HomeViewHolder holder)
ArrayList<SubCategoryDetails> list = new ArrayList<>();
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
list.add(new SubCategoryDetails());
SubCategoryGridAdapter adapter = new SubCategoryGridAdapter(list);
holder.subCatGrid.setAdapter(adapter);
holder.subCatGrid.setVisibility(View.VISIBLE);
class HomeViewHolder extends RecyclerView.ViewHolder
RecyclerView subCatRV;
TextView catTitleTV, productNameTV;
ImageView productIV;
NonScrollableGridView subCatGrid;
LinearLayout categoryLL, productLL;
TableRow catTR;
public HomeViewHolder(View view)
super(view);
subCatRV = (RecyclerView) view.findViewById(R.id.subCatRV);
productNameTV = (TextView) view.findViewById(R.id.productNameTV);
catTitleTV = (TextView) view.findViewById(R.id.catTitleTV);
productIV = (ImageView) view.findViewById(R.id.productIV);
subCatGrid = (NonScrollableGridView) view.findViewById(R.id.subCatGrid);
categoryLL = (LinearLayout) view.findViewById(R.id.categoryLL);
productLL = (LinearLayout) view.findViewById(R.id.productLL);
catTR = (TableRow) view.findViewById(R.id.catTR);
class SubCategoryGridAdapter extends BaseAdapter
ArrayList<SubCategoryDetails> subCatData;
public SubCategoryGridAdapter(ArrayList<SubCategoryDetails> subCatData)
this.subCatData = subCatData;
@Override
public int getCount()
return subCatData.size();
@Override
public Object getItem(int position)
return null;
@Override
public View getView(int position, View convertView, ViewGroup parent)
if (convertView == null)
convertView = ((Activity) ctx).getLayoutInflater().inflate(R.layout.custom_sub_cat_grid, null, true);
return convertView;
@Override
public long getItemId(int position)
return 0;
class PromoProductAdapter extends RecyclerView.Adapter<PromoProductAdapter.PromoHolder>
ArrayList<SubCategoryDetails> data;
RecyclerView horizontalRV;
public PromoProductAdapter(ArrayList<SubCategoryDetails> data, RecyclerView horizontalRV)
this.data = data;
this.horizontalRV = horizontalRV;
@Override
public PromoHolder onCreateViewHolder(ViewGroup parent, int viewType)
LayoutInflater inflater = ((Activity) ctx).getLayoutInflater();
View view = inflater.inflate(R.layout.custom_promoted_product, null);
if (horizontalRV != null)
int height = view.getMeasuredHeight();
horizontalRV.getLayoutParams().height = height;
return new PromoHolder(view);
@Override
public int getItemCount()
return data.size();
@Override
public void onBindViewHolder(PromoHolder holder, int position)
class PromoHolder extends RecyclerView.ViewHolder
public PromoHolder(View view)
super(view);
请帮我解决这个问题。
【问题讨论】:
能贴出适配器代码吗? 通常 RecyclerView 不会wrap_content
height。
我已经更新了我的问题
@mr.icetea 你有什么建议来管理我的 RecyclerView 的高度
@KislayKumar 它看起来像 hack,但是您是否尝试将您的 RecyclerView 包装在某个布局中并设置高度(如果此布局)并将 RecyclerView 保留为 match_parent 属性?
【参考方案1】:
一个更简单的解决方案是保持高度硬编码(因为它是一个水平视图,高度可以保持固定),然后如果输入为空,则隐藏水平回收器视图。
if(list.size() == 0)
horizontalRecyclerView.setVisibility(View.GONE);
【讨论】:
【参考方案2】:我自己解决了这个问题。我使用了从link 找到的自定义 LinearLayoutManager。
public class MyLinearLayoutManager extends LinearLayoutManager
public MyLinearLayoutManager(Context context)
super(context);
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);
measureScrapChild(recycler, 0,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
int width = mMeasuredDimension[0];
int height = mMeasuredDimension[1];
switch (widthMode)
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
width = widthSize;
break;
case View.MeasureSpec.UNSPECIFIED:
switch (heightMode)
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
height = heightSize;
break;
case View.MeasureSpec.UNSPECIFIED:
setMeasuredDimension(width, height);
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension)
View view = recycler.getViewForPosition(position);
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();
measuredDimension[1] = view.getMeasuredHeight();
recycler.recycleView(view);
只需将此 LinearLayoutManager 添加到您的 RecyclerView 即可。
谢谢大家 干杯!!!
【讨论】:
这可能曾经有效,但不再有效。试过了,它在尝试测量不存在的东西时崩溃了。但无论如何只测量第一项似乎并不合适。以上是关于在垂直 recyclerView 中带有 wrap_content 的水平 recyclerView的主要内容,如果未能解决你的问题,请参考以下文章
覆盖中带有 wrap_content 的 TextView 未扩展到完整内容宽度
ViewPager中带有StaggeredGridLayoutManager的RecyclerView,返回fragment时自动排列item
Firefox Android 中带有“white-space:pre-wrap”的“input”高度大于 Android 中的 Chrome