Fix flickering avatar.

This commit is contained in:
Alan Evans 2019-06-19 11:57:07 -04:00
parent e603162ee7
commit 1a32bc8232
3 changed files with 74 additions and 26 deletions

View File

@ -22,14 +22,15 @@ import android.graphics.Typeface;
import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.RippleDrawable;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.components.AlertView; import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AvatarImageView; import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView; import org.thoughtcrime.securesms.components.DeliveryStatusView;
@ -240,7 +241,11 @@ public class ConversationListItem extends RelativeLayout
@Override @Override
public void unbind() { public void unbind() {
if (this.recipient != null) this.recipient.removeListener(this); if (this.recipient != null) {
this.recipient.removeListener(this);
this.recipient = null;
contactPhotoImage.setAvatar(glideRequests, null, true);
}
} }
private void setBatchState(boolean batch) { private void setBatchState(boolean batch) {
@ -336,9 +341,11 @@ public class ConversationListItem extends RelativeLayout
@Override @Override
public void onModified(final Recipient recipient) { public void onModified(final Recipient recipient) {
Util.runOnMain(() -> { Util.runOnMain(() -> {
fromView.setText(recipient, unreadCount == 0); if (this.recipient == recipient) {
contactPhotoImage.setAvatar(glideRequests, recipient, true); fromView.setText(recipient, unreadCount == 0);
setRippleColor(recipient); contactPhotoImage.setAvatar(glideRequests, recipient, true);
setRippleColor(recipient);
}
}); });
} }

View File

@ -5,22 +5,29 @@ import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.util.AttributeSet;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatImageView;
import android.util.AttributeSet;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.avatars.ContactColors; import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientExporter; import org.thoughtcrime.securesms.recipients.RecipientExporter;
import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.ThemeUtil;
import java.util.Objects;
public class AvatarImageView extends AppCompatImageView { public class AvatarImageView extends AppCompatImageView {
private static final String TAG = AvatarImageView.class.getSimpleName(); private static final String TAG = AvatarImageView.class.getSimpleName();
@ -44,6 +51,9 @@ public class AvatarImageView extends AppCompatImageView {
private Paint outlinePaint; private Paint outlinePaint;
private OnClickListener listener; private OnClickListener listener;
private @Nullable RecipientContactPhoto recipientContactPhoto;
private @NonNull Drawable unknownRecipientDrawable;
public AvatarImageView(Context context) { public AvatarImageView(Context context) {
super(context); super(context);
initialize(context, null); initialize(context, null);
@ -64,16 +74,18 @@ public class AvatarImageView extends AppCompatImageView {
} }
outlinePaint = ThemeUtil.isDarkTheme(getContext()) ? DARK_THEME_OUTLINE_PAINT : LIGHT_THEME_OUTLINE_PAINT; outlinePaint = ThemeUtil.isDarkTheme(getContext()) ? DARK_THEME_OUTLINE_PAINT : LIGHT_THEME_OUTLINE_PAINT;
unknownRecipientDrawable = new ResourceContactPhoto(R.drawable.ic_profile_default).asDrawable(getContext(), ContactColors.UNKNOWN_COLOR.toConversationColor(getContext()), inverted);
} }
@Override @Override
protected void dispatchDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
super.dispatchDraw(canvas); super.onDraw(canvas);
float cx = getWidth() / 2f;
float cy = getHeight() / 2f;
float radius = cx - (outlinePaint.getStrokeWidth() / 2f);
float cx = canvas.getWidth() / 2;
float cy = canvas.getHeight() / 2;
float radius = (canvas.getWidth() / 2) - (outlinePaint.getStrokeWidth() / 2);
canvas.drawCircle(cx, cy, radius, outlinePaint); canvas.drawCircle(cx, cy, radius, outlinePaint);
} }
@ -85,23 +97,34 @@ public class AvatarImageView extends AppCompatImageView {
public void setAvatar(@NonNull GlideRequests requestManager, @Nullable Recipient recipient, boolean quickContactEnabled) { public void setAvatar(@NonNull GlideRequests requestManager, @Nullable Recipient recipient, boolean quickContactEnabled) {
if (recipient != null) { if (recipient != null) {
requestManager.load(recipient.getContactPhoto()) RecipientContactPhoto photo = new RecipientContactPhoto(recipient);
.fallback(recipient.getFallbackContactPhotoDrawable(getContext(), inverted))
.error(recipient.getFallbackContactPhotoDrawable(getContext(), inverted)) if (!photo.equals(recipientContactPhoto)) {
.diskCacheStrategy(DiskCacheStrategy.ALL) recipientContactPhoto = photo;
.circleCrop()
.into(this); Drawable fallbackContactPhotoDrawable = photo.recipient.getFallbackContactPhotoDrawable(getContext(), inverted);
if (photo.contactPhoto != null) {
GlideApp.with(this)
.load(photo.contactPhoto)
.fallback(fallbackContactPhotoDrawable)
.error(fallbackContactPhotoDrawable)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.circleCrop()
.into(this);
} else {
setImageDrawable(fallbackContactPhotoDrawable);
}
}
setAvatarClickHandler(recipient, quickContactEnabled); setAvatarClickHandler(recipient, quickContactEnabled);
} else { } else {
setImageDrawable(new ResourceContactPhoto(R.drawable.ic_profile_default).asDrawable(getContext(), ContactColors.UNKNOWN_COLOR.toConversationColor(getContext()), inverted)); recipientContactPhoto = null;
setImageDrawable(unknownRecipientDrawable);
super.setOnClickListener(listener); super.setOnClickListener(listener);
} }
} }
public void clear(@NonNull GlideRequests glideRequests) {
glideRequests.clear(this);
}
private void setAvatarClickHandler(final Recipient recipient, boolean quickContactEnabled) { private void setAvatarClickHandler(final Recipient recipient, boolean quickContactEnabled) {
if (!recipient.isGroupRecipient() && quickContactEnabled) { if (!recipient.isGroupRecipient() && quickContactEnabled) {
super.setOnClickListener(v -> { super.setOnClickListener(v -> {
@ -116,4 +139,24 @@ public class AvatarImageView extends AppCompatImageView {
} }
} }
private static class RecipientContactPhoto {
private final @NonNull Recipient recipient;
private final @Nullable ContactPhoto contactPhoto;
private final boolean ready;
RecipientContactPhoto(@NonNull Recipient recipient) {
this.recipient = recipient;
this.ready = !recipient.isResolving();
this.contactPhoto = recipient.getContactPhoto();
}
public boolean equals(@Nullable RecipientContactPhoto other) {
if (other == null) return false;
return other.recipient.equals(recipient) &&
other.ready == ready &&
Objects.equals(other.contactPhoto, contactPhoto);
}
}
} }

View File

@ -94,8 +94,6 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
recipient.removeListener(this); recipient.removeListener(this);
recipient = null; recipient = null;
} }
contactPhotoImage.clear(glideRequests);
} }
private void setText(int type, String name, String number, String label) { private void setText(int type, String name, String number, String label) {