我知道在stackoverflow上发布了许多类似的问题,所以请不要认为我没有搜索到高低。我认为我的问题只是从现在完全理解listViews和列表项的生命周期。我有一个列表视图,可以包含两种类型的消息,出站或入站。最初,我的listView将使用不同的背景颜色,具体取决于消息的类型(出站与入站),并且它可以完美地工作。现在我的应用程序不需要列表项的不同背景,但它实际上需要不同的列表项的不同布局。
这是我的适配器的剪辑。
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
SoapBoxMessage thisMessage = messages.get(position);
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (thisMessage.isOutbound()) {
v = inflater.inflate(R.layout.outbound_row, null);
} else {
v = inflater.inflate(R.layout.inbound_row, null);
}
}
答案 0 :(得分:4)
适配器可以支持不同的ViewItemTypes,以解决您的回收问题。
static public enum LAYOUT_TYPE {
INBOUND,
OUTBOUND
}
@Override
public int getViewTypeCount () {
return LAYOUT_TYPE.values().length;
}
@Override
public int getItemViewType (int position) {
if ( messages.get(position).isOutbound())
return LAYOUT_TYPE.OUTBOUND.ordinal();
else
return LAYOUT_TYPE.INBOUND.ordinal();
}
@Override
public View getView (int position, View convertView, ViewGroup parent) {
LAYOUT_TYPE itemType = LAYOUT_TYPE.values()[getItemViewType(position)];
... (code until inflater )
switch (itemType){
case INBOUND:
convertview = /inflate & configure inbound layout
break;
case OUTBOUND:
convertview = /inflate & configure outbound layout
break;
}
您不需要担心回收视图,因为listview将尊重每个位置的ViewItemTypes,并且它只会提供该位置的正确viewtype的转换视图
答案 1 :(得分:2)
问题是listview正在回收视图,所以当你检查视图是否为null时它不会传递,因为视图在被回收时不为null
每次调用getView时都需要对视图进行膨胀,基本上删除了if(v == null)
答案 2 :(得分:2)
尝试使用像这样的ViewHolder:
ViewHolder holder;
public View getView(int position, View convertView, ViewGroup parent) {
convertView = null;
SoapBoxMessage thisMessage = messages.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (thisMessage.isOutbound()) {
convertView = inflater.inflate(R.layout.outbound, null, false);
//specific to your outbound layout
holder = new ViewHolder();
holder.text= (TextView)convertView.findViewById(R.id.textview);
holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup);
holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton);
} else {
convertView = inflater.inflate(R.layout.inbound, null, false);
//specific to your inbound layout
holder = new ViewHolder();
holder.text= (TextView)convertView.findViewById(R.id.textview);
holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup);
holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton);
}
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
//Here you can set the text or other code you want to implement
holder.text.setText("Whatever!");
return convertView;
}
static class ViewHolder {
//TODO put components you use like:
TextView text;
RadioGroup group;
ToggleButton toggle;
}
答案 3 :(得分:1)
这是因为正在发生的回收。你需要这些东西:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
SoapBoxMessage thisMessage = messages.get(position);
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.listview_feedlog_item, null);
holder = new ViewHolder();
holder.txtTime = (TextView) convertView.findViewById(R.id.textTime);
holder.txtDate = (TextView) convertView.findViewById(R.id.textDate);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// I don't know how your SoapBoxMessage is made up so here are two sample methods
holder.txtTime.setText(thisMessage.getTime());
holder.txtDate.setText(thisMessage.getDate());
return convertView;
}
/* private view holder class */
private class ViewHolder {
TextView txtTime;
TextView txtDate;
}
另外,请记住始终在getView
方法中重置或启动值。由于View
可以回收利用,因此它可能具有以前的生命属性。
答案 4 :(得分:0)
这是否是一种好习惯,删除if (v == null)
将解决问题。
无论如何,你将不得不重新膨胀视图。