ListView项目未正确构建

时间:2014-07-23 13:54:31

标签: android listview android-arrayadapter

我的自定义ArrayAdapter存在一些问题。我正在尝试基于某些属性构建视图,但是一旦我开始滚动(有时甚至在此之前),视图就不能正确构建并且显示不正确。我知道这与ListView重用项目这一事实有关,但我无法弄清楚如何解决它。从理论上讲,这段代码应该有效。至少这就是我的想法。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    if (rowView == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        rowView = inflater.inflate(R.layout.message_view_row, null);
        image = (ImageView) rowView.findViewById(R.id.message_row_image);
        messageText = (TextView) rowView
                .findViewById(R.id.message_row_message);
        senderName = (TextView) rowView
                .findViewById(R.id.message_row_senderName);
        dateText = (TextView) rowView.findViewById(R.id.message_row_date);
        mainLayout = (LinearLayout) rowView
                .findViewById(R.id.messaging_view_mainLayout);
        messageLayout = (LinearLayout) rowView
                .findViewById(R.id.message_row_messageLayout);
    } else {
        image = (ImageView) rowView.findViewById(R.id.message_row_image);
        messageText = (TextView) rowView
                .findViewById(R.id.message_row_message);
        senderName = (TextView) rowView
                .findViewById(R.id.message_row_senderName);
        dateText = (TextView) rowView.findViewById(R.id.message_row_date);
        mainLayout = (LinearLayout) rowView
                .findViewById(R.id.messaging_view_mainLayout);
        messageLayout = (LinearLayout) rowView
                .findViewById(R.id.message_row_messageLayout);
    }

    Message msg = messages.get(position);
    View imageFromMain = mainLayout.getChildAt(0);
    View messageLayoutFromMain = mainLayout.getChildAt(1);
    mainLayout.removeAllViews();
    // handle the view stance
    if (!msg.isOwnMessage()) {
        // switch the views
        mainLayout.addView(messageLayoutFromMain);
        mainLayout.addView(imageFromMain);
        // set the color for the message box
        messageLayout.setBackgroundColor(context.getResources().getColor(
                R.color.friend_message_color));
    } else {
        // switch the views
        mainLayout.addView(imageFromMain);
        mainLayout.addView(messageLayoutFromMain);
        messageLayout.setBackgroundColor(context.getResources().getColor(
                R.color.clanster_color));
    }

    messageText.setText(msg.getMessage());
    senderName.setText(msg.getSenderName());
    Date date = msg.getCreatedAt();
    dateText.setText(dateFormat.format(msg.getCreatedAt()));

    if (msg.getSenderImageUrl() != null
            && !msg.getSenderImageUrl().isEmpty()) {
        Picasso.with(context).load(msg.getSenderImageUrl())
                .transform(new RoundedTransformation()).into(image);
    } else {
        Picasso.with(context).load(R.drawable.defaultimage)
                .transform(new RoundedTransformation()).into(image);
    }

    return rowView;
}

这部分不起作用的部分是我从布局中删除所有视图并根据某个属性以特定顺序重新添加它们的部分。

3 个答案:

答案 0 :(得分:1)

这是处理问题的更好方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    LayoutInflater inflater = ((Activity) context).getLayoutInflater();

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.message_view_row, null);
    }

    image = (ImageView) convertView.findViewById(R.id.message_row_image);
    messageText = (TextView) convertView.findViewById(R.id.message_row_message);
    senderName = (TextView) convertView.findViewById(R.id.message_row_senderName);
    dateText = (TextView) convertView.findViewById(R.id.message_row_date);
    mainLayout = (LinearLayout) convertView.findViewById(R.id.messaging_view_mainLayout);
    messageLayout = (LinearLayout) convertView.findViewById(R.id.message_row_messageLayout);

    Message msg = messages.get(position);

    //your problem area is here: 
    //**View imageFromMain = mainLayout.getChildAt(0);**
    //**View messageLayoutFromMain = mainLayout.getChildAt(1);**
    //when the view is recycled, you cannot assume 
    //that the views will be at the needed positions. instead, you should refactor
    //your code to make them separate views, and inflate them like this
    View imageFormMain = inflater.inflate(<your_refactored_view_name1>);
    View messageLayoutFromMain = inflater.inflate(<your_refactored_view_name2>);

    mainLayout.removeAllViews();
    // handle the view stance
    if (!msg.isOwnMessage()) {
        // switch the views
        mainLayout.addView(messageLayoutFromMain);
        mainLayout.addView(imageFromMain);
        // set the color for the message box
        messageLayout.setBackgroundColor(context.getResources().getColor(
                R.color.friend_message_color));
    } else {
        // switch the views
        mainLayout.addView(imageFromMain);
        mainLayout.addView(messageLayoutFromMain);
        messageLayout.setBackgroundColor(context.getResources().getColor(
                R.color.clanster_color));
    }

    messageText.setText(msg.getMessage());
    senderName.setText(msg.getSenderName());
    Date date = msg.getCreatedAt();
    dateText.setText(dateFormat.format(msg.getCreatedAt()));

    if (msg.getSenderImageUrl() != null && !msg.getSenderImageUrl().isEmpty()) {
        Picasso.with(context).load(msg.getSenderImageUrl())
                .transform(new RoundedTransformation()).into(image);
    } else {
        Picasso.with(context).load(R.drawable.defaultimage)
                .transform(new RoundedTransformation()).into(image);
    }

    return convertView;
}

答案 1 :(得分:0)

试试这个:

LayoutInflater inflater = (LayoutInflater) activity
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(layout, parent, false);

而不是:

View rowView = convertView;

希望这有帮助。

答案 2 :(得分:0)

getView()的第一部分更改为此。你正在重写代码两次,没有必要,它看起来很乱。

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        LayoutInflater mInflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = mInflator.inflate(R.layout.message_view_row, parent, null);
    }

    image = (ImageView) convertView.findViewById(R.id.message_row_image);
    messageText = (TextView) convertView
            .findViewById(R.id.message_row_message);
    senderName = (TextView) convertView
            .findViewById(R.id.message_row_senderName);
    dateText = (TextView) convertView.findViewById(R.id.message_row_date);
    mainLayout = (LinearLayout) rowView
            .findViewById(R.id.messaging_view_mainLayout);
    messageLayout = (LinearLayout) convertView
            .findViewById(R.id.message_row_messageLayout);

...

return convertView;

注意当您为convertView充气以将作为参数传递