Skip to content

Commit

Permalink
Convert all Thumbprint Avatars to circle shape (#60)
Browse files Browse the repository at this point in the history
Thumbprint design is changing entity avatars to be a circular shape,
meaning they will now render exactly how user avatars render. However,
we will still keep both the ThumbprintUserAvatar and ThumbprintEntityAvatar
around to keep the semantics separate and to allow for future changes
to one instead of the other.
  • Loading branch information
brian-terczynski authored Aug 23, 2024
1 parent 808cff8 commit b85b74f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,9 @@ import kotlin.math.min
* The background color is determined within this Thumbprint component, based on the ASCII values of
* the initials' first character; this implementation is shared between Thumbprint platforms (i.e.
* web and iOS), see [setColorsFromInitials].
*
* @param isEntity whether the avatar represents an entity, i.e. a business rather than individual,
* which uses a rounded-rectangle shape rather than circle and a single initial
* rather than two
*/
internal class BlankAvatarDrawable(
val context: Context,
private val isEntity: Boolean,
private val initialsFontSize: Int
) : Drawable() {

Expand All @@ -47,8 +42,6 @@ internal class BlankAvatarDrawable(
private val backgroundColors = context.resources.getIntArray(
R.array.blank_avatar_background_colors
)
private val roundingRadius = context.resources
.getDimensionPixelSize(R.dimen.round_corner_radius).toFloat()

private var backgroundColor: Int = -1
private var textColor: Int = -1
Expand Down Expand Up @@ -80,11 +73,7 @@ internal class BlankAvatarDrawable(

override fun draw(canvas: Canvas) {
paint.color = backgroundColor
if (isEntity) {
canvas.drawRoundRect(bounds, roundingRadius, roundingRadius, paint)
} else {
canvas.drawCircle(centerX, centerY, radius, paint)
}
canvas.drawCircle(centerX, centerY, radius, paint)

text?.let {
paint.color = textColor
Expand All @@ -105,7 +94,7 @@ internal class BlankAvatarDrawable(
}

private fun setColorsFromInitials(initials: String?) {
val hash = initials?.firstOrNull()?.toInt()
val hash = initials?.firstOrNull()?.code
if (hash == null) {
backgroundColor = ContextCompat.getColor(context, R.color.tp_gray_200)
textColor = ContextCompat.getColor(context, R.color.tp_black)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@ import androidx.annotation.StyleableRes
import com.squareup.picasso.Picasso
import com.squareup.picasso.Transformation
import com.thumbtack.thumbprint.BlankAvatarDrawable
import com.thumbtack.thumbprint.CircularImageTransformation
import com.thumbtack.thumbprint.R
import kotlinx.android.synthetic.main.avatar_view.view.*
import java.util.Locale

/**
* Displays a Thumbprinted avatar image for a user.
*
* Avatars may be entities ([isEntity]), i.e. a business rather than an individual, which use a
* rounded-rectangle shape rather than a circle and a single initial rather than two.
* Displays a Thumbprint avatar image for a user.
*/
abstract class AvatarViewBase(context: Context, attrs: AttributeSet? = null, isEntity: Boolean) :
abstract class AvatarViewBase(context: Context, attrs: AttributeSet? = null) :
RelativeLayout(context, attrs) {

class InvalidSizeException(message: String) : Exception(message)
Expand Down Expand Up @@ -71,13 +69,11 @@ abstract class AvatarViewBase(context: Context, attrs: AttributeSet? = null, isE

initialsPlaceholder = BlankAvatarDrawable(
context,
isEntity = isEntity,
initialsFontSize = fontSize
)

loadingPlaceholder = BlankAvatarDrawable(
context,
isEntity = isEntity,
initialsFontSize = fontSize
)
}
Expand Down Expand Up @@ -153,16 +149,29 @@ abstract class AvatarViewBase(context: Context, attrs: AttributeSet? = null, isE
}

/**
* Returns the transformation needed for the Image View,
* which is either a circular mask for user avatars or a
* rounded rectangle mask for entity avatars.
* Returns the transformation needed for the Image View
*/
abstract fun getTransformation(): Transformation
private fun getTransformation(): Transformation {
return CircularImageTransformation
}

/**
* Returns the size in pixels of the online badge
*/
abstract fun getOnlineBadgeSize(size: Size): Int
private fun getOnlineBadgeSize(size: Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_extra_large)
}
}

/**
* Returns the X translation, in pixels, that the online badge
Expand All @@ -173,7 +182,21 @@ abstract class AvatarViewBase(context: Context, attrs: AttributeSet? = null, isE
* image to not clip children). As a result, the position of badges on Android are
* different than those on Web/iOS.
*/
abstract fun getOnlineBadgeOffsetX(size: Size): Int
private fun getOnlineBadgeOffsetX(size: Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_extra_large)
}
}


/**
* Returns the Y translation, in pixels, that the online badge
Expand All @@ -184,7 +207,20 @@ abstract class AvatarViewBase(context: Context, attrs: AttributeSet? = null, isE
* image to not clip children). As a result, the position of badges on Android are
* different than those on Web/iOS.
*/
abstract fun getOnlineBadgeOffsetY(size: Size): Int
private fun getOnlineBadgeOffsetY(size: Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_extra_large)
}
}

companion object {
private const val DEFAULT_ATTRIBUTE_INDEX = -1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,6 @@ package com.thumbtack.thumbprint.views.avatar

import android.content.Context
import android.util.AttributeSet
import com.squareup.picasso.Transformation
import com.thumbtack.thumbprint.R
import com.thumbtack.thumbprint.RoundedCornersImageTransformation

class ThumbprintEntityAvatar(context: Context, attrs: AttributeSet? = null) :
AvatarViewBase(context, attrs, true) {

override fun getTransformation(): Transformation {
return RoundedCornersImageTransformation.get(context)
}

override fun getOnlineBadgeSize(size: Companion.Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_extra_large)
}
}

override fun getOnlineBadgeOffsetX(size: Companion.Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_x_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_x_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_x_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_x_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_x_extra_large)
}
}

override fun getOnlineBadgeOffsetY(size: Companion.Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_y_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_y_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_y_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_y_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.entity_avatar_badge_offset_y_extra_large)
}
}
}
AvatarViewBase(context, attrs)
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,6 @@ package com.thumbtack.thumbprint.views.avatar

import android.content.Context
import android.util.AttributeSet
import com.squareup.picasso.Transformation
import com.thumbtack.thumbprint.CircularImageTransformation
import com.thumbtack.thumbprint.R

class ThumbprintUserAvatar(context: Context, attrs: AttributeSet? = null) :
AvatarViewBase(context, attrs, false) {

override fun getTransformation(): Transformation {
return CircularImageTransformation
}

override fun getOnlineBadgeSize(size: Companion.Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_extra_large)
}
}

override fun getOnlineBadgeOffsetX(size: Companion.Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_x_extra_large)
}
}

override fun getOnlineBadgeOffsetY(size: Companion.Size): Int {
return when (size) {
Companion.Size.EXTRA_SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_extra_small)
Companion.Size.SMALL -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_small)
Companion.Size.MEDIUM -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_medium)
Companion.Size.LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_large)
Companion.Size.EXTRA_LARGE -> resources
.getDimensionPixelSize(R.dimen.user_avatar_badge_offset_y_extra_large)
}
}
}
AvatarViewBase(context, attrs)

0 comments on commit b85b74f

Please sign in to comment.