【问题标题】:horizontal recyclerView with wrap_content in vertical recyclerView在垂直 recyclerView 中带有 wrap_content 的水平 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 属性?

标签: android android-recyclerview


【解决方案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 即可。

    谢谢大家 干杯!!!

    【讨论】:

    • 这可能曾经有效,但不再有效。试过了,它在尝试测量不存在的东西时崩溃了。但无论如何只测量第一项似乎并不合适。
    猜你喜欢
    • 1970-01-01
    • 2016-01-20
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多