Blog Infos
Author
Published
Topics
Published
Topics

In this publication, I’m addressing the challenges faced when creating a widget that requires custom fonts.

Let’s begin by introducing the results of what we will get. The idea is to show the upcoming events in a list, which are using custom fonts.

And the empty state, which should show “Nothing” text, using the Tuesday Night Font.

The bad guy

After reading the Glance documentation, I discovered that it allows font customization, but it’s limited to a few fonts and font families existing in the system. The documentation says.

Defaults are provided, but it is also possible to supply a custom family. If this is found on the system it will be used, otherwise it will fallback to a system default.

Can I provide a custom font? It has a simple answer, no, limitations with widgets prevent Glance from displaying custom fonts. There are only a few built-in fonts which we can use.

The solution

In this example, I’m using the version 1.0.0.
Basically, if the system does not provide a built-in UI or widget, we can draw it with Canvas and fortunately, this helps me to draw a custom font with Canvas. Let’s move forward to see how it actually happens.
At first, we should create a simple widget.

With the first step, you should declare the receiver inside the AndroidManifest

<receiver
android:name=".widget.event.EventsWidgetReceiver"
android:enabled="@bool/glance_appwidget_available"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/event_widget_info" />
</receiver>
view raw receiver.xml hosted with ❤ by GitHub

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

Putting a Jetpack on your legacy codebase

At Pinterest, we are always working on using the latest technologies when possible in our 10+ year old codebase.
Watch Video

Putting a Jetpack on your legacy codebase

Kurt Nelson
Senior Software Engineer

Putting a Jetpack on your legacy codebase

Kurt Nelson
Senior Software Engi ...

Putting a Jetpack on your legacy codebase

Kurt Nelson
Senior Software Engineer

Jobs

Next, we need to add information to the widget by creating a straightforward XML file inside the res/xml folder and naming it event_widget_info.xml. This XML file should include specific parameters that we need to define for the widget.

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/up_next_medium"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="200dp"
android:minHeight="80dp"
android:previewImage="@drawable/medium_up_next_widget"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen" />

After we are done with the XML, let’s move forward to the code part.
At first, we need to create a GlanceAppWidgetReceiver

class EventsWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = EventsWidget()
}

Then actually the EventsWidget

class EventsWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
Box(
modifier = GlanceModifier
.fillMaxSize()
.background(Color.White),
contentAlignment = Alignment.Center
) {
Text(
text = "Welcome to App Widget",
style = TextStyle(
color = ColorProvider(Color.Black),
fontSize = 20.sp
)
)
}
}
}
}
view raw EventsWidget.kt hosted with ❤ by GitHub

After this, you will see a simple widget with simple text.

Let’s dig deeper to understand how we can actually apply the custom fonts for the widget.
For that purpose, I have created a GlanceText, which we can use in this simple way.

Box(
modifier = GlanceModifier
.fillMaxSize()
.background(Color.White),
contentAlignment = Alignment.Center
) {
GlanceText(
modifier = GlanceModifier.padding(horizontal = 20.dp),
text = "Welcome to App Widget",
font = R.font.good_times_rg,
fontSize = 15.sp,
color = Color.Black
)
}
view raw EventsWidget.kt hosted with ❤ by GitHub

Here is the result using the GlanceText.

Old friends are coming to help

How actually GlanceText works under the hood, it uses Canvas to overcome custom font limitations in Jetpack Glance, at first I’m creating a TextPaint and then giving it the custom font and then actually drawing it with the paint. Here is the whole code, which makes it happen. Basically, you can control letterSpacingtextColorfontSize and any other properties, which TextPaint can handle.

fun Context.textAsBitmap(
text: String,
fontSize: TextUnit,
color: Color = Color.Black,
letterSpacing: Float = 0.1f,
font: Int
): Bitmap {
val paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
paint.textSize = spToPx(fontSize.value, this)
paint.color = color.toArgb()
paint.letterSpacing = letterSpacing
paint.typeface = ResourcesCompat.getFont(this, font)
val baseline = -paint.ascent()
val width = (paint.measureText(text)).toInt()
val height = (baseline + paint.descent()).toInt()
val image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(image)
canvas.drawText(text, 0f, baseline, paint)
return image
}

And the code of the GlanceText which uses an Image under the hood.

@Composable
fun GlanceText(
text: String,
@FontRes font: Int,
fontSize: TextUnit,
modifier: GlanceModifier = GlanceModifier,
color: Color = Color.Black,
letterSpacing: TextUnit = 0.1.sp
) {
Image(
modifier = modifier,
provider = ImageProvider(
LocalContext.current.textAsBitmap(
text = text,
fontSize = fontSize,
color = color,
font = font,
letterSpacing = letterSpacing.value
)
),
contentDescription = null,
)
}
view raw GlanceText.kt hosted with ❤ by GitHub

Basically, here you can draw anything with the canvas.

In our next article, I will try to share my experiments of creating an animation inside the widget. And in the end, I want to share one more example, where I used the GlanceText.

You can find the full code of this example in my Github repository.

And that’s it for today 🤩

Jetpack Glance gives us a new way to reimagine the Widgets. I have some ideas which will be covered in upcoming articles, stay tuned and clap if you like the article.

You can find me on X @chatikyan
Thanks for reading this article. I hope you enjoyed it.

THE END

This article was previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
With the introduction to Compose Google changed the way we wrote UIs in android.…
READ MORE
blog
What is CompositionLocal ? when/how can we use it? How to pass widely used…
READ MORE
blog
I have been playing around with Compose and recently implemented video playback in a…
READ MORE
blog
Hi everyone! We (Kaspresso Team and AvitoTech) are back with more about automated Android testing. Previously…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu