Android 如何在桌面AppWidget中实现带圆角边框的ImageView(Kotlin)
AppWidget中ImageView实现圆角边框的可行方案
核心原因说明
你之前的方案失败有两个核心问题:
- 桌面小部件使用RemoteViews渲染,无法直接通过
findViewById获取控件实例,也无法直接使用Glide的into(view)方法绑定视图 - ImageView的src内容不会受背景shape裁切,常规页面的裁切方案在RemoteViews中不生效
可行方案(兼容全Android版本)
步骤1:添加圆角Bitmap处理工具方法
import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.PorterDuff import android.graphics.PorterDuffXfermode import android.graphics.RectF import android.os.Build import android.content.res.Resources fun getRoundedBitmapWithBorder( source: Bitmap, cornerRadiusDp: Float, borderWidthDp: Float = 0f, borderColor: Int = Color.WHITE ): Bitmap { val density = Resources.getSystem().displayMetrics.density val cornerRadius = cornerRadiusDp * density val borderWidth = borderWidthDp * density val output = Bitmap.createBitmap(source.width, source.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(output) val paint = Paint(Paint.ANTI_ALIAS_FLAG) val rect = RectF(0f, 0f, source.width.toFloat(), source.height.toFloat()) // 绘制圆角遮罩 canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint) paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) canvas.drawBitmap(source, 0f, 0f, paint) paint.xfermode = null // 绘制边框(不需要边框可以删除这部分逻辑) if (borderWidth > 0) { paint.color = borderColor paint.style = Paint.Style.STROKE paint.strokeWidth = borderWidth val borderRect = RectF( borderWidth / 2, borderWidth / 2, source.width - borderWidth / 2, source.height - borderWidth / 2 ) canvas.drawRoundRect(borderRect, cornerRadius, cornerRadius, paint) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !source.isPremultiplied) { source.setPremultiplied(true) } return output }
步骤2:替换原有加载头像的错误代码
删除原逻辑中findViewById和Glide直接绑定控件的代码,替换为异步加载+Bitmap处理逻辑:
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext // 放在RemoteViews初始化逻辑之后 val avatarUrl = "http://p15.qhimg.com/bdm/720_444_0/t01b12dfd7f42342197.jpg" CoroutineScope(Dispatchers.IO).launch { // 子线程加载并处理图片 val originBitmap = Glide.with(context) .asBitmap() .load(avatarUrl) .submit() .get() // 生成20dp圆角、2dp白色边框的Bitmap,不需要边框可省略后两个参数 val roundedBitmap = getRoundedBitmapWithBorder(originBitmap, 20f, 2f) // 主线程更新RemoteViews withContext(Dispatchers.Main) { views.setImageViewBitmap(R.id.avatar, roundedBitmap) appWidgetManager.updateAppWidget(widgetId, views) } }
简化方案(仅支持Android 12及以上)
如果你的应用最低适配API 31,可以直接在布局的ImageView标签添加属性,无需额外代码处理:
<ImageView android:id="@+id/avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:outlineProvider="background" android:clipToOutline="true" android:background="@drawable/你的圆角shape文件" />
内容的提问来源于stack exchange,提问作者Nicholas Jela
相关产品推荐
相关产品推荐

