根据数据内容创建 RecyclerView 项目布局
Create RecyclerView item layout based on content of data
我正在创建数据 object 的回收视图,每个 object 都会有所不同,例如
对象 1
- 字符串标题
- 字符串描述
- 图片
目标 2
- 字符串描述
目标 3
- 图片
- 字符串 Link
目标 4
- 字符串描述
- 视频
等等
所以我需要动态创建项目布局以适应每个数据object。我不想创建包含所有可能的视图和组件的项目布局并显示和隐藏,因为我觉得这是不好的做法。
所以我的问题是我需要使用 onBindViewHolder 中的位置访问列表中的 object,以便在 ViewHolder class.
中构建我的布局
我尝试使用一种在 onBindViewHolder class 中调用并传入 object 的方法,在该方法中我将自定义视图添加到数组中,同时设置其中的内容但是这个没用。
有谁知道如何做到这一点?
此致
在您的适配器中 class 您应该进行以下更改:
在您的情况下,您应该覆盖 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
中检查项目类型,然后加载数据。
希望对你有帮助
首先你要像这里解释的那样正确地实现视图类型 How to create RecyclerView with multiple view type?
实际上,你的问题是重复的,但我会写一些额外的组织材料来帮助你处理更多的持有人。
关于这个答案,我将使用 ButterKnife 和 Picasso libraris,因为它们很棒:http://jakewharton.github.io/butterknife/ and http://square.github.io/picasso/
在您的项目上创建一个包holders
,然后将您放入其中的所有视图持有者,下面是持有者的示例:
用public void bindData(Data data)
创建一个AbstractHolder
,然后你的适配器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 ...
}
结论:
使用此方法,您的适配器 class 只是一个 "distribution center" 可能的类型和每种类型 "knows" 如何创建自身以及如何处理其数据。
这使您的代码易于维护且组织良好。
我正在创建数据 object 的回收视图,每个 object 都会有所不同,例如
对象 1 - 字符串标题 - 字符串描述 - 图片
目标 2 - 字符串描述
目标 3 - 图片 - 字符串 Link
目标 4 - 字符串描述 - 视频
等等
所以我需要动态创建项目布局以适应每个数据object。我不想创建包含所有可能的视图和组件的项目布局并显示和隐藏,因为我觉得这是不好的做法。
所以我的问题是我需要使用 onBindViewHolder 中的位置访问列表中的 object,以便在 ViewHolder class.
中构建我的布局我尝试使用一种在 onBindViewHolder class 中调用并传入 object 的方法,在该方法中我将自定义视图添加到数组中,同时设置其中的内容但是这个没用。
有谁知道如何做到这一点?
此致
在您的适配器中 class 您应该进行以下更改:
在您的情况下,您应该覆盖 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
中检查项目类型,然后加载数据。
希望对你有帮助
首先你要像这里解释的那样正确地实现视图类型 How to create RecyclerView with multiple view type? 实际上,你的问题是重复的,但我会写一些额外的组织材料来帮助你处理更多的持有人。
关于这个答案,我将使用 ButterKnife 和 Picasso libraris,因为它们很棒:http://jakewharton.github.io/butterknife/ and http://square.github.io/picasso/
在您的项目上创建一个包
holders
,然后将您放入其中的所有视图持有者,下面是持有者的示例:用
public void bindData(Data data)
创建一个AbstractHolder
,然后你的适配器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 ...
}
结论:
使用此方法,您的适配器 class 只是一个 "distribution center" 可能的类型和每种类型 "knows" 如何创建自身以及如何处理其数据。
这使您的代码易于维护且组织良好。