使用RecyclerView创建动态列表:
当我们创建一个RecyclerView时。适配器我们必须指定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吗?
首先,必须创建两个布局XML文件。之后,在recyclerview适配器中,TYPE_CALL和TYPE_EMAIL是两个静态值,分别为适配器类中的1和2。
现在在Recycler视图Adapter类级别定义两个静态值,例如:private static int TYPE_EMAIL = 2;
现在创建多个视图的视图持有者,如下所示:
class CallViewHolder extends RecyclerView.ViewHolder {
private TextView txtName;
private TextView txtAddress;
CallViewHolder(@NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtAddress = itemView.findViewById(R.id.txtAddress);
}
}
class EmailViewHolder extends RecyclerView.ViewHolder {
private TextView txtName;
private TextView txtAddress;
EmailViewHolder(@NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtAddress = itemView.findViewById(R.id.txtAddress);
}
}
现在在recyclerview适配器的onCreateViewHolder和onBindViewHolder方法中编写如下代码:
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View view;
if (viewType == TYPE_CALL) { // for call layout
view = LayoutInflater.from(context).inflate(R.layout.item_call, viewGroup, false);
return new CallViewHolder(view);
} else { // for email layout
view = LayoutInflater.from(context).inflate(R.layout.item_email, viewGroup, false);
return new EmailViewHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
if (getItemViewType(position) == TYPE_CALL) {
((CallViewHolder) viewHolder).setCallDetails(employees.get(position));
} else {
((EmailViewHolder) viewHolder).setEmailDetails(employees.get(position));
}
}
如果你想将它与Android数据绑定结合使用,请查看https://github.com/evant/binding-collection-adapter -它是迄今为止我所见过的多种视图类型RecyclerView的最佳解决方案。
你可以这样使用它
var items: AsyncDiffPagedObservableList<BaseListItem> =
AsyncDiffPagedObservableList(GenericDiff)
val onItemBind: OnItemBind<BaseListItem> =
OnItemBind { itemBinding, _, item -> itemBinding.set(BR.item, item.layoutRes) }
然后在列表所在的布局中
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:enableAnimations="@{false}"
app:scrollToPosition="@{viewModel.scrollPosition}"
app:itemBinding="@{viewModel.onItemBind}"
app:items="@{viewModel.items}"
app:reverseLayoutManager="@{true}"/>
你的列表项必须实现BaseListItem接口,它看起来像这样:
interface BaseListItem {
val layoutRes: Int
}
项目视图应该看起来像这样:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="...presentation.somescreen.list.YourListItem"/>
</data>
...
</layout>
YourListItem实现BaseListItem。
是的,这是可能的。只需实现getItemViewType(),并照顾onCreateViewHolder()中的viewType参数。
所以你可以这样做:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
class ViewHolder0 extends RecyclerView.ViewHolder {
...
public ViewHolder0(View itemView){
...
}
}
class ViewHolder2 extends RecyclerView.ViewHolder {
...
public ViewHolder2(View itemView){
...
}
@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;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0: return new ViewHolder0(...);
case 2: return new ViewHolder2(...);
...
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolder0 viewHolder0 = (ViewHolder0)holder;
...
break;
case 2:
ViewHolder2 viewHolder2 = (ViewHolder2)holder;
...
break;
}
}
}
这是非常简单直接的。
只需在适配器中重写getItemViewType()方法。根据数据返回不同的itemViewType值。例如,考虑一个Person类型的对象,其成员为male,如果isMale为真,则返回1,isMale为假,则在getItemViewType()方法中返回2。
现在来到createViewHolder (ViewGroup parent, int viewType),在不同的viewType的基础上,你可以膨胀不同的布局文件。像下面这样:
if (viewType == 1){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.male, parent, false);
return new AdapterMaleViewHolder(view);
}
else{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.female, parent, false);
return new AdapterFemaleViewHolder(view);
}
在onBindViewHolder (VH holder,int position)检查holder是AdapterFemaleViewHolder或AdapterMaleViewHolder的实例,并相应地分配值。
ViewHolder可能是这样的
class AdapterMaleViewHolder extends RecyclerView.ViewHolder {
...
public AdapterMaleViewHolder(View itemView){
...
}
}
class AdapterFemaleViewHolder extends RecyclerView.ViewHolder {
...
public AdapterFemaleViewHolder(View itemView){
...
}
}