Android Jetpack Compose开发Glance小组件【实现自定义字体篇】

**截止 Jetpack Compose Glance1.1.0官方小组件目前Glance Text不支持自定义字体,只默认支持官方自带,如下

package androidx.glance.text

/**
 * Describes the family of the font.
 * 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.
 */
class FontFamily constructor(val family: String) {
    companion object {
        /**
         * The formal text style for scripts.
         */
        val Serif = FontFamily("serif")

        /**
         * Font family with low contrast and plain stroke endings.
         */
        val SansSerif = FontFamily("sans-serif")

        /**
         * Font family where glyphs have the same fixed width.
         */
        val Monospace = FontFamily("monospace")

        /**
         * Cursive, hand-written like font family.
         */
        val Cursive = FontFamily("cursive")
    }

    override fun toString(): String {
        return family
    }
}


要实现自定UI字体,需要使用自定义文本Bitmap,就是以图片的加载自定义字体【在 Jetpack Compose Glance 1.1.0 中,官方小组件的 Glance Text 不支持自定义字体,仅支持默认的 Serif、SansSerif、Monospace 和 Cursive 字体。要实现自定义字体,可以通过将文本渲染为 Bitmap 的方式来实现。具体步骤包括:使用 Paint 类设置字体、颜色和大小,然后通过 Canvas 将文本绘制到 Bitmap 上。最后,将生成的 Bitmap 作为 Image 显示在小组件中。这种方法虽然绕过了 Glance Text 的限制,但增加了实现的复杂性】。
字体放置位置:
在这里插入图片描述
实现自定义字体carter_one.ttf方式如下
核心代码

@SuppressLint("ResourceAsColor")
    fun createTextBitmap(context: Context, text: String, fontResId: Int): Bitmap {
        val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = ContextCompat.getColor(context, R.color.white) // 从资源获取白色
            textSize = 50f  //字体大小
            typeface = ResourcesCompat.getFont(context, fontResId)
        }
        val width = paint.measureText(text).toInt()
        val height = paint.fontMetrics.run { (descent - ascent).toInt() }

        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        canvas.drawText(text, 0f, -paint.fontMetrics.ascent, paint)
        return bitmap
    }

完整代码:

class CattleLikeWorkerGlanceSmallWidgetStyleOne : GlanceAppWidget() {

    @SuppressLint("ResourceAsColor")
    fun createTextBitmap(context: Context, text: String, fontResId: Int): Bitmap {
        val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = ContextCompat.getColor(context, R.color.white) // 从资源获取白色
            textSize = 50f  //字体大小
            typeface = ResourcesCompat.getFont(context, fontResId)
        }
        val width = paint.measureText(text).toInt()
        val height = paint.fontMetrics.run { (descent - ascent).toInt() }

        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        canvas.drawText(text, 0f, -paint.fontMetrics.ascent, paint)
        return bitmap
    }


    private fun createRemoteViews(context: Context): RemoteViews {
        return RemoteViews(
            context.packageName,
            R.layout.custom_widget_layout
        ).apply {

        }
    }

    fun forceUpdate() {
        CoroutineScope(Dispatchers.Default).launch {
            GlanceAppWidgetManager(context).getGlanceIds(CattleLikeWorkerGlanceSmallWidgetStyleOne::class.java)
                .forEach { glanceId ->
                    update(context, glanceId)
                }
        }
    }

    @SuppressLint("UnrememberedMutableState")
    override suspend fun provideGlance(context: Context, id: GlanceId) {
        provideContent {
           Content()
        }
    }


    @Composable
    fun CustomTextWidget() {
        // 使用 RemoteViews 引用自定义布局

    }


    @Composable
    private fun Content() {
        Box(
            modifier = GlanceModifier
                .fillMaxSize()
                .background(ColorProvider(Color(0XFF000000)))
                .cornerRadius(22.dp)

        ) {
            Box(
                modifier = GlanceModifier
                    .padding(vertical = 16.67.dp, horizontal = 16.67.dp)
                    .fillMaxSize(),
                contentAlignment = Alignment.TopStart
            ) {
                Column {
                    Text(
                        text = "小组件字体测试【常规字体】",
                        style = TextStyle(
                            color = ColorProvider(Color(0xFFE9E9E9)),
                            fontWeight = FontWeight.Normal,
                            fontSize = 10.sp
                        ),
                        maxLines = 1, // 限制为单行
                    )


                    val bitmap = createTextBitmap(context, "小组件字体测试【自定义字体】", R.font.carter_one)
                    Image(
                        provider = ImageProvider(bitmap),
                        contentDescription = null,
                        modifier = GlanceModifier
                    )
                }
            }


            Box(
                modifier = GlanceModifier
                    //.padding(10.dp)
                    .fillMaxSize(),
                contentAlignment = Alignment.CenterStart
            ) {

            }

            Box(
                modifier = GlanceModifier
                    .padding(13.dp)
                    .fillMaxSize(),
                contentAlignment = Alignment.BottomStart
            ) {
                Column(
                    modifier = GlanceModifier
                        .fillMaxWidth(),
                    verticalAlignment = Alignment.Vertical.CenterVertically
                ) {
                    Column(
                        modifier = GlanceModifier
                            .background(ColorProvider(Color(0xFFFF4C01)))
                            .cornerRadius(7.dp)
                            .padding(horizontal = 12.dp, vertical = 3.dp),
                    ) {

                        val bitmap = createTextBitmap(context, "¥ 290.17", R.font.carter_one)
                        Image(
                            provider = ImageProvider(bitmap),
                            contentDescription = null,
                            modifier = GlanceModifier
                        )

                        Text(
                            text = "¥ 290.17",
                            style = TextStyle(
                                color = ColorProvider(Color.Black),
                                fontSize = 13.sp,
                                fontWeight = FontWeight.Medium
                            ),
                            maxLines = 1
                        )
                    }
                }
            }
        }
    }
}

注意Glance里使用RemoteViews加载原始的带字体样式【android:fontFamily=“@font/carter_one”】的xml布局也是不行的。
整体效果如下:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值