我需要RecyclerView
内的两个垂直ScrollView
。我需要为RecyclerView
中的每个列表添加加载更多页脚。如何在Android中实现这一目标?
答案 0 :(得分:2)
我认为这就是你要找的东西。 Showing multiple lists in a single RecyclerView
。我将wiki中的描述用来描述如何轻松实现这一目标。
这是一个简单的模型,可以清楚地说明我们想要实现的目标。
列表标题(第一个列表)
列表标题(第二个列表)
页脚视图
我们来看两个名为firstList
和secondList
的列表。两者都是一些对象的列表。
您需要在全局范围内声明它们并在全局范围内初始化它们。这样您就不必将任何特定列表传递给Adapter
。
定义您的观点
因此,在初始化Adapter
之前,您需要声明一些常量,以便区分您将在列表中填充的不同类型的视图。例如,在我的情况下,我有五个不同的视图,我为每个项目分配了一个唯一值,以便我可以明确告诉在getItemViewType
上调用Adapter
时显示哪个视图
private static final int FOOTER_VIEW = 1;
private static final int FIRST_LIST_ITEM_VIEW = 2;
private static final int FIRST_LIST_HEADER_VIEW = 3;
private static final int SECOND_LIST_ITEM_VIEW = 4;
private static final int SECOND_LIST_HEADER_VIEW = 5;
定义ViewHolder
课程并正确绑定每个项目
现在让我们自定义您的ViewHolder
。我们将在这里列出每个列表项中显示的项目实例。我们在这里维护两个不同的列表,让我们假设每个列表都有一个标题和一个描述作为列表项。
因此我们需要获取这些实例并将它们与适当的值绑定。我在我的代码中添加了一个示例,您将在此处看到两个不同的函数bindViewFirstList()
和bindViewSecondList
,以便将UI字段与适当的值绑定。还有另一个函数bindViewFooter()
来自定义第二个列表的页脚视图。您可以声明其他一些功能,例如bindViewHeaderFirstList()
和bindViewHeaderSecondList
,以便从此处自定义和设置标头的值。这是ViewHolder
的代码示例。
public class ViewHolder extends RecyclerView.ViewHolder {
// List items of first list
private TextView mTextDescription1;
private TextView mListItemTitle1;
// List items of second list
private TextView mTextDescription2;
private TextView mListItemTitle2;
// Element of footer view
private TextView footerTextView;
public ViewHolder(final View itemView) {
super(itemView);
// Get the view of the elements of first list
mTextDescription1 = (TextView) itemView.findViewById(R.id.description1);
mListItemTitle1 = (TextView) itemView.findViewById(R.id.title1);
// Get the view of the elements of second list
mTextDescription2 = (TextView) itemView.findViewById(R.id.description2);
mListItemTitle2 = (TextView) itemView.findViewById(R.id.title2);
// Get the view of the footer elements
footerTextView = (TextView) itemView.findViewById(R.id.footer);
}
public void bindViewSecondList(int pos) {
// Have a close look here. We're calculating the appropriate position of the item in the secondList
// Second list will be populated after the firstList
// So if the firstList doesn't have any item the secondList will have a header and its items.
if (firstList == null) pos = pos - 1;
else {
// If the firstList is not empty, it'll have its header and its items. See the else part.
if (firstList.size() == 0) pos = pos - 1;
else pos = pos - firstList.size() - 2;
}
final String description = secondList.get(pos).getDescription();
final String title = secondList.get(pos).getTitle();
mTextDescription2.setText(description);
mListItemTitle2.setText(title);
}
public void bindViewFirstList(int pos) {
// Have a close look here. We're calculating the appropriate position of the item in the firstList
// Decrease pos by 1 as there is a header view now.
pos = pos - 1;
final String description = firstList.get(pos).getDescription();
final String title = firstList.get(pos).getTitle();
mTextDescription1.setText(description);
mListItemTitle1.setText(title);
}
public void bindViewFooter(int pos) {
footerTextView.setText("This is footer");
}
}
为每种类型的视图获取自定义ViewHolder
现在为每个元素声明自定义ViewHolder
,以便在onBindViewHolder
上调用Adapter
时区分它们。
public class FooterViewHolder extends ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
}
}
private class FirstListHeaderViewHolder extends ViewHolder {
public FirstListHeaderViewHolder(View itemView) {
super(itemView);
}
}
private class FirstListItemViewHolder extends ViewHolder {
public FirstListItemViewHolder(View itemView) {
super(itemView);
}
}
private class SecondListHeaderViewHolder extends ViewHolder {
public SecondListHeaderViewHolder(View itemView) {
super(itemView);
}
}
private class SecondListItemViewHolder extends ViewHolder {
public SecondListItemViewHolder(View itemView) {
super(itemView);
}
}
为每种类型的列表项获取正确的布局文件
在onCreateViewHolder
中,您需要return
与特定列表项关联的布局。这是我的。
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
if (viewType == FOOTER_VIEW) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_footer, parent, false);
FooterViewHolder vh = new FooterViewHolder(v);
return vh;
} else if (viewType == FIRST_LIST_ITEM_VIEW) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_first_list, parent, false);
FirstListItemViewHolder vh = new FirstListItemViewHolder(v);
return vh;
} else if (viewType == FIRST_LIST_HEADER_VIEW) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_first_list_header, parent, false);
FirstListHeaderViewHolder vh = new FirstListHeaderViewHolder(v);
return vh;
} else if (viewType == SECOND_LIST_HEADER_VIEW) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_second_list_header, parent, false);
SecondListHeaderViewHolder vh = new SecondListHeaderViewHolder(v);
return vh;
} else {
// SECOND_LIST_ITEM_VIEW
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_second_list, parent, false);
SecondListItemViewHolder vh = new SecondListItemViewHolder(v);
return vh;
}
}
使用onBindViewHolder
检查传递给ViewHolder
的{{1}}是否是您要在特定 onBindViewHolder
中显示的项目的实例。
position
获取@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
try {
if (holder instanceof SecondListItemViewHolder) {
SecondListItemViewHolder vh = (SecondListItemViewHolder) holder;
vh.bindViewSecondList(position);
} else if (holder instanceof FirstListHeaderViewHolder) {
FirstListHeaderViewHolder vh = (FirstListHeaderViewHolder) holder;
} else if (holder instanceof FirstListItemViewHolder) {
FirstListItemViewHolder vh = (FirstListItemViewHolder) holder;
vh.bindViewFirstList(position);
} else if (holder instanceof SecondListHeaderViewHolder) {
SecondListHeaderViewHolder vh = (SecondListHeaderViewHolder) holder;
} else if (holder instanceof FooterViewHolder) {
FooterViewHolder vh = (FooterViewHolder) holder;
vh.bindViewFooter(position);
}
} catch (Exception e) {
e.printStackTrace();
}
}
这是RecyclerView
的一个棘手的部分。你可能有三个案例。您的第一个列表可以是空的,也可以是第二个列表。第三种情况是,两个列表都填充了一些数据。
因此,我们需要在这里考虑这三种情况。在我的例子中,我的第一个列表中有一个标题。如果是我的第二个列表,我想显示一个标题和一个页脚。所以我的Adapter
看起来像这样。
getItemCount
从@Override
public int getItemCount() {
int firstListSize = 0;
int secondListSize = 0;
if (secondList == null && firstList == null) return 0;
// Get the sizes of the lists
if (secondList != null)
secondListSize = secondList.size();
if (firstList != null)
firstListSize = firstList.size();
// Case 1: When both lists have data
if (secondListSize > 0 && firstListSize > 0)
return 1 + firstListSize + 1 + secondListSize + 1; // first list header, first list size, second list header , second list size, footer
// Case 2: When only the second list have data
else if (secondListSize > 0 && firstListSize == 0)
return 1 + secondListSize + 1; // second list header, second list size, footer
// Case 3: When only the first list have data
else if (secondListSize == 0 && firstListSize > 0)
return 1 + firstListSize; // first list header , first list size
else return 0;
}
我猜这是getItemViewType
中最棘手的部分。您需要计算在给出列表中特定Adapter
项目时要返回的项目视图。
完成这项工作的最简单方法是编写首先返回页眉和页脚视图的逻辑。当您完成编写定义页眉和页脚position
的逻辑时,很容易为其他人编写。
这就是我管理我的方式。看,我首先定义了页眉和页脚的位置,这些位置为我简化了其他方程式。
position
当需要在单个@Override
public int getItemViewType(int position) {
int firstListSize = 0;
int secondListSize = 0;
if (secondList == null && firstList == null)
return super.getItemViewType(position);
if (secondList != null)
secondListSize = secondList.size();
if (firstList != null)
firstListSize = firstList.size();
if (secondListSize > 0 && firstListSize > 0) {
if (position == 0) return FIRST_LIST_HEADER_VIEW;
else if (position == firstListSize + 1)
return SECOND_LIST_HEADER_VIEW;
else if (position == secondListSize + 1 + firstListSize + 1)
return FOOTER_VIEW;
else if (position > firstListSize + 1)
return SECOND_LIST_ITEM_VIEW;
else return FIRST_LIST_ITEM_VIEW;
} else if (secondListSize > 0 && firstListSize == 0) {
if (position == 0) return SECOND_LIST_HEADER_VIEW;
else if (position == secondListSize + 1) return FOOTER_VIEW;
else return SECOND_LIST_ITEM_VIEW;
} else if (secondListSize == 0 && firstListSize > 0) {
if (position == 0) return FIRST_LIST_HEADER_VIEW;
else return FIRST_LIST_ITEM_VIEW;
}
return super.getItemViewType(position);
}
中显示多个列表时,您已完成自定义Adapter
的实施。我在code部分添加了一个演示项目。您可以构建和运行项目。
干杯!
答案 1 :(得分:0)