You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android桌面小部件中动态设置Shape描边颜色?

问题描述

我有一个名为rounded_corner_shape.xml的Drawable文件:

<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <stroke
        android:width="1dp"
        android:color="TO_BE_SET_DYNAMICALLY" />

    <corners android:radius="8dp" />
</shape>

该文件被用于ip_properties.xml布局中:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/ip_property_tv_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/rounded_corner_shape" />
</LinearLayout>

我希望在RemoteViewsService.RemoteViewsFactory的实现类中动态设置描边颜色,代码框架如下:

class WifiPropertyViewsFactory: RemoteViewsService.RemoteViewsFactory{
    // 其他重写方法...

    override fun getViewAt(position: Int): RemoteViews =
       RemoteViews(context.packageName, R.layout.ip_properties)
                .apply {
                    setTextViewText(R.id.ip_property_tv_1, "some data")
                    // 这里需要设置带圆角的背景描边颜色
                }

}

尝试用RemoteViews.setInt(R.id.ip_property_tv_1, "setBackgroundTint", colorInt)实现,但没有效果,请问该如何解决?


解决方案

setBackgroundTint无法生效的原因是:这个方法是对整个Drawable进行着色,而你的需求是单独修改shape中的描边属性,且RemoteViews本身不支持直接修改已加载的shape内部属性。以下是几种可行的实现方式:

方法一:API 24+ 直接设置动态生成的Drawable

如果你的应用最低兼容API 24及以上,这是最直接的方案:

  1. 先实现dp转px的工具方法:
fun Int.dpToPx(context: Context): Int {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        this.toFloat(),
        context.resources.displayMetrics
    ).toInt()
}
  1. 在getViewAt中动态创建GradientDrawable(对应你的shape)并设置属性:
override fun getViewAt(position: Int): RemoteViews =
    RemoteViews(context.packageName, R.layout.ip_properties)
        .apply {
            setTextViewText(R.id.ip_property_tv_1, "some data")
            
            val gradientDrawable = GradientDrawable().apply {
                cornerRadius = 8.dpToPx(context).toFloat()
                setStroke(1.dpToPx(context), colorInt) // colorInt为目标颜色值
            }
            
            setDrawable(R.id.ip_property_tv_1, "background", gradientDrawable)
        }

方法二:通过Bitmap间接设置(兼容低版本)

如果需要兼容API 24以下的版本,可将动态生成的Drawable转换成Bitmap再设置为背景:

override fun getViewAt(position: Int): RemoteViews =
    RemoteViews(context.packageName, R.layout.ip_properties)
        .apply {
            setTextViewText(R.id.ip_property_tv_1, "some data")
            
            // 生成带圆角和描边的Drawable
            val gradientDrawable = GradientDrawable().apply {
                cornerRadius = 8.dpToPx(context).toFloat()
                setStroke(1.dpToPx(context), colorInt)
                // 根据TextView预估尺寸设置Drawable大小,避免显示异常
                setSize(200.dpToPx(context), 40.dpToPx(context))
            }
            
            // 转换为Bitmap
            val bitmap = Bitmap.createBitmap(
                gradientDrawable.intrinsicWidth,
                gradientDrawable.intrinsicHeight,
                Bitmap.Config.ARGB_8888
            )
            val canvas = Canvas(bitmap)
            gradientDrawable.setBounds(0, 0, canvas.width, canvas.height)
            gradientDrawable.draw(canvas)
            
            // 设置Bitmap为背景
            setImageViewBitmap(R.id.ip_property_tv_1, bitmap)
        }

方法三:利用TintList覆盖描边颜色

修改shape文件的描边颜色为基础色,再通过tintList覆盖颜色:

  1. 修改rounded_corner_shape.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <stroke
        android:width="1dp"
        android:color="@android:color/transparent" />
    <corners android:radius="8dp" />
</shape>
  1. 在RemoteViews中设置背景tint列表:
override fun getViewAt(position: Int): RemoteViews =
    RemoteViews(context.packageName, R.layout.ip_properties)
        .apply {
            setTextViewText(R.id.ip_property_tv_1, "some data")
            val tintList = ColorStateList.valueOf(colorInt)
            setColorStateList(R.id.ip_property_tv_1, "backgroundTintList", tintList)
        }

注意:此方案仅适用于shape只有描边和圆角、无填充色的场景,否则tint会同时影响填充色。


内容的提问来源于stack exchange,提问作者w2sv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 06:05:36