make avatar shape configurable (in code)

This commit is contained in:
Daniel Gultsch 2023-03-08 09:52:01 +01:00
parent 26d856e91f
commit eb15dc1260
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
6 changed files with 50 additions and 14 deletions

View file

@ -10,6 +10,7 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import im.conversations.android.R;
import im.conversations.android.database.model.AddressWithName;
import im.conversations.android.database.model.AvatarWithAccount;
import im.conversations.android.ui.graphics.drawable.AvatarDrawable;
@ -59,9 +60,18 @@ public class AvatarFetcher {
LOGGER.info("ImageView reference was gone after fetching avatar");
return;
}
final var resources = imageView.getResources();
final var roundedBitmapDrawable =
RoundedBitmapDrawableFactory.create(imageView.getResources(), result);
roundedBitmapDrawable.setCircular(true);
RoundedBitmapDrawableFactory.create(resources, result);
final boolean circular = resources.getBoolean(R.bool.avatar_chat_overview_circular);
if (circular) {
roundedBitmapDrawable.setCircular(true);
} else {
final float radius =
resources.getDimension(R.dimen.avatar_chat_overview_radius)
/ resources.getDimension(R.dimen.avatar_chat_overview_size);
roundedBitmapDrawable.setCornerRadius(result.getWidth() * radius);
}
imageView.setImageDrawable(roundedBitmapDrawable);
}

View file

@ -20,6 +20,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import com.google.android.material.elevation.SurfaceColors;
@ -44,17 +45,22 @@ public class AvatarDrawable extends ColorDrawable {
private final int intrinsicWidth;
private final Context context;
private final boolean circular;
private final int roundedCornerRadius;
public AvatarDrawable(final Context context, final AddressWithName addressWithName) {
this.context = context;
final String name = addressWithName.name;
final Jid key = addressWithName.address;
this.paint = getPaint(addressWithName.address);
this.textPaint = getTextPaint();
final Matcher matcher = LETTER_PATTERN.matcher(Strings.nullToEmpty(name));
this.letter = matcher.find() ? matcher.group().toUpperCase(Locale.ROOT) : null;
final var resources = context.getResources();
final int avatarDrawableSize =
context.getResources().getDimensionPixelSize(R.dimen.avatar_drawable_size);
resources.getDimensionPixelSize(R.dimen.avatar_chat_overview_size);
this.circular = resources.getBoolean(R.bool.avatar_chat_overview_circular);
this.roundedCornerRadius =
resources.getDimensionPixelSize(R.dimen.avatar_chat_overview_radius);
this.intrinsicHeight = avatarDrawableSize;
this.intrinsicWidth = avatarDrawableSize;
}
@ -78,16 +84,25 @@ public class AvatarDrawable extends ColorDrawable {
@Override
public void draw(final Canvas canvas) {
final float midX = getBounds().width() / 2.0f;
final float midY = getBounds().height() / 2.0f;
final float radius = Math.min(getBounds().width(), getBounds().height()) / 2.0f;
textPaint.setTextSize(radius);
this.textPaint.setTextSize(radius);
final Rect r = new Rect();
canvas.getClipBounds(r);
final int cHeight = r.height();
final int cWidth = r.width();
// TODO if we ever want to do rounded corners we can use drawRoundRect()
canvas.drawCircle(midX, midY, radius, paint);
final var roundedSquareRadius =
context.getResources().getDimensionPixelSize(R.dimen.avatar_chat_overview_radius);
if (this.circular) {
final float midX = getBounds().width() / 2.0f;
final float midY = getBounds().height() / 2.0f;
canvas.drawCircle(midX, midY, radius, paint);
} else {
canvas.drawRoundRect(
new RectF(0, 0, getBounds().width(), getBounds().height()),
roundedSquareRadius,
roundedSquareRadius,
paint);
}
if (letter == null) {
return;
}

View file

@ -3,6 +3,7 @@ package im.conversations.android.xmpp.manager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.hash.Hashing;
@ -102,7 +103,12 @@ public class AvatarManager extends AbstractManager {
return Futures.transform(
getAvatar(address, type, id),
bytes -> {
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
final var sourceBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
final var size = Math.min(sourceBitmap.getHeight(), sourceBitmap.getWidth());
// return a square version of the avatar. we are not displaying the rest and can
// save the bytes plus the corner radius calculation in AvatarFetcher requires a
// square
return ThumbnailUtils.extractThumbnail(sourceBitmap, size, size);
},
CPU_EXECUTOR);
}

View file

@ -10,9 +10,10 @@
<ImageView
android:id="@+id/avatar"
android:layout_width="@dimen/avatar_drawable_size"
android:layout_height="@dimen/avatar_drawable_size"
android:layout_margin="16dp"
android:layout_width="@dimen/avatar_chat_overview_size"
android:layout_height="@dimen/avatar_chat_overview_size"
android:layout_marginStart="16dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

View file

@ -0,0 +1,5 @@
<resources>
<dimen name="avatar_chat_overview_size">40dp</dimen>
<bool name="avatar_chat_overview_circular">false</bool>
<dimen name="avatar_chat_overview_radius">10dp</dimen>
</resources>

View file

@ -8,5 +8,4 @@
<dimen name="in_call_fab_margin">8dp</dimen>
<dimen name="in_call_fab_margin_center">12dp</dimen>
<dimen name="publish_avatar_size">96dp</dimen>
<dimen name="avatar_drawable_size">40dp</dimen>
</resources>