我的自定义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;
}
这个部分不工作的地方是我从布局中删除所有视图并根据某个属性以特定顺序重新添加它们的部分。
这是一个更好的方法来处理你的问题:
@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;
}
试试这个:
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(layout, parent, false);
代替:
View rowView = convertView;
将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来传递父元素作为参数