如何使用相同的RecyclerView适配器用于不同的布局

时间:2015-07-21 11:18:14

标签: android android-recyclerview

我正在开发一个很大程度上依赖于RecyclerView使用的应用程序。

我真的需要知道如何对不同的项目布局使用相同的RecyclerView。布局的一个例子是:

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

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

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

提前致谢!

4 个答案:

答案 0 :(得分:5)

由于xml中的recyclerview项目并不依赖于您将在其中充气的项目类型,因此您可以继续使用相同的回收站视图布局文件来存储这三个片段。

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

现在,如果您有异构列表,则必须覆盖适配器中的getItemViewType(),并在onCreateViewHolder()onBindViewHolder()

中正确使用

希望这有帮助! :)

答案 1 :(得分:4)

我遇到了类似的情况,这是我所遵循的模型。

首先,片段布局文件

片段布局文件不会改变所有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的适配器将针对每个片段进行更改,因此需要为getAdapter创建一个抽象函数并对数据进行模板化。这三个片段中的每一个都将来自此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派生出来。

答案 2 :(得分:1)

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

// 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;
        }
    });
}

在您的活动中

UITableView

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

答案 3 :(得分:-1)

//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;
}