Android 将布局动态添加到另一个布局

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

我有一个RecyclerView适配器。在
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