Android 基于数据内容创建RecyclerView项布局
我正在创建一个数据对象的回收器视图,每个对象都会有所不同,例如 Obj 1 -字符串标题 -字符串描述 -形象 Obj 2 -字符串描述 Obj 3 -形象 -串链 Obj 4 -字符串描述 -录像带 等 因此,我需要动态创建项目布局,以适应每个数据对象。我不想创建一个包含所有可能视图和组件的项目布局,也不想显示和隐藏,因为我觉得这是一个糟糕的做法 因此,我的问题是我需要使用onBindViewHolder中的位置访问列表中的对象,以便在ViewHolder类中构造布局 我尝试使用一个方法,我在onBindViewHolder类中调用了该方法,并传入了一个对象,在该对象中我将自定义视图添加到数组中,同时设置了数组中的内容,但这不起作用 有人知道如何做到这一点吗Android 基于数据内容创建RecyclerView项布局,android,android-layout,android-recyclerview,Android,Android Layout,Android Recyclerview,我正在创建一个数据对象的回收器视图,每个对象都会有所不同,例如 Obj 1 -字符串标题 -字符串描述 -形象 Obj 2 -字符串描述 Obj 3 -形象 -串链 Obj 4 -字符串描述 -录像带 等 因此,我需要动态创建项目布局,以适应每个数据对象。我不想创建一个包含所有可能视图和组件的项目布局,也不想显示和隐藏,因为我觉得这是一个糟糕的做法 因此,我的问题是我需要使用onBindViewHolder中的位置访问列表中的对象,以便在ViewHolder类中构造布局 我尝试使用一个方法,我在
关于在适配器类中,您应该执行以下更改: 在您的情况下,应该重写
getItemViewType
方法
@Override
public int getItemViewType(int position) {
if (position < arrayList.size()) {
return ITEM_X_TYPE;
} else
return ITEM_Y_TYPE;
}
在onBindViewHolder
中执行以下操作:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof XVH) {
XVH m = (XVH) holder;
... (continue your code)
编辑:
现在我建议您在onCreateViewHolder
中执行以下smth:
@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");
}
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
}
在这里,您创建了一个视图,并将其传递给视图持有者,然后创建视图持有者调用不同构造函数的不同实例
然后在VH构造器中,您执行如下smth:
@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");
}
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
中,检查项目类型,然后加载数据
我希望这对您有所帮助首先,您需要实现正确的视图类型,如本文所述 事实上,你的问题是重复的,但我会写一些额外的组织材料来帮助你处理更多的持有者
- 在这个答案上,我将使用巴特诺夫和毕加索的天秤座,因为它们很棒
- 在您的项目上创建一个包
,然后在其中放置所有视图holder,下面是holder的示例:holder
- 使用
创建一个public void bindData(数据数据)
,这样您的适配器AbstractHolder
:就扩展了RecyclerView.adapter
@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");
}
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);
}
}
- 那么您的适配器代码将是:
这使您的代码易于维护,并且组织良好。Duplicate of:@DeanWild它不是一个副本,我正在尝试动态创建布局,据我所知,这些答案建议创建多个ViewHolder它完全是重复的。你认为你想要达到的是坏习惯。创建单独的视图保持架、单独的布局文件并正确执行
getItemViewType
是最佳做法正确答案。@Budius我将有20多种视图类型,因此我应该创建20多种布局并创建20多种视图保持架?@DJ-DOO是。试着想象一下,使用20多种变体并试图通过Java动态生成来管理所有变体将是一场维护噩梦。使用单独的视图持有者和单独的XML,它变得简单得多。在您的项目上创建一个漂亮的包holders
,并将所有的ViewHolders放在那里。每个视图持有者可以有一个setData(Object)
方法,并且在内部持有者“知道”如何正确使用该数据。但是我将有20多个变体。你是说我有20多个视图持有者吗?!好的,我明白了,那么你可以有一个VH,然后根据你的数据,你可以创建不同的VH构造函数
,从java构建视图,并从XML
@Utlimo\m抱歉,我不完全理解。我不应该在onCreateViewHolder中膨胀布局吗?我应该创建20多个布局吗?你能给我举个例子吗……对不起,我只是不太明白it@DJ-DOO检查我编辑的答案如果对你有帮助,你可以根据你的项目彼此的相似程度使用这两种解决方案,这是非常好的,在将您的示例与Butterknife的使用集成之后,我在我的小部件上得到了空指针。我将编辑我的OP以显示实现Don't。如果您在使用该库时遇到困难,请阅读文档或干脆不使用它。但这真的不再是你最初问题的一部分了。我们能用Android数据绑定代替ButterKnife吗?