使用 2 种不同的列表项时,Listview 的 getView() 无法正常工作
Listview's getView() isn't working properly when using 2 different kinds of listitem
我有一个用于列表视图的自定义数组适配器,我将它用于联系人,因为我希望列表视图更有条理我想为联系人姓名的第一个字母添加 header
这是我目前的进度:
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View listItem = convertView;
LinearLayout header = null;
String preLabel = " ";
char firstChar = ' ';
final Contact c = Contacts.get(position);
String label = c.name;
if(position != 0) {//OOb prevention
preLabel = Contacts.get(position - 1).name;
firstChar = label.toUpperCase().charAt(0);
}
char preFirstChar = preLabel.toUpperCase().charAt(0);
if (listItem == null) {
//If its the 1st position or the 1st character of the name is different inflate the layout with a header, else inflate the other layout.
if(position==0 || firstChar != preFirstChar) {
listItem = LayoutInflater.from(mContext).inflate(R.layout.contacts_list_item, parent, false);
header = (LinearLayout) listItem.findViewById(R.id.section);
setSection(header, label);
}else{
listItem = LayoutInflater.from(mContext).inflate(R.layout.contacts_list2, parent, false);
}
}//Etc etc
我认为添加任何代码都没有关系向下滚动到当我向上滚动时视图不可见或被破坏的位置 0 没有 header.
如果我继续做同样的事情,它突然会自行修复,现在第 1 个位置再次出现 header,再次滚动,但现在不会了,为什么会这样?
适配器是否使用另一种方法来创建视图?
它是否尝试预测它将使用哪种布局以使其更快?
错误的视觉参考:
如您所见,位置 0(为简单起见,我将位置编号而不是联系人姓名放在文本视图中)在开始处有一个 header,滚动了一下后,消失,然后又出现。
当您滚动并且视图超出可见区域时,ListView 将 re-use 列表中其他位置的相同膨胀视图。
因此,如果您的 getView
方法中的逻辑有时会膨胀 R.layout.a
,有时会膨胀 R.layout.b
,这可能会导致麻烦,因为那样您可能会得到 convertView
你需要 re-use 类型 a
但你需要一个 b
类型的视图用于列表中的这个特定位置。
解决方案是使用ViewType
s,这就是你告诉ListView你有两种不同类型的布局,然后它知道什么时候可以回收某种类型以及使用哪种View
.
基本上你应该return覆盖getViewTypeCount()
和return 2(你有两种类型的布局),并移动检查我们是否需要header的逻辑或者不 getItemViewType(int position)
.
我有一个用于列表视图的自定义数组适配器,我将它用于联系人,因为我希望列表视图更有条理我想为联系人姓名的第一个字母添加 header 这是我目前的进度:
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View listItem = convertView;
LinearLayout header = null;
String preLabel = " ";
char firstChar = ' ';
final Contact c = Contacts.get(position);
String label = c.name;
if(position != 0) {//OOb prevention
preLabel = Contacts.get(position - 1).name;
firstChar = label.toUpperCase().charAt(0);
}
char preFirstChar = preLabel.toUpperCase().charAt(0);
if (listItem == null) {
//If its the 1st position or the 1st character of the name is different inflate the layout with a header, else inflate the other layout.
if(position==0 || firstChar != preFirstChar) {
listItem = LayoutInflater.from(mContext).inflate(R.layout.contacts_list_item, parent, false);
header = (LinearLayout) listItem.findViewById(R.id.section);
setSection(header, label);
}else{
listItem = LayoutInflater.from(mContext).inflate(R.layout.contacts_list2, parent, false);
}
}//Etc etc
我认为添加任何代码都没有关系向下滚动到当我向上滚动时视图不可见或被破坏的位置 0 没有 header.
如果我继续做同样的事情,它突然会自行修复,现在第 1 个位置再次出现 header,再次滚动,但现在不会了,为什么会这样? 适配器是否使用另一种方法来创建视图? 它是否尝试预测它将使用哪种布局以使其更快?
错误的视觉参考:
如您所见,位置 0(为简单起见,我将位置编号而不是联系人姓名放在文本视图中)在开始处有一个 header,滚动了一下后,消失,然后又出现。
当您滚动并且视图超出可见区域时,ListView 将 re-use 列表中其他位置的相同膨胀视图。
因此,如果您的 getView
方法中的逻辑有时会膨胀 R.layout.a
,有时会膨胀 R.layout.b
,这可能会导致麻烦,因为那样您可能会得到 convertView
你需要 re-use 类型 a
但你需要一个 b
类型的视图用于列表中的这个特定位置。
解决方案是使用ViewType
s,这就是你告诉ListView你有两种不同类型的布局,然后它知道什么时候可以回收某种类型以及使用哪种View
.
基本上你应该return覆盖getViewTypeCount()
和return 2(你有两种类型的布局),并移动检查我们是否需要header的逻辑或者不 getItemViewType(int position)
.