我使用自定义ArrayAdapter来填充listview。
我使用Picasso加载图像,在加载图像之前我计算每个图像的高度和宽度。因此动态ImageView具有不同的高度和宽度。
当我向上滚动列表视图时,一切都很顺利。但是当我向下滚动列表视图时,列表开始跳转,当涉及带图像的行时
我认为,它是由listview元素循环引起的,它会忘记动态图像视图高度,并在再次重新计算图像视图时产生这种跳跃效果。我将我的动态imageview附加到Holder,但它没有帮助
我的适配器的一部分看起来像这样:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ChatMessageElement el = list.get(position);
ViewHolder holder = null;
NewMessagesLabelHolder labelHolder = null;
if (convertView == null) {
convertView = el.getView(inflater, parent);
if (el.isMessage()) {
holder = new ViewHolder();
holder.messageLayout = (RelativeLayout) convertView.findViewById(R.id.message_container);
holder.messageContent = (LinearLayout) convertView.findViewById(R.id.message_content);
holder.bottomIndicator = (LinearLayout) convertView.findViewById(R.id.bottom_indicators);
holder.dateTextView = (TextView) convertView.findViewById(R.id.message_date);
holder.timeAgo = (TextView) convertView.findViewById(R.id.time_ago);
holder.nameTextView = (TextView) convertView.findViewById(R.id.user_name);
convertView.setTag(holder);
}
} else {
if (el.isMessage()) {
holder = (ViewHolder) convertView.getTag();
}
}
if (el.isMessage()) {
Message currentMessage = (Message) el;
drawMessage(holder, currentMessage, position);
}
return convertView;
}
private void drawMessage(ViewHolder holder, Message message, int position) {
String date = message.getCreatedAt();
String formattedDate = Helper.getInstance().formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "HH:mm", date);
String userName = message.getUserName();
holder.likesLabelImageView.setVisibility(View.GONE);
holder.likesCountTextView.setVisibility(View.GONE);
holder.nameTextView.setText(userName);
holder.dateTextView.setText(formattedDate);
if (message.isLiked()) {
holder.likesCountTextView.setText(Integer.toString(message.getLikesCount()));
holder.likesCountTextView.setVisibility(View.VISIBLE);
holder.likesLabelImageView.setVisibility(View.VISIBLE);
}
List<MessageComponent> messageComponentList;
messageComponentList = message.getMessageComponents();
drawMessageContent(holder, messageComponentList, message);
holder.nameTextView.setTag(position);
holder.avatarImageView.setTag(position);
holder.nameTextView.setOnClickListener(userClickListener);
holder.avatarImageView.setOnClickListener(userClickListener);
// hang empty onLingClickListener to display context menu when
// long click on whole message
holder.nameTextView.setOnLongClickListener(longClickListener);
holder.avatarImageView.setOnLongClickListener(longClickListener);
}
private void drawMessageContent(ViewHolder holder, final List<MessageComponent> messageComponentList, final Message msg) {
holder.messageContent.removeAllViewsInLayout();
int messageComponentListSize = messageComponentList.size();
for (final MessageComponent messageComponent : messageComponentList) {
messageComponentListSize--;
if (messageComponentListSize == 0)
iAmLast = true;
final String type = messageComponent.getType();
if (type.equals(MessageComponent.MESSAGE_COMPONENT_TEXT_TYPE)) {
TextView textView = new TextView(context);
textView.setText(messageComponent.getText());
setViewBackground(textView, msg);
//reset margins for texts, caused by margin changes for images
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) holder.bottomIndicator.getLayoutParams();
params.setMargins(45, -82, 0, 0);
holder.bottomIndicator.setLayoutParams(params);
holder.messageContent.addView(textView);
}
if (type.equals(MessageComponent.MESSAGE_COMPONENT_IMAGE_TYPE)) {
ViewGroup.LayoutParams params = new ActionBar.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
thumbHeight
);
final RoundedImageView imageView = new RoundedImageView(context);
imageView.setPadding(20, 0, 20, 20);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setCornerRadius(15.0f);
mHandler.post(new Runnable() {
@Override
public void run() {
drawPreview(messageComponent, imageView);
}
});
imageView.setLayoutParams(params);
// hang empty onLingClickListener to display context menu when
// long click on whole message
imageView.setOnLongClickListener(longClickListener);
final RelativeLayout mediaContainer = new RelativeLayout(context);
mediaContainer.addView(imageView);
}
}
}
// Calculates restricted dimensions with a maximum of $goal_width by $goal_height
private ImageSize resize_dimensions(float goal_width, float goal_height, float width, float height) {
float ratio = Math.min(goal_width/width, goal_height/height);
int nwidth = Math.round(width*ratio);
int nheight = Math.round(height*ratio);
if(nwidth>nheight*2)
nheight = 400;
if(nheight>nwidth*2)
nwidth = 600;
ImageSize imageSize = new ImageSize(nwidth, nheight);
return imageSize;
}
private void drawPreview(MessageComponent messageComponent, final ImageView imageView) {
String type = messageComponent.getType();
String mediaPath = messageComponent.getMediaPath();
String thumbPath = messageComponent.getThumbPath();
String thumbUrl = messageComponent.getThumbUrl();
String videoThumbPath = messageComponent.getVideoThumbPath();
Uri uri = null;
if (type.equals(MessageComponent.MESSAGE_COMPONENT_IMAGE_TYPE)) {
if (!TextUtils.isEmpty(mediaPath)) {
uri = Uri.parse("file://" + mediaPath);
File file = new File(uri.getPath());
if (file.exists()) {
resizeAndLoadThumbnail(uri, imageView);
return;
}
}
if (!TextUtils.isEmpty(thumbPath)) {
uri = Uri.parse("file://" + mediaPath);
File file = new File(uri.getPath());
if (file.exists()) {
resizeAndLoadThumbnail(uri, imageView);
return;
}
}
if (thumbUrl != null) {
uri = Uri.parse(thumbUrl);
}
if (uri != null) {
resizeAndLoadThumbnail(uri, imageView);
return;
}
}
}
private void resizeAndLoadThumbnail(Uri uri, final ImageView imageView) {
Picasso.with(context).load(uri).into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
ImageSize imgSize = resize_dimensions(900, 900, width, height);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
imgSize.width,
imgSize.height
);
imageView.setLayoutParams(params);
imageView.setImageBitmap(bitmap);
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
}