消息应用程序的ListView在滚动后显示错误的listItem布局

时间:2013-12-09 17:34:01

标签: java android listview android-listview

我知道在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);

            }
        }

5 个答案:

答案 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)将解决问题。 无论如何,你将不得不重新膨胀视图。