Bartek Lipinski
Bartek Lipinski

Reputation: 31468

How to convert TextStyle from Jetpack Compose to android.graphics.Typeface?

I need to draw text onto Canvas in Compose, for this purpose I need a TextPaint with android.graphics.Typeface.

Is there a way to easily convert Compose TextStyle to a android.graphics.Typeface?

Upvotes: 16

Views: 5360

Answers (5)

Jaya Surya Thotapalli
Jaya Surya Thotapalli

Reputation: 186

You can resolve android.graphics.Typeface object from a androidx.compose.ui.text.TextStyle object using LocalFontFamilyResolver.

val style: TextStyle = MaterialTheme.typography.body1
val resolver: FontFamily.Resolver = LocalFontFamilyResolver.current

val typeface: Typeface = remember(resolver, style) {
    resolver.resolve(
        fontFamily = style.fontFamily,
        fontWeight = style.fontWeight ?: FontWeight.Normal,
        fontStyle = style.fontStyle ?: FontStyle.Normal,
        fontSynthesis = style.fontSynthesis ?: FontSynthesis.All,
    )
}.value as Typeface

Upvotes: 17

vpuonti
vpuonti

Reputation: 101

I ran into the same issue as you: Wanting to draw text to a Canvas in a TextStyle that is defined in my Compose Theme.

I found out you can use androidx.compose.ui.text.Paragraph.paint(canvas) to draw text to the Canvas.

That in itself has no way to set offsets for the paint job, so you can use drawContext.canvas.nativeCanvas.withTranslation() to move the drawing to a specified offset.

val paragraph = Paragraph(
  text = "Hello",
  style = MaterialTheme.typography.titleLarge,
  constraints = Constraints(),
  density = LocalDensity.current,
  fontFamilyResolver = LocalFontFamilyResolver.current,
)
val colorOnSurface = MaterialTheme.colorScheme.onSurface

Canvas(
  modifier = Modifier.fillMaxSize()
) {
  //
  drawContext.canvas.nativeCanvas.withTranslation(
    100f,
    100f
  ) {
      paragraph.paint(
        canvas = drawContext.canvas,
        color = colorOnSurface,
      )
  }
}

This seems quite sketchy, but it's the best I've got ¯_(ツ)_/¯.

Upvotes: 0

OneDev
OneDev

Reputation: 617

try this

    val textPaint = TextPaint()
    val context = LocalContext.current
    Canvas(modifier = Modifier.fillMaxWidth()) {
        textPaint.apply {
            typeface = Typeface.createFromAsset(context.assets, "fonts/yourfont.ttf")
                ...
        }
        drawContext.canvas.nativeCanvas.drawText("test", yourStart, yourEnd, X, Y, textPaint)
    }

Upvotes: 0

RaBaKa 78
RaBaKa 78

Reputation: 1475

To draw text to canvas, you can do like this

@Composable
fun DrawText() {
    val paint = Paint().asFrameworkPaint()
    Canvas(modifier = Modifier.fillMaxSize()) {
        paint.apply {
            isAntiAlias = true
            textSize = 24f
            typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) // your typeface

            //other methods like color, dither, fontMetrics, shadow etc...are also available 

        }

        drawIntoCanvas {
            it.nativeCanvas.drawText("Hello World", size.width/2, size.height/2, paint)
        }
    }
}

I think to convert TextStyle(compose library) to typeface will be a pain since no support from android, If you want to draw text to canvas I think this will be enough

Upvotes: -1

Ajaz Ahmed
Ajaz Ahmed

Reputation: 319

Currently the only workaround that i found is to provide with resources:

val textTypeface: android.graphics.Typeface? =
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) LocalContext.current.resources.getFont(R.font.quicksand_light) else null

However if android version < android oreo, idk how to provide the font, so i fallback to default fount.

Upvotes: 1

Related Questions