我使用适配器创建了ListView
但唯一的问题是我们使用不同的布局,因为它是一个消息传递应用程序。我想通过使用视图回收来提高性能,但无法弄清楚如何回收视图。
是否可以更改视图布局或是否可能:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MessageLog message = this.mData.get(position);
MessageRowViewHolder holder = new MessageRowViewHolder();
int type = getItemViewType(position);
switch (type) {
case TYPE_ITEM:
// Inflate the correct view depending on whether the message is a reply or
// own message.
if (message.isReply()) {
convertView = mInflater.inflate(R.layout.row_prisoners_voicemail_message, parent, false);
} else {
convertView = mInflater.inflate(R.layout.row_own_voicemail_message, parent, false);
}
// The holder simply holds views for convenient access.
// It is nothing more than a dumb container.
holder.type = type;
holder.position = position;
holder.messageBackground = (RelativeLayout) convertView.findViewById(R.id.voiceMessageRectangleBackground);
holder.commentView = (TextView) convertView.findViewById(R.id.voiceMessageCommentText);
holder.messageDurationView = (TextView) convertView.findViewById(R.id.voiceMessageDurationText);
holder.metaTextView = (TextView) convertView.findViewById(R.id.voiceMessageMetaText);
holder.timestampView = (TextView) convertView.findViewById(R.id.voiceMessageTimestampText);
holder.editButtonView = (ImageView) convertView.findViewById(R.id.voiceMessageEditButtonImage);
holder.favouritedImageView = (ImageView) convertView.findViewById(R.id.voiceMessageFavouritedImage);
holder.playPauseImageView = (ImageView) convertView.findViewById(R.id.voiceMessagePlayPauseImage);
// Numeric tags to detect which view has been clicked.
holder.editButtonView.setTag(position+"");
holder.metaTextView.setTag(position+"");
holder.editButtonView.setOnClickListener(this);
holder.metaTextView.setOnClickListener(this);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.grid_date_row, parent, false);
holder.type = type;
holder.dateView = (TextView) convertView.findViewById(R.id.date);
break;
case TYPE_FILLER:
convertView = mInflater.inflate(R.layout.grid_filler_row, parent, false);
holder.type = type;
holder.dateView = (TextView) convertView.findViewById(R.id.refreshText);
break;
case TYPE_ITEM_UPLOAD:
convertView = mInflater.inflate(R.layout.row_upload_voicemail_message, parent, false);
holder.type = type;
holder.messageBackground = (RelativeLayout) convertView.findViewById(R.id.voiceMessageRectangleBackground);
break;
}
// Short-hand notations for the resources and the message date.
Resources r = context.getResources();
Date messageDate = message.getDate();
switch (holder.type) {
case TYPE_ITEM:
// Set the duration of the call and the timestamp.
holder.messageDurationView.setText(PvmUtils.formatMessageDuration(context, message.getDuration()));
holder.timestampView.setText(PvmUtils.formatMessageTimestamp(messageDate));
// Set the on click listener for editing.
// Show/hide the favourited view and comment.
if (message.isFavourited()) {
holder.favouritedImageView.setVisibility(View.VISIBLE);
String description = message.getDescription();
if (description != null) {
holder.commentView.setVisibility(View.VISIBLE);
holder.commentView.setText(description);
} else {
holder.commentView.setVisibility(View.GONE);
}
} else {
holder.favouritedImageView.setVisibility(View.INVISIBLE);
holder.commentView.setVisibility(View.GONE);
}
if (message.isReply()) {
// If it is a reply, set the 'NEW' label if it is a new message.
if (message.isRead()) {
holder.metaTextView.setText("");
} else {
holder.metaTextView.setText(r.getString(R.string.new_voice_message_label));
}
} else {
// If it is own message, set whether the message has been uploaded and
// listened to; and if so, when.
if (message.isRead()) {
String dateRead = "";
if (message.getReadAt() != null) {
dateRead = PvmUtils.formatMediumLongDate(message.getReadAt());
}
// E.g. ✓✓ 20 Oct 17 15:54
String textToSet = String.format("%s %s", r.getString(R.string.doubleTick), dateRead);
holder.metaTextView.setText(textToSet);
} else {
holder.metaTextView.setText(r.getString(R.string.tick));
}
}
break;
case TYPE_SEPARATOR:
// Just set the formatted date.
SimpleDateFormat formatDate = new SimpleDateFormat("dd MMM yy (EEE)", SharedResources.getLocale(context));
holder.dateView.setText(formatDate.format(messageDate));
break;
case TYPE_FILLER:
// Whatever this is...
int size = list.getHeight();
holder.dateView.setPadding(0, size/2, 0, size/2);
break;
case TYPE_ITEM_UPLOAD:
// Set the background colour when uploading an item to yellow.
int colour;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
colour = r.getColor(R.color.yellow_message, null);
} else {
colour = r.getColor(R.color.yellow_message);
}
holder.messageBackground.setBackgroundColor(colour);
break;
}
return convertView;
}
答案 0 :(得分:1)
您可以对ListView
使用多个布局,因此无需立即迁移到RecyclerView
;-)
如果您正在使用从BaseAdapter
以某种方式扩展的适配器,则必须覆盖两种方法:
getViewTypeCount()
返回将由getView(int,View,ViewGroup)创建的视图类型数。
getItemViewType(int position)
获取将由getView(int,View,ViewGroup)为指定项创建的View类型。
您只需根据需要定义多种不同的视图类型:
private static int VIEW_TYPE_REPLY = 0;
private static int VIEW_TYPE_OTHER = 1;
然后getItemViewType()
的实现可能如下所示:
MessageLog message = this.mData.get(position);
if (message.isReply()) {
return VIEW_TYPE_REPLY;
} else {
return VIEW_TYPE_OTHER;
}
在getView()
中,可以写
int viewType = getItemViewType(position);
switch(viewType){
case VIEW_TYPE_REPLY:
convertView = mInflater.inflate(R.layout.row_prisoners_voicemail_message, parent, false);
break;
default:
convertView = mInflater.inflate(R.layout.row_own_voicemail_message, parent, false);
}
// ....
以后可能会使用不同的ViewHolder
,具体取决于View
类型的内容有多大差异。
通过覆盖这两种方法,您可以使框架在可能的情况下回收View
。因此,没有必要检查非null convertView 是否具有正确的布局。