我有一个ListView,它由我的自定义BaseAdapter填充,其中包含一些TextView和ImageButtons的视图。如果用户从其中一个列表项中选择PopupMenu中的项,则会更改该列表项上关联的TextView的文本。这对我的ListView中的所有项目都很有效,除了第一项。由于某种原因,第一项永远不会更新TextView。我怀疑它与我的convertView有关,因为该项没有被重置,但我不知道如何修复它。
这是我的设置。我有一个由自定义BaseAdapter填充的ListView。在我的BaseAdapter中,我有getView()
:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
IMOModGroup modGroup = modGroups.get(position);
convertView = modGroup.getConvertView(parent);
}
return convertView;
}
IMOModGroup是一种特殊的数据结构,它包含每个列表项的所有状态和数据。因此,当convertView为null时,BaseAdapter会从IMOModGroup为该位置请求一个新的convertView。这是创建新convertView的IMOModGroup方法:
public View getConvertView(ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.modifier_list_item, parent, false);
//...
TextView selectedModText = (TextView) convertView.findViewById(R.id.modName);
selectedModText.setText(R.string.no_modifier_selected);
selectedModText.setTextColor(context.getResources().getColor(R.color.grayed_out_text_color));
//...
return convertView;
}
用户可以在每个列表项上打开PopupMenu并进行选择。当他们这样做时,上面代码中的TextView被更改以反映新文本的选择。该代码如下所示:
public boolean onMenuItemClick(MenuItem item) {
String selectedMod = item.getTitle().toString();
TextView selectedModText = (TextView) convertView.findViewById(R.id.modName);
selectedModText.setText(selectedMod);
selectedModText.setTextColor(context.getResources().getColor(R.color.imo_blue_light));
//...
return false;
}
所有这些对ListView中的每个项目都有效,除了第一个项目,它永远不会更新以反映TextView更改。我已经过测试,以确保TextView文本实际上已被更改,并且可以在以后调用和查看,并且它已正确设置。所以看起来数据是正确的,但视图没有得到更新。
我很确定问题是我的convertView没有被重置,所以ListView只是继续使用旧文本的旧视图。我在设置文本后尝试在BaseAdapter上调用notifyDataSetChanged()
,但这并不起作用。
这个问题很有希望:First item in list view is not displaying correctly
但我不确定这是不是我的问题,而且我不确定如何将其应用到我的方案中。
有什么想法吗?我已经在SO和Google上阅读了一些类似的问题,但这些问题似乎与我的具体情况无关。我已经使用ListViews和Adapters很长一段时间了,这是我第一次见到这样的东西。谢谢你的帮助。
对评论作出反应的编辑
这是完整的BaseAdapter代码......
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.ArrayList;
public class IMOModListAdapter extends BaseAdapter {
private Context context;
private ArrayList<IMOModGroup> modGroups;
public IMOModListAdapter(Context context, ArrayList<IMOModGroup> modGroups) {
this.context = context;
this.modGroups = modGroups;
}
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
IMOModGroup modGroup = modGroups.get(position);
convertView = modGroup.getConvertView(parent);
}
return convertView;
}
public Object getItem(int position) {
return 0;
}
public long getItemId(int position) {
return 0;
}
public int getCount() {
return modGroups.size();
}
}
进一步测试
当我深入研究调试时,我意识到当列表中元素1的TextView发生更改时,甚至根本不会调用getView()
。但是当更改任何其他元素时,getView()
被称为正常。
作为一个完整性检查,我尝试从父项Activity本身更改外部第一个列表项的文本。如果我尝试更改第一个项目,它什么都不做,但如果我尝试更改任何其他列表项,它工作正常!这太奇怪了!这就是我试过的:
//Set the text of the first item. This does NOTHING and the TextView
//in the item remains unchanged
IMOModGroup modGroup = modGroups.get(0);
modGroup.setTestText("This is some test text");
modList.notifyDataSetChanged();
//Set the text of the second item. This works completely fine!!!!!
IMOModGroup modGroup = modGroups.get(1);
modGroup.setTestText("This is some test text");
modList.notifyDataSetChanged();
答案 0 :(得分:2)
我找到了解决这个问题的方法。只是研究关于BaseAdapter和getView()
的随机SO问题,我终于在this post之前遇到了Romain Guy,其中他声明你绝不应该wrap_content
使用layout_height
getView()
一个ListView,因为它导致ListView调用适配器的layout_height
吨次,只是为了创建用于测量内容高度的虚拟视图。事实证明这导致了我的问题,因此将我的match_parent
更改为match_parent
就可以了。
不幸的是,现在这会导致一个新问题,因为我无法使用wrap_content
,因为它会在我的父布局中隐藏其他视图。但至少第一个列表项目现在正确更新。
<强>更新强>
我学会了如何在填充适配器后手动和动态设置ListView的高度。我使用了下面的方法,希望这可以帮助某些人遇到类似的问题。这使得我不必使用ListView
,但我仍然可以将private void setModListHeight() {
int numberOfItems = modGroups.size(); //the ArrayList providing data for my ListView
int totalItemsHeight = 0;
for(int position = 0; position < numberOfItems; position++) {
View item = modListAdapter.getView(position, null, modList);
item.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
totalItemsHeight += item.getMeasuredHeight();
}
int totalDividersHeight = modList.getDividerHeight() * (numberOfItems - 1);
ViewGroup.LayoutParams params = modList.getLayoutParams();
params.height = totalItemsHeight + totalDividersHeight;
modList.setLayoutParams(params);
modList.requestLayout();
}
高度设置为仅与其内容一样大。
.sf-menu {
list-style: none;
margin: 0;
padding: 0;
}
.sf-menu li {
float: left;
}
.sf-menu li a {
border-right: 2px solid;
border-color : #fff #00a54f;
}
.sf-menu > li.sfHover > a,
.sf-menu > li > a:hover, .sf-menu > li.sfHoverForce > a {
border-color : #fff black;
color: #00a54f;
}