Question about font weight. It is represented by a...
# compose
z
Question about font weight. It is represented by an integer, and the standard weights are increments of 100. This suggests that it should be possible to (somewhat) smoothly animate between weights. However, when I try doing so, at least with the standard system font on a Pixel 3, it looks like the actual weight values are being coerced to a fixed set of weight steps. So it would seem like the weight values are not being used to somehow dynamically draw the weights. It makes sense that the font is just asked to provide glyphs as close as possible to the weight, so I’m not surprised, but just wanted to confirm.
s
when there are • font 100 file • font 200 file • font 400 file A font value has to be matched to one of those. When the font is a variable font with the support then it should be possible to pass 132 to the font for the freetype/font to render it in that weight. You are right that right now there isn’t much meaning of that value right now, and we do not have support for variable fonts. I guess we left it open because of that (which we could actually hide it and open when required).
I didnt think very deeply about the variable font but having support for any weight made sense at the time for variable fonts and animations.
z
So even if using a custom font that supports variable weight, Compose wouldn’t actually render it with arbitrary weight?
s
I believe we pass in the value to android typeface, but never tried varaiable font on compose yet.
r
There’s an alternative though
Which may not work depending on your use case
s
(also the initial variable font was added in android 26) and looking at the code [21,24], [26, 28] [28,..] might have different behavior right now.
r
But you can request the
Path
outline of a chunk of text
And then you can stroke/fill that
Path
and vary the stroke width smoothly
s
(also it is possible to create a Typeface on android with the variable font, create a FontFamily using Android.Typeface and pass that one in)
z
But you can request the 
Path
 outline of a chunk of text
That’s an Android-specific api, not Compose, right?
Trying with this font on API 30, seems to only render in two different weights.
Copy code
val variableFont = remember { FontFamily(Font(R.raw.variable_font)) }
val animatedWeight by rememberInfiniteTransition()
  .animateFloat(
    initialValue = 1f, targetValue = 1000f,
    infiniteRepeatable(tween(5000), repeatMode = Reverse)
  )
Text(
  "Weight: ${animatedWeight.toInt()}",
  fontWeight = FontWeight(animatedWeight.toInt()),
  fontFamily = variableFont
)
Anyhoo, thanks for the idea @romainguy!
a
In View system to set the weight of a variable font you have to use
textView.fontVariationSettings = "'wght' 150"
, in which
fontVariationSettings
isn't used in typeface resolving and is instead set on the underlying
TextPaint
. This is the reason why directly setting font weight won't work. In Compose UI we can set
fontFeatureSettings
through
TextStyle
and it'll be nice if we can also set
fontVariationSettings
.
today i learned 1
ATM we can use
AndroidView
to animate font weight.
Copy code
val weight by rememberInfiniteTransition().animateFloat(
    initialValue = 1f,
    targetValue = 1000f,
    animationSpec = infiniteRepeatable(
        animation = tween(
            durationMillis = 2000,
            easing = LinearEasing
        ),
        repeatMode = RepeatMode.Reverse
    )
)
AndroidView(
    factory = {
        TextView(it).apply {
            text = "Animated Weight"
            setTextSize(TypedValue.COMPLEX_UNIT_SP, 80f)
            textAlignment = View.TEXT_ALIGNMENT_CENTER
        }
    },
    modifier = Modifier.fillMaxWidth()
) {
    it.fontVariationSettings = "'wght' ${weight.toInt()}"
}
Note that
fontVariationSettings
is only available on API 26+ and Android 12 starts to use variable fonts as system fonts.
z
Woah neat. Any chance you wanna file a feature request for exposing
fontVariationSettings
in the Compose API?
Also TIL about “uniwidth” fonts, which are also helpful for animating weight
a