【问题标题】:How to use the same RecyclerView Adapter for different layouts如何为不同的布局使用相同的 RecyclerView Adapter
【发布时间】:2015-10-10 19:41:06
【问题描述】:

我正在开发一个严重依赖 RecyclerView 使用的应用程序。

我真的需要知道如何为不同的项目布局使用相同的 RecyclerView。布局示例如下:

1) 带有名称和描述的列表项

2) 带有图像和名称的列表项

您可以看到它们相似,但布局略有不同。

提前致谢!

【问题讨论】:

  • 您需要提供有关您的应用的更多详细信息 - 否则很难给出推荐

标签: android android-recyclerview


【解决方案1】:

由于 xml 中的 recyclerview 项目不依赖于您将在其中膨胀的项目类型,您可以继续为三个片段使用相同的 recycler view 布局文件。

至于适配器,您的列表似乎是同质的(即单一类型的视图项)。最好为每种情况使用 3 个不同的适配器。您可以自定义构造函数,根据您的方便为每种适配器添加自定义帮助方法。

现在,如果您有一个异构列表,则必须在适配器中覆盖 getItemViewType() 并在 onCreateViewHolder()onBindViewHolder() 中适当地使用它

希望这会有所帮助! :)

【讨论】:

    【解决方案2】:

    我遇到过类似的情况,这是我遵循的模式。

    首先,片段布局文件

    3个片段的片段布局文件都不会改变(基本上和列表片段类似),所以我为列表片段创建了一个模板文件。

    list_fragment_template.xml
    
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </FrameLayout>
    

    现在片段代码:

    在我的例子中,所有 3 个片段都做几乎相同的事情(获取回收器视图、获取适配器、回收器视图装饰和一些其他操作等)。

    创建了一个扩展片段的 AbstrctFragment 并覆盖了 onCreate onAttach onDestroy 等。由于只有类型的数据 recyclerview 消耗和适配器将数据推送到 recycelrview 会改变每个片段,创建一个抽象函数来获取适配器和模板化数据。这三个片段中的每一个都将派生自这个 AbstractFragment。

        public abstract class AbstractFragment<E> extends Fragment {
    
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
    
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.template_list_fragment, container, false);
    
    
                mRecyclerView = (RecyclerView) view.findViewById(R.id.list);
    
                // get adapter to show item list
                // and fetch data.
                mRecyclerAdapter = getAdapter();
                mRecyclerView.setAdapter(mRecyclerAdapter);
    
                // show it as vertical list
                mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
                // add seperator between list items.
                mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
    
    return view;
        }
    

    ... onAttach onDetach 以及每个片段的任何常见成员函数和成员变量。

    现在 RecyclerView 布局文件。由于它们的布局不同,显然它们一定是不同的。

    RecyclerViewAdapters:同样,这里的通用代码是成员声明、CreateViewHolder(这里只有布局名称更改,所有代码都相同)和所有这些适配器共享的任何其他函数。 (类似于过滤列表项)。

    与我们对片段所做的类似,您可以将其保留在 AbstractRecyclerViewAdapter 中,并将 bindViewholder 等作为抽象函数,并拥有 3 个不同的 recyclerAdapter 派生自此 AbstractRecyclerViewAdapter..

    【讨论】:

      【解决方案3】:

      为时已晚,但可能对有需要的开发人员有所帮助 您的适配器应如下所示,您也可以使用此示例添加页眉和页脚

      public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {
      
      // Declaring Variable to Understand which View is being worked on
      // IF the view under inflation and population is header or Item
      private static final int TYPE_HEADER = 0;
      private static final int TYPE_ITEM = 1;
      private static final int TYPE_FOOTER = 2;
      
      private Activity mContext;
      private ArrayList<DataModel> _mItems;
      private int mLayout;
      private String mProductHeadingTitle="Heading";
      private String mProductHeadingSubTitle="SubHeading";
      private String loadingText="LOADING";
      private int visibility= View.VISIBLE;
      
      public interface SampleAdapterInterface {
           void itemClicked(int position);
      }
      
      SampleAdapterInterface mCallBack;
      
      public SampleAdapter(Activity context, ArrayList<DataModel> items, int item_layout) {
          if (_mItems != null) {
              _mItems.clear();
          }
          this.mContext = context;
          this._mItems = items;
          this.mLayout = item_layout;
          mCallBack = (SampleAdapterInterface) context;
      }
      
      @Override
      public int getItemCount() {
          return _mItems.size()+2; // +2 for header and footer
      }
      
      @Override
      public int getItemViewType(int position) {
      
          if (position==0)
              return TYPE_HEADER;
          else if(position==(_mItems.size()+1))
              return TYPE_FOOTER;
      
          return TYPE_ITEM;
      }
      
      public void setHeaderData(String title,String subTitle)
      {
          this.mProductHeadingTitle=title;
          this.mProductHeadingSubTitle=subTitle;
      
          Log.d("LOG", "ProductHeadingTitle: " + mProductHeadingTitle);
          Log.d("LOG", "ProductHeadingSubTitle: " + mProductHeadingSubTitle);
      
          notifyDataSetChanged();
      }
      
      public void setFooterData(String loadingText,int visibility)
      {
          this.loadingText=loadingText;
          this.visibility=visibility;
      
          Log.d("LOG", "LoadingText: " + loadingText);
          Log.d("LOG", "Visibility: " + visibility);
      
          notifyDataSetChanged();
      }
      
      @Override
      public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      
      
          if (viewType == TYPE_HEADER)
          {
              View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_layout,parent,false);
      
              ViewHolder vhHeader = new ViewHolder(view,viewType);
      
              return vhHeader;
          }
          else if (viewType == TYPE_ITEM)
          {
              View view = LayoutInflater.from(parent.getContext()).inflate(mLayout,parent,false);
      
              //Creating ViewHolder and passing the object of type view
              ViewHolder vhItem = new ViewHolder(view,viewType);
      
              return vhItem;
          }
          else if (viewType == TYPE_FOOTER)
          {
              View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_lyout,parent,false);
      
              ViewHolder vhFooter = new ViewHolder(view,viewType);
      
              return vhFooter;
          }
          return null;
      }
      
      @Override
      public void onBindViewHolder(ViewHolder viewHolder, int pos) {
      
      
          if(viewHolder.Holderid ==0)
          {
              // header view
              Log.d("LOG", "in header binder");
              viewHolder.mProductCatalogTitle.setText(mProductHeadingTitle);
              viewHolder.mProductCatalogSubTitle.setText(mProductHeadingSubTitle);
          }
          else if(viewHolder.Holderid==1)
          {
              final int position=pos-1; // -1 to substract header number
              // your code
          }
          else if(viewHolder.Holderid==2)
          {
              // footer
              Log.d("LOG", "in footer binder");
              viewHolder.mProgressBar.setVisibility(visibility);
              viewHolder.mLoading.setText(loadingText);
          }
      
      
      }
      
      class ViewHolder extends RecyclerView.ViewHolder {
      
          int Holderid;
      
          // header
          TextView mProductCatalogTitle;
          TextView mProductCatalogSubTitle;
      
          //list
          // item type variable declaration
      
          // footer
          ProgressBar mProgressBar;
          TextView mLoading;
      
          public ViewHolder(View itemView, int viewType) {
              super(itemView);
              // Here we set the appropriate view in accordance with the the view type as passed when the holder object is created
              if(viewType == TYPE_HEADER)
              {
                  Holderid = 0;
                  mProductCatalogTitle = (TextView) itemView.findViewById(R.id.tv_title);
                  mProductCatalogSubTitle = (TextView) itemView.findViewById(R.id.tv_subtitle);
              }
              else if(viewType == TYPE_ITEM)
              {
                  Holderid = 1;
                  itemView.setClickable(true);
                  itemView.setOnClickListener(new OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          mCallBack.itemClicked(getAdapterPosition()-1);
                      }
                  });
                  // initialize the view holder
              }
      
              else if(viewType == TYPE_FOOTER)
              {
                  Holderid = 2;
                  mLoading = (TextView) itemView.findViewById(R.id.tv_loading);
                  mProgressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
              }
          }
      }
      

      在你的活动中

      // Adding to adapter as gridview when grid button clicked
      private void setProductGridAdapter() {
          mListViewTab.setVisibility(View.VISIBLE);
          mGridViewTab.setVisibility(View.INVISIBLE);
      
          mSampleAdapter = new SampleAdapter(YourActicity.this,
                  yourlist,R.layout.item_product_grid);
          mRecyclerView.setAdapter(mSampleAdapter);
      
          mRecyclerView.setHasFixedSize(true);
      
          final GridLayoutManager layoutManager = new GridLayoutManager(getActivity(),
                  2,                              //number of columns
                  LinearLayoutManager.VERTICAL,   // orientation
                  false);                         //reverse layout
          mRecyclerView.setLayoutManager(layoutManager);
      
          layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
              @Override
              public int getSpanSize(int position) {
      
                  // to show header and footer in full row
                  if(position==0 || position==(yourlist.size()+1))
                      return layoutManager.getSpanCount();
                  else
                      return 1;
              }
          });
      
          mRecyclerView.scrollToPosition(AppController.currentPosition);
      
          mSampleAdapter.notifyDataSetChanged();
      
          // Scroll listener for RecyclerView to call load more products
          mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
      
              @Override
              public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
      
                  int visibleItemCount = layoutManager.getChildCount();
                  int totalItemCount = layoutManager.getItemCount();
                  int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
      
                  int lastInScreen = firstVisibleItem + visibleItemCount;
                  if ((lastInScreen >= totalItemCount) && !isLoading) {
                      //last item
                      // do something after last item like load more code or 
                      // show No more items string
                      mSampleAdapter.setFooterData("NO More Items",View.INVISIBLE);
                  }
                  AppController.currentPosition = firstVisibleItem;
              }
          });
      
      }
      
      // Adding to adapter as listview when list button clicked
      private void setProductListAdapter() {
          mListViewTab.setVisibility(View.INVISIBLE);
          mGridViewTab.setVisibility(View.VISIBLE);
      
          mSampleAdapter = new SampleAdapter(YourActicity.this, yourlist,R.layout.item_product_list);
          mRecyclerView.setAdapter(mSampleAdapter);
      
          mRecyclerView.setHasFixedSize(true);
      
          final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(),
                  LinearLayoutManager.VERTICAL,   // orientation
                  false);                         //reverse layout
          mRecyclerView.setLayoutManager(layoutManager);
      
          mRecyclerView.scrollToPosition(AppController.currentPosition);
          mSampleAdapter.notifyDataSetChanged();
      
          // Scroll listener for RecyclerView to call load more products
          mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
      
              @Override
              public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
      
                  int visibleItemCount = layoutManager.getChildCount();
                  int totalItemCount = layoutManager.getItemCount();
                  int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
      
                  int lastInScreen = firstVisibleItem + visibleItemCount;
                  if ((lastInScreen >= totalItemCount) && !isLoading) {
                      //last item
                      // do something after last item like load more code or 
                      // show No more items string
                      mSampleAdapter.setFooterData("NO MOre Items",View.INVISIBLE);
                  }
                  AppController.currentPosition = firstVisibleItem;
              }
          });
      }
      

      并且您的活动必须在活动中实现 SampleAdapterInterface 才能从适配器获取回调。 将按钮从网格切换到列表时调用这些方法,反之亦然

      【讨论】:

        【解决方案4】:
        //To setViewType maybe is a solution for you.Sample below:  
        private static final int TYPE_DESC = 0;
        private static final int TYPE_IMAGE = TYPE_DESC + 1;
        private static final int TYPE_THREE_TEXT = TYPE_IMAGE + 1;
        public int getItemViewType(int position) {
            int type = super.getItemViewType(position);
            try
            {
                type = Integer.parseInt(data.get(position).get("type"));
            } catch (Exception e)
            {
                e.printStackTrace();
            }
            return type;
        }
        
        public int getViewTypeCount() {
            return 3;
        }
        public View getView(int position, View convertView, ViewGroup parent) {
            int type = TYPE_DESC;
            try
            {
                type = Integer.parseInt(data.get(position).get("type"));
            } catch (Exception e)
            {
                e.printStackTrace();
            }
            ViewHolder holder = null;
            if (convertView == null)
            {
                System.out.println("getView::convertView is null");
                holder = new ViewHolder();
                switch (type)
                {
                    case TYPE_DESC:
                        convertView = View.inflate(getBaseContext(),
                                R.layout.listitem_1, null);
                        break;
                    case TYPE_IMAGE:
                        convertView = View.inflate(getBaseContext(),
                                R.layout.listitem_2, null);
                        break;
                    case TYPE_THREE_TEXT:
                        convertView = View.inflate(getBaseContext(),
                                R.layout.listitem_3, null);
                        break;
                }
                convertView.setTag(holder);
            }
            else
            {
                holder = (ViewHolder) convertView.getTag();
            }
            //TODO
            return convertView;
        }
        

        【讨论】:

        • 这不是 RecyclerView.Adapter 子类。 OP 特别需要 RecyclerView 的帮助 :)
        猜你喜欢
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 2021-02-02
        • 2016-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        相关资源
        最近更新 更多