Introduce glyph fonts to correct spacing.
This commit is contained in:
parent
4dd3b92eda
commit
5c5d55d265
4 changed files with 114 additions and 17 deletions
BIN
app/src/main/assets/fonts/SignalSymbols-Bold.otf
Normal file
BIN
app/src/main/assets/fonts/SignalSymbols-Bold.otf
Normal file
Binary file not shown.
|
@ -7,9 +7,9 @@ import android.view.View
|
|||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.ContextUtil
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
|
@ -57,20 +57,31 @@ object BioTextPreference {
|
|||
SpanUtil.appendSpacer(this, 8)
|
||||
SpanUtil.appendCenteredImageSpanWithoutSpace(this, ContextUtil.requireDrawable(context, R.drawable.ic_official_28), 28, 28)
|
||||
} else if (recipient.isSystemContact) {
|
||||
val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_person_circle_24).apply {
|
||||
setTint(ContextCompat.getColor(context, R.color.signal_colorOnSurface))
|
||||
val systemContactGlyph = SignalSymbols.getSpannedString(
|
||||
context,
|
||||
SignalSymbols.Weight.BOLD,
|
||||
SignalSymbols.Glyph.PERSON_CIRCLE
|
||||
).let {
|
||||
SpanUtil.ofSize(it, 20)
|
||||
}
|
||||
SpanUtil.appendSpacer(this, 8)
|
||||
SpanUtil.appendCenteredImageSpanWithoutSpace(this, drawable, 24, 24)
|
||||
|
||||
append(" ")
|
||||
append(systemContactGlyph)
|
||||
}
|
||||
|
||||
if (recipient.isIndividual && !recipient.isSelf) {
|
||||
val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_chevron_right_24).apply {
|
||||
setBounds(0, 0, 24.dp, 24.dp)
|
||||
setTint(ContextCompat.getColor(context, R.color.signal_colorOutline))
|
||||
val chevronGlyph = SignalSymbols.getSpannedString(
|
||||
context,
|
||||
SignalSymbols.Weight.BOLD,
|
||||
SignalSymbols.Glyph.CHEVRON_RIGHT
|
||||
).let {
|
||||
SpanUtil.ofSize(it, 24)
|
||||
}.let {
|
||||
SpanUtil.color(ContextCompat.getColor(context, R.color.signal_colorOutline), it)
|
||||
}
|
||||
|
||||
append(SpanUtil.buildCenteredImageSpan(drawable))
|
||||
append(" ")
|
||||
append(chevronGlyph)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.fonts
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.TextPaint
|
||||
import android.text.style.MetricAffectingSpan
|
||||
|
||||
/**
|
||||
* Helper object for working with the SignalSymbols font
|
||||
*/
|
||||
object SignalSymbols {
|
||||
|
||||
enum class Glyph(val unicode: Char) {
|
||||
CHEVRON_RIGHT('\uE025'),
|
||||
PERSON_CIRCLE('\uE05E')
|
||||
}
|
||||
|
||||
enum class Weight {
|
||||
BOLD
|
||||
}
|
||||
|
||||
private val cache = mutableMapOf<Weight, Typeface>()
|
||||
|
||||
fun getSpannedString(
|
||||
context: Context,
|
||||
weight: Weight,
|
||||
glyph: Glyph
|
||||
): CharSequence {
|
||||
val typeface = getTypeface(context, weight)
|
||||
val span = CustomTypefaceSpan(typeface)
|
||||
|
||||
val text = SpannableStringBuilder(glyph.unicode.toString())
|
||||
text.setSpan(span, 0, text.length, 0)
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
private fun getTypeface(context: Context, weight: Weight): Typeface {
|
||||
return when (weight) {
|
||||
Weight.BOLD -> getBoldWeightedFont(context)
|
||||
else -> error("Unsupported weight: $weight")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBoldWeightedFont(context: Context): Typeface {
|
||||
return cache.getOrPut(
|
||||
Weight.BOLD
|
||||
) {
|
||||
Typeface.createFromAsset(
|
||||
context.assets,
|
||||
"fonts/SignalSymbols-Bold.otf"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom TypefaceSpan to support TypefaceSpan in API<28
|
||||
*
|
||||
* Source: https://www.youtube.com/watch?v=x-FcOX6ErdI&t=486s
|
||||
*/
|
||||
private class CustomTypefaceSpan(val font: Typeface?) : MetricAffectingSpan() {
|
||||
override fun updateMeasureState(textPaint: TextPaint) = update(textPaint)
|
||||
override fun updateDrawState(textPaint: TextPaint?) = update(textPaint)
|
||||
|
||||
private fun update(tp: TextPaint?) {
|
||||
tp.apply {
|
||||
val old = this!!.typeface
|
||||
val oldStyle = old?.style ?: 0
|
||||
val font = Typeface.create(font, oldStyle)
|
||||
typeface = font
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon;
|
|||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.ButtonStripPreference;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp;
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
@ -191,17 +192,22 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
|
|||
SpanUtil.appendSpacer(nameBuilder, 8);
|
||||
SpanUtil.appendCenteredImageSpanWithoutSpace(nameBuilder, ContextUtil.requireDrawable(requireContext(), R.drawable.ic_official_28), 28, 28);
|
||||
} else if (recipient.isSystemContact()) {
|
||||
Drawable drawable = ContextUtil.requireDrawable(requireContext(), R.drawable.symbol_person_circle_24);
|
||||
drawable.setTint(ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurface));
|
||||
SpanUtil.appendSpacer(nameBuilder, 8);
|
||||
SpanUtil.appendCenteredImageSpanWithoutSpace(nameBuilder, drawable, 24, 24);
|
||||
CharSequence systemContactGlyph = SignalSymbols.INSTANCE.getSpannedString(requireContext(),
|
||||
SignalSymbols.Weight.BOLD,
|
||||
SignalSymbols.Glyph.PERSON_CIRCLE);
|
||||
|
||||
nameBuilder.append(" ");
|
||||
nameBuilder.append(SpanUtil.ofSize(systemContactGlyph, 20));
|
||||
}
|
||||
|
||||
if (!recipient.isSelf() && recipient.isIndividual()) {
|
||||
Drawable drawable = ContextUtil.requireDrawable(requireContext(), R.drawable.symbol_chevron_right_24);
|
||||
drawable.setBounds(0, 0, (int) DimensionUnit.DP.toPixels(24), (int) DimensionUnit.DP.toPixels(24));
|
||||
drawable.setTint(ContextCompat.getColor(requireContext(), R.color.signal_colorOutline));
|
||||
nameBuilder.append(SpanUtil.buildCenteredImageSpan(drawable));
|
||||
CharSequence chevronGlyph = SignalSymbols.INSTANCE.getSpannedString(requireContext(),
|
||||
SignalSymbols.Weight.BOLD,
|
||||
SignalSymbols.Glyph.CHEVRON_RIGHT);
|
||||
|
||||
nameBuilder.append(" ");
|
||||
nameBuilder.append(SpanUtil.color(ContextCompat.getColor(requireContext(), R.color.signal_colorOutline),
|
||||
SpanUtil.ofSize(chevronGlyph, 24)));
|
||||
|
||||
fullName.setText(nameBuilder);
|
||||
fullName.setOnClickListener(v -> {
|
||||
|
|
Loading…
Add table
Reference in a new issue