根据数据内容创建RecyclerView项目布局

时间:2015-08-21 10:45:49

标签: android android-layout android-recyclerview recycler-adapter

我正在创建数据对象的回收站视图,这些对象中的每一个都会有所不同,例如。

对象1   - 字符串标题   - 字符串描述   - 图像

对象2   - 字符串描述

对象3  - 图片   - 字符串链接

对象4   - 字符串描述   - 视频

所以我需要动态创建项目布局以适应每个数据对象。我不想创建包含所有可能的视图和组件的项目布局,并显示和隐藏,因为我认为这是不好的做法。

所以我的问题是我需要使用onBindViewHolder中的位置从列表中访问一个对象,以便在ViewHolder类中构建我的布局。

我尝试使用我在onBindViewHolder类中调用的方法并传入我在其中添加自定义视图的对象,同时在内部设置内容,但这不起作用。

有谁知道如何做到这一点?

此致

2 个答案:

答案 0 :(得分:5)

首先正确实现视图类型,如此处所述How to create RecyclerView with multiple view type? 实际上,你的问题与此重复,但我会写一些额外的组织内容来帮助你处理更多的持有者。

  • 关于这个答案,我将使用ButterKnife和Picasso图书馆,因为它们很棒:http://jakewharton.github.io/butterknife/http://square.github.io/picasso/

  • 在项目holders上创建一个包,然后在里面创建所有视图持有者,下面是持有者的示例:

  • 使用AbstractHolder创建public void bindData(Data data),然后使用适配器extends RecyclerView.Adapter<AbstractHolder>

  • 创建如下所示的持有者:

示例Holder1.java

public class Holder1 extends AbstractHolder {

    // that's an example of views this would use
    @Bind(R.id.text) TextView text;
    @Bind(R.id.image) ImageView image;

    // constructor as normal:
    public Holder1(View itemView){
        super(itemView);
        ButterKnife.bind(this, itemView); // init the views
    }

    // call this from the adapter
    @Override public void bindData(Data data){
        text.setText(data.text);
        Picasso.with(itemView.getContext()).load(data.url).into(image);        
    }

    // here you create an instance of this holder,
    // this way the holder and the layout it's associated with goes together
    public static Holder1 create(ViewGroup parent){
        View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.holder1, parent, false);
        return new Holder1(root);
    }

}
  • 然后您的适配器代码将是:

@Override public AbstractHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch(viewType){
            case TYPE_HOLDER_1: return Holder1.create(parent);
            case TYPE_HOLDER_2: return Holder2.create(parent);
            case TYPE_HOLDER_3: return Holder3.create(parent);
            ... carry on for all types   
        }
 }

@Override public void onBindViewHolder(AbstractHolder holder, int position) {
    Object data = getItem(position);
    holder.bindData(data);
}


// the get type would be similar to that:
@Override
public int getItemViewType(int position) {
    Object data = getItem(position);
    if( ... some condition...) return TYPE_HOLDER_1;
    else if( ... other condition...) return TYPE_HOLDER_2;
    else if( ... other condition...) return TYPE_HOLDER_3;
    ... etc ...
}

<强>结论

使用此方法,您的Adapter类只是一个&#34;分发中心&#34;对于可能的类型和每种类型&#34;知道&#34;如何创建自己以及如何处理其数据。

这使您的代码易于维护且组织良好。

答案 1 :(得分:1)

在适配器类中,您应该进行以下更改:

在您的情况下,您应该覆盖getItemViewType方法

@Override
    public int getItemViewType(int position) {
        if (position < arrayList.size()) {
            return ITEM_X_TYPE;
        } else
            return ITEM_Y_TYPE;
    }

在您的onCreateViewHolder

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


        if (viewType == ITEM_X_TYPE) {
            return new XVH(mView);
        } else if (viewType == ITEM_Y_TYPE) {
            return new YVH(mView);
        }

        throw new RuntimeException("type not found");
    }

onBindViewHolder执行此操作:

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof XVH) {

            XVH m = (XVH) holder;
            ... (continue your code)

修改

现在我的建议是,在onCreateViewHolder中你应该像这样做:

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.your_linear_layout_container, parent, false);
        if (viewType == ITEM_X_TYPE) {
            return new XVH(mView,ITEM_X_TYPE,Object one);
        } else if (viewType == ITEM_Y_TYPE) {
            return new XVH(mView,ITEM_Y_TYPE, Object two, Object three);
        }

        throw new RuntimeException(type not found");
    }

所以在这里你创建了一个视图,然后将它传递给你的视图持有者,并创建视图持有者调用不同构造函数的不同实例。

然后在你的VH构造函数中你会像这样做:

public class XVH extends RecyclerView.ViewHolder implements {
    int viewType;
    public XVH(View itemView,int viewType,Object one) {
        super(itemView);
        this.viewType = viewType;
        // manage your layouts here, build there here or you can inflate from other xml 
    }

public XVH(View itemView,int viewType,Object two, Object three) {
            super(itemView);
            this.viewType = viewType;
            // manage your layouts here, build there here or you can inflate from other xml 
        }

onBindViewHolder中,您检查项目类型是什么,然后加载数据。

我希望这有助于你