来自https://developer.android.com/preview/material/ui-widgets.html
当我们创建 RecyclerView.Adapter
时,我们必须指定将与适配器绑定的 ViewHolder
.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private String[] mDataset;
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false);
//findViewById...
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
@Override
public int getItemCount() {
return mDataset.length;
}
}
那么,是否可以使用多种视图类型创建 RecyclerView
?
11 回答
下面不是伪代码,我测试了它,它对我有用 .
我想在recyclelerview中创建一个headerview,然后在 Headers 下方显示一个用户可以单击的图片列表 .
我在代码中使用了一些开关,不知道这是否是最有效的方法,所以请随意发表您的意见:
按照Anton的解决方案,拿出这个
ViewHolder
来保存/处理/委托不同类型的布局 . 但是当回收视图的ViewHolder
不是数据卷的类型时,不确定替换新布局是否有效 .所以基本上,只有在需要新的视图布局时才会调用
onCreateViewHolder(ViewGroup parent, int viewType)
;将为
viewType
调用getItemViewType(int position)
;在回收视图时总是调用
onBindViewHolder(ViewHolder holder, int position)
(引入新数据并尝试使用ViewHolder
显示) .因此,当调用
onBindViewHolder
时,它需要放入右视图布局并更新ViewHolder
.替换视图布局是否正确引入
ViewHolder
或任何问题?感谢任何评论!Edit: ViewHolder具有成员mItemViewType来保存视图
Edit: 看起来像onBindViewHolder(ViewHolder holder,int position)传入的ViewHolder已经通过查看getItemViewType(int position)来获取(或创建)以确保它是匹配的,因此可能不必担心ViewHolder 's type does not match the data[position]' s型 . 有谁知道如何拾取onBindViewHolder()中的ViewHolder?
Edit: 看起来循环
ViewHolder
是按类型挑选的,所以那里没有战士 .编辑:http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/回答这个问题 .
它得到了回收
ViewHolder
像:如果没有找到正确类型的回收
ViewHolder
,则创建一个新的 .实际上,我想改进Anton's answer .
由于
getItemViewType(int position)
返回一个整数值,因此您可以返回布局资源ID,以便在onCreateViewHolder(ViewGroup parent, int viewType)
方法中保存一些逻辑 .此外,我不建议在
getItemCount()
中进行密集计算,因为在渲染列表时,以及在将每个项目渲染到可见项目之外时,该特定函数至少被调用5次 . 遗憾的是,因为notifyDatasetChanged()
方法是最终的,你不能真正覆盖它,但你可以从适配器中的另一个函数调用它 .它非常简单直接 .
只需覆盖适配器中的getItemViewType()方法 . 在数据的基础上返回不同的itemViewType值 . 例如,考虑具有成员isMale的Person类型的对象,如果isMale为true,则返回1并且isMale为false,在getItemViewType()方法中返回2 .
现在来到createViewHolder (ViewGroup parent, int viewType),在不同的viewType的基础上,yon可以膨胀不同的布局文件 . 如下
在onBindViewHolder (VH holder,int position)中检查持有者是
AdapterFemaleViewHolder
的实例或instanceof
的AdapterMaleViewHolder
的实例,并相应地分配值 .ViewHolder可能是这样的
对的,这是可能的 . 在您的适配器getItemViewType布局像这样....
供参考链接:https://www.journaldev.com/12372/android-recyclerview-example
我有一个更好的解决方案,允许以声明和类型安全的方式创建多个视图类型 . 它是用Kotlin写的,顺便说一句,这真的很棒 .
所有必需视图类型的简单视图持有者
有一个适配器数据项的抽象 . 请注意,视图类型由特定视图持有者类的hashCode表示(Kotlin中的KClass)
只有
bindViewHolder
需要在具体的适配器项类中重写(类型安全方式)此类
AdapterItemMedium
对象的列表是适配器的数据源,它实际上接受List<AdapterItem>
,见下文 .此解决方案的重要部分是视图持有者工厂,它将提供特定ViewHolder的新实例
简单的适配器类看起来像这样
创建新视图类型只需3个步骤:
创建一个视图持有者类
创建一个适配器项类(从AdapterItemBase扩展)
ViewHolderProvider
注册视图持有者类以下是此概念的一个示例:android-drawer-template它更进一步 - 视图类型充当微调器组件,可选适配器项 .
如果视图类型的布局只有少数,绑定逻辑很简单,请遵循Anton的解决方案 .
但是,如果您需要管理复杂的布局和绑定逻辑,代码将会很混乱 .
我相信以下解决方案对于需要处理复杂视图类型的人非常有用 .
Base DataBinder class
在创建单一视图类型时,此类中定义的函数与适配器类几乎完全相同 .
对于每种视图类型,通过扩展此DataBinder来创建类 .
Sample DataBinder class
要管理DataBinder类,请创建适配器类 .
Base DataBindAdapter class
创建class通过扩展此基类,然后实例化DataBinder类并覆盖抽象方法
getItemCount
返回DataBinders的总项数
getItemViewType
定义适配器位置和视图类型之间的映射逻辑 .
getDataBinder
根据视图类型返回DataBinder实例
getPosition
从指定DataBinder中的位置将转换逻辑定义到适配器位置
getBinderPosition
从适配器位置将转换逻辑定义到DataBinder中的位置
希望这个解决方案会有所帮助 .
我在GitHub中留下了更多细节解决方案和样本,如果需要,请参考以下链接 .
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter
您可以使用该库:https://github.com/vivchar/RendererRecyclerViewAdapter
`
对于每个项目,您应该实现ViewRenderer,ViewHolder,SomeModel:
ViewHolder - 它是回收者视图的简单视图持有者 .
SomeModel - 它是带有
ItemModel
接口的模型有关详细信息,您可以查看文档 .
为不同的布局创建不同的ViewHolder
RecyclerView可以拥有您想要的任意数量的视图,但为了更好的可读性,我们可以看看如何使用两个ViewHolders创建一个 .
覆盖
public int getItemViewType(int position)
根据
onCreateViewHolder()
方法中的ViewType返回不同的ViewHolders基于
onBindViewHolder()
方法中的itemViewType填充视图这是一个小代码片段
getItemViewType(int position)是关键
在我看来,创建这种recyclerView的起点是这种方法的知识 . 由于此方法是可选的覆盖,因此默认情况下它在RecylerView类中不可见,这反过来又使许多开发人员(包括我)想知道从哪里开始 . 一旦你知道这个方法存在,创建这样的RecyclerView将是一个很小的步骤 .
对的,这是可能的 .
写一个通用视图持有者:
然后创建视图持有者并使它们扩展GenericViewHolder . 例如,这一个:
那么RecyclerView.Adapter类将如下所示:
是的,这是可能的 . 只需实现getItemViewType(),并处理
onCreateViewHolder()
中的viewType
参数 .所以你做的事情如下: