Android 将布局动态添加到另一个布局
我有一个RecyclerView适配器。在Android 将布局动态添加到另一个布局,android,android-layout,android-activity,android-xml,android-recyclerview,Android,Android Layout,Android Activity,Android Xml,Android Recyclerview,我有一个RecyclerView适配器。在onBindViewHolder中,我检查传递给适配器的每个项目有多少个图像。根据图像的数量,我希望将子布局加载/充气到主布局中 例如: 如果项目有一个图像,我需要将images\u one.xml充气到主布局中 如果项目有2个图像,我需要将images\u two.xml充气到主布局中 etc,最多8个图像(images\uheight.xml) 这是主布局,main\u layout.xml: <LinearLayout xmlns
onBindViewHolder
中,我检查传递给适配器的每个项目有多少个图像。根据图像的数量,我希望将子布局加载/充气到主布局中
例如:
- 如果项目有一个图像,我需要将
充气到主布局中images\u one.xml
- 如果项目有2个图像,我需要将
充气到主布局中images\u two.xml
- etc,最多8个图像(
)images\uheight.xml
main\u layout.xml
:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
// INFLATE CHILD LAYOUT HERE (images_one.xml, images_two.xml, etc.)
<TextView
android:id="@+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/image_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
最后,这是我的RecyclerView适配器:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private static Context context;
private List<Message> mDataset;
public RecyclerAdapter(Context context, List<Message> myDataset) {
this.context = context;
this.mDataset = myDataset;
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener, View.OnClickListener {
public TextView title;
public TextView desc;
public ViewHolder(View view) {
super(view);
view.setOnCreateContextMenuListener(this);
title = (TextView) view.findViewById(R.id.title);
desc = (TextView) view.findViewById(R.id.desc);
}
}
@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_layout, parent, false);
ViewHolder vh = new ViewHolder((LinearLayout) view);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message item = mDataset.get(position);
holder.title.setText(item.getTitle());
holder.desc.setText(item.getDesc());
int numImages = item.getImages().size();
if (numImages == 1) {
// Inflate images_one.xml into main_layout.xml
} else if (numImages == 2) {
// Inflate images_two.xml into main_layout.xml
} else if (numImages == 3) {
// Inflate images_three.xml into main_layout.xml
}
// ETC...
}
@Override
public int getItemCount() {
return mDataset.size();
}
}
公共类RecyclerAdapter扩展了RecyclerView.Adapter{
私有静态语境;
私有列表数据集;
公共RecyclerAdapter(上下文,列表myDataset){
this.context=上下文;
this.mDataset=myDataset;
}
公共静态类ViewHolder扩展了RecyclerView.ViewHolder实现了View.OnCreateContextMenuListener、View.OnClickListener{
公共文本视图标题;
公共文本视图描述;
公共视图持有者(视图){
超级(视图);
view.setOnCreateContextMenuListener(此);
title=(TextView)view.findViewById(R.id.title);
desc=(TextView)view.findViewById(R.id.desc);
}
}
@凌驾
public RecyclerAdapter.ViewHolder onCreateViewHolder(视图组父级,int-viewType){
View=LayoutFlater.from(parent.getContext()).flate(R.layout.main\u布局,parent,false);
ViewHolder vh=新的ViewHolder((线性布局)视图);
返回vh;
}
@凌驾
公共无效onBindViewHolder(ViewHolder,int位置){
消息项=mDataset.get(位置);
holder.title.setText(item.getTitle());
holder.desc.setText(item.getDesc());
int numImages=item.getImages().size();
如果(numImages==1){
//将images_one.xml充气到main_layout.xml中
}else if(numImages==2){
//将images_two.xml充气到main_layout.xml中
}else if(numImages==3){
//将images_three.xml膨胀到main_layout.xml中
}
//等等。。。
}
@凌驾
public int getItemCount(){
返回mDataset.size();
}
}
实现这一点的最佳方法是什么?Android打算使用的
ViewHolder
s方法是在onCreateViewHolder()
中创建/膨胀视图,然后在onBindViewHolder()中填充适配器数据。这一点很重要,因为只有在没有可回收的内容时才会调用onCreateViewHolder()
与列表视图
不同,回收视图
实际上是回收视图持有者
s,而不是视图
s。因此,尝试在onBindViewHolder()
中膨胀视图是行不通的
请注意,onCreateViewHolder()
中的viewType
参数?这是关键
首先,您需要覆盖适配器中的getItemViewType()
。让我们在这里抄近路;由于视图类型是一个int
,因此我们只使用项目中的图像数作为视图类型:
@Override
public int getItemViewType(int position) {
// ... return the number of images for data at position
}
(通常我会定义要返回的final int
s,如VIEW\u TYPE\u ONE\u IMAGE
等,这是正确的方法。)
适配器如何使用视图类型?如果位置0处的数据的视图类型为4,则RecyclerView
将仅将在onCreateViewHolder()中创建的ViewHolder
与viewType==4
传递到onBindViewHolder()
与position==0
现在,您的onCreateViewHolder()
可能如下所示:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_layout, parent, false);
return new ViewHolder(view, viewType);
}
(仅供参考:onCreateViewHolder()
的返回类型应该是您的ViewHolder
类型,而不是RecyclerView
s。)
请注意,我在ViewHolder
构造函数中添加了一个viewType
参数:
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener, View.OnClickListener {
public TextView title;
public TextView desc;
public ImageView img1;
public ImageView img2;
public ViewHolder(View view, int viewType) {
super(view);
view.setOnCreateContextMenuListener(this);
title = (TextView) view.findViewById(R.id.title);
desc = (TextView) view.findViewById(R.id.desc);
ViewGroup placeholder = (ViewGroup) view.findViewById(R.id.placeholder);
// here you can use the viewType to help you figure
// out which child views you need references for
switch (viewType) {
case 1:
// ...
break;
case 2:
LayoutInflater.from(parent.getContext()).inflate(R.layout.images_two, placeholder); // this combines inflate() and addView()
img1 = placeholder.findViewById(R.id.image_one);
img2 = placeholder.findViewById(R.id.image_two);
break;
// ...
}
}
}
如果在所有不同的视图中使用相同的ID,那么在构造函数中不一定需要viewType
;您只需在onBindViewHolder()
中检查它们是否为空
如果有许多不同的视图类型,组织创建/绑定代码的一个好方法是将ViewHolder
子类抽象化,为每个视图类型进一步将其子类化为不同的类型,然后在onCreateViewHolder()
中返回相应类型的实例。在抽象类型中声明一个抽象方法,如public void bind(yourtItemType item)
,并在子类中实现,那么您的onBindViewHolder()
方法就是:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(data.get(position)); // ... or however you access an item at position
}
…并且创建如下所示:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
switch (viewType) {
case 1:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.images_one, parent, false);
return new OneImageViewHolder(view);
case 2:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.images_two, parent, false);
return new TwoImageViewHolder(view);
// ... etc. etc.
}
}
别忘了,在onBindViewHolder()
中可能会传递一个回收的ViewHolder
,因此您必须假设所有视图都是“脏的”并将每个子视图设置为位置的数据的已知状态
您是否尝试过如何在RecyclerView适配器中实现它?将其充气到您的ViewHolder中的itemView中。如果在ViewHolder中充气,则无法检查该项目有多少图像。onBindViewHolder中的支架(ViewHolder,int position)
这是一个非常糟糕的答案,但我有一个顾虑。main_layout.xml发生了什么事?
?看起来,使用您的方法,我需要创建8个不同的“main layout”(每个图像数对应一个),其中每个布局除了图像部分外都完全相同?正确吗?不。我只是为答案编写了一些简化的代码。其思想是,使用视图类型,可以根据列表项的需要创建不同的视图。我将更新答案以包括main_layout.xml。好的,我更新了代码,但不确定spe无论如何,策略是膨胀主视图,膨胀图像视图b