从布局创建具有多个视图的RecyclerView [英] Create a RecyclerView with multiple view from layouts

查看:69
本文介绍了从布局创建具有多个视图的RecyclerView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在一个RecyclerView中使用2种布局

I am trying to have 2 layout in one RecyclerView

我有一个称为Bookmark的回收站视图列表,它是从xml中解析出来的,并且都可以正常工作,但是我想在此回收站视图中放置另一个包含按钮且可以单击的布局. 就像照片中的图标一样,图标来自recyclerview,加号按钮必须与列表兼容,如果列表较大或较小,则按钮将与列表空间兼容.

I have a recycler view list which is called Bookmark and it is parsed from an xml and this is all working , but I wanna in this recyclerview to put another layout which contains a button and that can be clickable. Like in the photo the icons are from recyclerview and the plus button need to be compatible with the list, if the list is larger or smaller the button will be compatible with the space of list.

这是我的适配器新代码,具体取决于答案@LluisFelisart 这是错误 ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)

This is my new code for the Adapter which depends on the answer @LluisFelisart And this is the error ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)

    public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    ArrayList<Bookmark> arrayList = new ArrayList<>();

    public MyAdapter(Context context, ArrayList<Bookmark> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }

    public class ViewHolder0 extends RecyclerView.ViewHolder {

        TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
        ImageView tvIcon;

        public ViewHolder0(@NonNull  View itemView) {
            super(itemView);

            tvName=itemView.findViewById(R.id.textView);
            tvIcon = itemView.findViewById(R.id.image_view);
         /*   tvId=itemView.findViewById(R.id.tvId);
            tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
            tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
        }
    }

    public class ViewHolder2 extends RecyclerView.ViewHolder {
        ImageView tvAddBookmark;

        public ViewHolder2(@NonNull View itemView) {
            super(itemView);
            tvAddBookmark = itemView.findViewById(R.id.image_button_add);
        }
    }
    @Override
    public int getItemViewType(int position) {
        // Just as an example, return 0 or 2 depending on position
        // Note that unlike in ListView adapters, types don't have to be contiguous
        return position % 2 * 2;
    }




    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.grid_item, viewGroup, false);

        switch (i) {
            case 0: return new ViewHolder0(viewGroup);
            case 2: return new ViewHolder2(viewGroup);
        }

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        switch (holder.getItemViewType()) {
            case 0:
                ViewHolder0 viewHolder0 = (ViewHolder0) holder;
                ((ViewHolder0) holder).tvName.setText(arrayList.get(position).getName());
                ((ViewHolder0) holder).tvIcon.setImageResource(arrayList.get(position).getIcon());
                break;

            case 2:
                ViewHolder2 viewHolder2 = (ViewHolder2) holder;

        }
        ((ViewHolder0) holder).tvIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent;
                intent = new Intent(context, BookmarkActivity.class);
                v.getContext().startActivity(intent);
            }
        });

        ((ViewHolder0) holder).tvIcon.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Intent intent = new Intent(context, ActivityBookmarksFavorites.class);
                v.getContext().startActivity(intent);
                return false;
            }
        });
    }




    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder  {

        TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
        ImageView tvIcon;

        public ViewHolder(@NonNull  View itemView) {
            super(itemView);

            tvName=itemView.findViewById(R.id.textView);
            tvIcon = itemView.findViewById(R.id.image_view);
         /*   tvId=itemView.findViewById(R.id.tvId);
            tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
            tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
        }



    }



}

这是网格项目的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    android:visibility="visible"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:id="@+id/image_view"
        style="@style/BookmarkIconIv" />
    <TextView android:id="@+id/textView"
        android:layout_marginTop="1.0dip"
        style="@style/BookmarkTextTv" />
</LinearLayout>

这是我想在回收站视图中显示的按钮的布局

This is the layout of button which I want to be in the recycler view

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageButton
        android:id="@+id/image_button_add"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:src="@drawable/ic_add_black_24dp"
        android:background="@color/transparent" />

</android.support.constraint.ConstraintLayout>

这是在回收站视图中显示的片段

This is the Fragment which the recycler view it is shown

public class FragmentBookmark extends Fragment {
    ArrayList<Bookmark> arrayList = new ArrayList<>();
    XmlPullParser pullParser;
    MyAdapter myAdapter;
    View paramView;
    RecyclerView myRecyclerView;
    private Context mContext;
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }
    @Nullable
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       paramView = inflater.inflate(R.layout.bookmark, container, false);

        myRecyclerView =  paramView.findViewById(R.id.myRecyclerView);
        myRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4));
        myRecyclerView.setHasFixedSize(true);
        myAdapter = new MyAdapter(mContext, arrayList);
        myRecyclerView.setAdapter(myAdapter);
        try {
            XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
            while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
                if (xpp.getEventType() == XmlPullParser.START_TAG) {
                    if (xpp.getName().equals("Bookmark")) {
                        Bookmark bookmark = new Bookmark();
                        bookmark.setName(xpp.getAttributeValue(null, "name"));
                        int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"),"drawable", mContext.getPackageName());
                        bookmark.setIcon(drawableResourceId);
                        arrayList.add(bookmark);
                    }
                }
                xpp.next();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        myAdapter.notifyDataSetChanged();
        return paramView;
    }
    }

这是包含recyclerview的布局书签

This is the layout bookmark which contains recyclerview

<LinearLayout android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/myRecyclerView"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:fillViewport="false">

    </android.support.v7.widget.RecyclerView>

</LinearLayout>

推荐答案

这是答案

按照此步骤

示例代码

layout.layout_one

layout.layout_one

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:cardCornerRadius="15dp"
    app:cardElevation="5dp"
    app:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="Name  : " />

            <TextView
                android:id="@+id/tvName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="Icon  : " />

            <ImageView
                android:id="@+id/tvIcon"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:padding="10dp"
                android:text="" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="Id  : " />

            <TextView
                android:id="@+id/tvId"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="SearchUrl  : " />

            <TextView
                android:id="@+id/tvSearchUrl"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="NativeUrl  : " />

            <TextView
                android:id="@+id/tvNativeUrl"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="" />

        </LinearLayout>

    </LinearLayout>

</android.support.v7.widget.CardView>

layout.button_two

layout.button_two

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imgButton"
        android:layout_width="50dp"
        android:layout_height="50dp" />
</LinearLayout>

现在您需要为两个viewType创建两个RecyclerView.ViewHolder

现在,您需要覆盖 getItemViewType()

  • it返回位于位置的项目的viewType,以用于视图回收.
  • Now you need to create two RecyclerView.ViewHolder for your both viewType

    Now you need to Override getItemViewType()

    • it Return the viewType of the item at position for the purposes of view recycling.
    • 这是具有多种视图类型的 RecyclerView.Adapter 的示例代码

      here is the sample code of RecyclerView.Adapter with multiple view types

      DataAdapter

      import android.content.Context;
      import android.support.annotation.NonNull;
      import android.support.v7.widget.RecyclerView;
      import android.view.LayoutInflater;
      import android.view.View;
      import android.view.ViewGroup;
      import android.widget.ImageView;
      import android.widget.TextView;
      import java.util.ArrayList;
      
      public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
      
          private Context context;
          ArrayList<Bookmark> arrayList = new ArrayList<>();
          public static final int ITEM_TYPE_ONE = 0;
          public static final int ITEM_TYPE_TWO = 1;
      
          public DataAdapter(Context context, ArrayList<Bookmark> arrayList) {
              this.context = context;
              this.arrayList = arrayList;
          }
      
          @NonNull
          @Override
          public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
      
              View view = null;
              // check here the viewType and return RecyclerView.ViewHolder based on view type
              if (viewType == ITEM_TYPE_ONE) {
                  view = LayoutInflater.from(context).inflate(R.layout.layout_one, parent, false);
                  return new ViewHolder(view);
              } else if (viewType == ITEM_TYPE_TWO) {
                  view = LayoutInflater.from(context).inflate(R.layout.button_two, parent, false);
                  return new ButtonViewHolder(view);
              }else {
                  return  null;
              }
      
          }
      
          @Override
          public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
      
              final int itemType = getItemViewType(position);
              // First check here the View Type
              // than set data based on View Type to your recyclerview item
              if (itemType == ITEM_TYPE_ONE) {
                  ViewHolder viewHolder = (ViewHolder) holder;
                  viewHolder.tvName.setText(arrayList.get(position).getName());
                  viewHolder.tvIcon.setImageResource(arrayList.get(position).getIcon());
                  viewHolder.tvSearchUrl.setText(arrayList.get(position).getSearchUrl());
                  viewHolder.tvNativeUrl.setText(arrayList.get(position).getNativeUrl());
              } else if (itemType == ITEM_TYPE_TWO) {
                  ButtonViewHolder buttonViewHolder = (ButtonViewHolder) holder;
                  buttonViewHolder.imgButton.setImageResource(arrayList.get(position).getIcon());
              }
      
          }
      
          @Override
          public int getItemViewType(int position) {
              // based on you list you will return the ViewType 
              if (arrayList.get(position).getViewType() == 0) {
                  return ITEM_TYPE_ONE;
              } else {
                  return ITEM_TYPE_TWO;
              }
          }
      
          @Override
          public int getItemCount() {
              return arrayList.size();
          }
      
          public class ViewHolder extends RecyclerView.ViewHolder {
      
              TextView tvName, tvId, tvSearchUrl, tvNativeUrl;
      
              ImageView tvIcon;
      
              public ViewHolder(@NonNull View itemView) {
                  super(itemView);
      
                  tvName = itemView.findViewById(R.id.tvName);
                  tvIcon = itemView.findViewById(R.id.tvIcon);
                  tvId = itemView.findViewById(R.id.tvId);
                  tvSearchUrl = itemView.findViewById(R.id.tvSearchUrl);
                  tvNativeUrl = itemView.findViewById(R.id.tvNativeUrl);
              }
          }
      
          public class ButtonViewHolder extends RecyclerView.ViewHolder {
      
      
              ImageView imgButton;
      
              public ButtonViewHolder(@NonNull View itemView) {
                  super(itemView);
      
                  imgButton = itemView.findViewById(R.id.imgButton);
      
              }
          }
      }
      

      在列表中添加数据时,您需要在列表中提供viewtype.

      在您的Bookmark POJO类中进行一些更改

      When you adding data in your list you need to provide the viewtype in list

      Make some changes in your Bookmark POJO class

      Bookmark POJO类

      public class Bookmark
      {
          String name,id,nativeUrl,searchUrl;
          int icon;
      
          int viewType;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public String getId() {
              return id;
          }
      
          public void setId(String id) {
              this.id = id;
          }
      
          public int getIcon() {
              return icon;
          }
      
          public void setIcon(int icon) {
              this.icon = icon;
          }
      
          public String getNativeUrl() {
              return nativeUrl;
          }
      
          public void setNativeUrl(String nativeUrl) {
              this.nativeUrl = nativeUrl;
          }
      
          public String getSearchUrl() {
              return searchUrl;
          }
      
          public void setSearchUrl(String searchUrl) {
              this.searchUrl = searchUrl;
          }
      
          public int getViewType() {
              return viewType;
          }
      
          public void setViewType(int viewType) {
              this.viewType = viewType;
          }
      
          @Override
          public String toString() {
              return "Bookmark{" +
                      "name='" + name + '\'' +
                      ", icon='" + icon + '\'' +
                      ", id='" + id + '\'' +
                      ", nativeUrl='" + nativeUrl + '\'' +
                      ", searchUrl='" + searchUrl + '\'' +
                      '}';
          }
      }
      

      示例活动代码

      Sample activity code

      import android.content.Context;
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
      import android.support.v7.widget.LinearLayoutManager;
      import android.support.v7.widget.RecyclerView;
      import android.util.Log;
      
      import org.xmlpull.v1.XmlPullParser;
      import org.xmlpull.v1.XmlPullParserException;
      
      import java.io.IOException;
      import java.util.ArrayList;
      
      public class MainActivity extends AppCompatActivity {
      
          private Context mContext;
          ArrayList<Bookmark> arrayList = new ArrayList<>();
      
          RecyclerView myRecyclerView;
          DataAdapter dataAdapter;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
      
              mContext = this;
      
              myRecyclerView = findViewById(R.id.myRecyclerView);
              myRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
              myRecyclerView.setHasFixedSize(true);
      
              dataAdapter = new DataAdapter(mContext, arrayList);
              myRecyclerView.setAdapter(dataAdapter);
      
              try {
      
                  XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
      
                  while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
                      if (xpp.getEventType() == XmlPullParser.START_TAG) {
                          if (xpp.getName().equals("Bookmark")) {
      
                              Log.e("MY_VALUE", " * " + xpp.getAttributeValue(0) + " * ");
                              Log.e("MY_VALUE", " * " + xpp.getAttributeValue(1) + " * ");
                              Log.e("MY_VALUE", " * " + xpp.getAttributeValue(5) + " * ");
                              Log.e("MY_VALUE", " * " + xpp.getAttributeValue(2) + " * ");
                              Log.e("MY_VALUE", " * " + xpp.getAttributeValue(3) + " * ");
                              Log.e("MY_VALUE", " * " + xpp.getAttributeValue(4) + " * ");
      
      
                              Bookmark bookmark = new Bookmark();
                              bookmark.setName(xpp.getAttributeValue(0));
      
                              int drawableResourceId = this.getResources().getIdentifier(xpp.getAttributeValue(1), "drawable", mContext.getPackageName());
                              bookmark.setIcon(drawableResourceId);
      
                              bookmark.setId(xpp.getAttributeValue(2));
      
                              bookmark.setSearchUrl(xpp.getAttributeValue(3));
                              bookmark.setNativeUrl(xpp.getAttributeValue(4));
      
                              // here you need to set view type
                              bookmark.setViewType(0);
                              arrayList.add(bookmark);
                          }
                      }
      
                      xpp.next();
                  }
              } catch (XmlPullParserException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              // here i have added second viewType
              // you need to set as per your requirement
              Bookmark bookmark = new Bookmark();
              bookmark.setViewType(1);
              bookmark.setIcon(R.drawable.dishu);
              arrayList.add(bookmark);
              dataAdapter.notifyDataSetChanged();
      
          }
      
      
      }
      

      注意

      在下面的代码中,我在Arraylist的最后一个索引处设置了第二个viewType 您需要根据需要设置viewType

      NOTE

      In the below code i have set second viewType at the last index of Arraylist you need to set viewType as per your requirement

      有关更多信息,您可以查看以下文章

      For more information you can check below articles

      • Working with RecyclerView and multiple view types
      • A RecyclerView with multiple item types
      • Android RecyclerView with Different Child Layouts
      • Android Pagination Tutorial—Handling Multiple View Types
      • Heterogenous Layouts inside RecyclerView
      • Android RecyclerView Example – Multiple ViewTypes
      • How to create RecyclerView with multiple view type?
      • Android Multiple row layout using RecyclerView

      这篇关于从布局创建具有多个视图的RecyclerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆