如何为不同的布局使用相同的RecyclerView适配器
我正在开发一个严重依赖于RecyclerView的应用程序。如何为不同的布局使用相同的RecyclerView适配器
我真的需要知道如何针对不同的项目布局使用相同的RecyclerView。布局的一个例子是:
1)的名称和描述列表项
2)与图像和名称的列表项
你可以看到它们是相似的,但有轻微更改布局。
提前致谢!
由于XML的recyclerview项目不依赖于那种你会在它膨胀的项目,你可以继续使用相同的回收视图布局文件的三个片段。
至于适配器,您的列表似乎是同质的(即单一类型的查看项目)。最好的做法是为每种情况使用3种不同的适配器。您可以自定义构造函数,为您的方便添加每种适配器的自定义帮助器方法。
现在,如果你有一个异构的列表中,你将不得不覆盖适配器getItemViewType()
和onCreateViewHolder()
和onBindViewHolder()
希望这有助于适当地使用这个! :)
我碰到类似的情况,这里是我遵循的模式。
首先,片段布局文件。
片段布局文件是不会更改所有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个片段做几乎同样的东西(得到回收观点,得到适配器,回收视图装饰和一些更多的操作等)。
创建延伸片段和overrided的onCreate onAttach的onDestroy等。由于只类型数据recyclerview消耗和适配器的将数据推至recycelrview将针对每个片段而改变,创建抽象函数getAdapter和模板化数据的AbstrctFragment。这三个片段中的每一个都将从这个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以及任何常见的memberfunctions和每个片段的成员变量。
现在RecyclerView布局文件。由于它们的布局各不相同,显然它们必须有所不同。
RecyclerViewAdapters:同样在这里共同的代码。将成员声明,CreateViewHolder(这里只布局名称改变其余全部代码是相同的),并且所有这些适配器的将共享的任何其他功能。 (像过滤列表项目)。
类似于我们是怎么做的片段,你可以记住这AbstractRecyclerViewAdapter并bindViewholder等抽象功能,并有3个不同的recyclerAdapters这会从这个AbstractRecyclerViewAdapter派生..
//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 :) –
为时已晚,但是,可能是有人需要帮助开发商 有益的适配器应该是这样的,你也可以在你的活动使用此示例
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以从适配器获取回调。 调用这些方法时,切换按钮从网格到列表,反之亦然
您需要提供有关您的应用的更多细节 - 否则很难给出推荐 – ligi