Android 如何在小部件中使用Glide更新ImageView contentDescription

Android 如何在小部件中使用Glide更新ImageView contentDescription,android,imageview,android-widget,android-glide,talkback,Android,Imageview,Android Widget,Android Glide,Talkback,我有一个用于主屏幕的Android小部件,其布局基本上是一个ImageView: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_ultraviolet_widget_layout&q

我有一个用于主屏幕的Android小部件,其布局基本上是一个
ImageView

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_ultraviolet_widget_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true"
    android:focusable="true"
    android:gravity="center">

    <ImageView
        android:id="@+id/iv_ultraviolet_widget_image"
        android:layout_width="@dimen/widget_size"
        android:layout_height="@dimen/widget_size"
        android:src="@drawable/ic_uvi_loading" />

</RelativeLayout>
我的问题是,如何在小部件的
ImageView
中更新
contentDescription
属性,并在每次更新和使用Glide时提供说明,以便我的小部件更易于访问,并且可以与对讲一起使用。我已经搜索过了,但还没有找到任何Glide和远程视图的示例

提前感谢,


Xavi

您可以在加载图像时将侦听器添加到Glide。因此,当加载映像成功时,将更新imageView的contentDescription

您可以在以下内容中阅读如何将侦听器添加到Gilde:

GlideApp.with(上下文)
.加载(“http://via.placeholder.com/300.png")
.placeholder(R.drawable.placeholder)
.错误(R.drawable.imagenotfound)
.listener(新的RequestListener(){
@凌驾
public boolean onload失败(@Nullable glide,对象模型,目标,boolean isFirstResource){
//日志异常
Log.e(“标签”,“错误加载图像”,e);
return false;//返回false以放置错误占位符很重要
}
@凌驾
公共布尔onResourceReady(可绘制资源、对象模型、目标、数据源数据源、布尔isFirstResource){
//加载图像成功,请在此处更新contentDescription
返回false;
}
})
.输入(ivImg);

感谢@Nguy的帮助ễn广泰ọ, 我找到了解决办法。首先,我在Kotlin中创建了一个数据类(元组),用于保存drawable及其关联字符串:

data class UltravioletImageContents(@DrawableRes val drawableId: Int, val contentDescription: String)
其次,我使用Glide result listener添加contentDescription更新,并将更改推送到我的
UpdateWidgetView
函数中的小部件

@JvmStatic
private fun updateWidgetViews(context: Context, appWidgetId: Int, ultravioletImageContents: UltravioletImageContents) {
    val widgetView = RemoteViews(context.packageName, R.layout.ultraviolet_widget)

    // Set an Intent to launch MainActivity when clicking on the widget
    val intent = Intent(context, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
    widgetView.setOnClickPendingIntent(R.id.rl_ultraviolet_widget_layout, pendingIntent)

    // Set image
    val appWidgetTarget = AppWidgetTarget(context, R.id.iv_ultraviolet_widget_image, widgetView, appWidgetId)
    Glide
        .with(context)
        .asBitmap() // This is needed because AppWidgetTarget is a Bitmap target. See: https://github.com/bumptech/glide/issues/2717#issuecomment-351791721
        .transition(BitmapTransitionOptions.withCrossFade())
        .load(ultravioletImageContents.drawableId)
        .listener(object : RequestListener<Bitmap> {
            override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, isFirstResource: Boolean): Boolean {
                Timber.e(e, "Drawable cannot be loaded and set in widget image view")
                return false // Important to return false so the error placeholder can be placed
            }

            override fun onResourceReady(resource: Bitmap?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                // Set contentDescription in order to enable accessibility and be usable with TalkBack
                widgetView.setContentDescription(R.id.iv_ultraviolet_widget_image, ultravioletImageContents.contentDescription)

                pushWidgetUpdate(context, appWidgetId, widgetView)

                return false
            }
        })
        .into(appWidgetTarget)
}
@JvmStatic
private fun UpdateWidgetView(上下文:context,appWidgetId:Int,ultravioletImageContents:ultravioletImageContents){
val widgetView=RemoteView(context.packageName、R.layout.u小部件)
//设置在单击小部件时启动MainActivity的意图
val intent=intent(上下文,MainActivity::class.java)
val pendingent=pendingent.getActivity(上下文,0,意图,0)
setOnClickPendingEvent(R.id.rl_紫外线_小部件_布局,PendingEvent)
//设置图像
val-appWidgetTarget=appWidgetTarget(上下文、R.id.iv\u紫外小部件\u图像、widgetView、appWidgetId)
滑翔
.与(上下文)
.asBitmap()//这是必需的,因为AppWidgetTarget是位图目标。请参阅:https://github.com/bumptech/glide/issues/2717#issuecomment-351791721
.transition(BitmapTransitionOptions.withCrossFade())
.load(ultravioletImageContents.drawableId)
.listener(对象:RequestListener{
重写fun onLoadFailed(e:GlideException?,型号:Any?,目标:com.bumptech.glide.request.target.target?,isFirstResource:Boolean):布尔{
Timber.e(e,“无法在窗口小部件图像视图中加载和设置可绘制文件”)
return false//返回false以便放置错误占位符很重要
}
覆盖onResourceReady(资源:位图?、模型:任意?、目标:com.bumptech.glide.request.target.target?、数据源:数据源?、isFirstResource:Boolean):布尔{
//设置contentDescription以启用可访问性并可用于对讲
setContentDescription(R.id.iv_紫外线_小部件_图像,ultravioletImageContents.contentDescription)
pushWidgetUpdate(上下文、appWidgetId、widgetView)
返回错误
}
})
.into(appWidgetTarget)
}
最后,我想指出,
pushWidgetUpdate
被移动到了
onResourceReady
中,因为我认为在没有图像的情况下更新我的小部件是没有意义的(但是,可能我遗漏了一些东西)

data class UltravioletImageContents(@DrawableRes val drawableId: Int, val contentDescription: String)
@JvmStatic
private fun updateWidgetViews(context: Context, appWidgetId: Int, ultravioletImageContents: UltravioletImageContents) {
    val widgetView = RemoteViews(context.packageName, R.layout.ultraviolet_widget)

    // Set an Intent to launch MainActivity when clicking on the widget
    val intent = Intent(context, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
    widgetView.setOnClickPendingIntent(R.id.rl_ultraviolet_widget_layout, pendingIntent)

    // Set image
    val appWidgetTarget = AppWidgetTarget(context, R.id.iv_ultraviolet_widget_image, widgetView, appWidgetId)
    Glide
        .with(context)
        .asBitmap() // This is needed because AppWidgetTarget is a Bitmap target. See: https://github.com/bumptech/glide/issues/2717#issuecomment-351791721
        .transition(BitmapTransitionOptions.withCrossFade())
        .load(ultravioletImageContents.drawableId)
        .listener(object : RequestListener<Bitmap> {
            override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, isFirstResource: Boolean): Boolean {
                Timber.e(e, "Drawable cannot be loaded and set in widget image view")
                return false // Important to return false so the error placeholder can be placed
            }

            override fun onResourceReady(resource: Bitmap?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                // Set contentDescription in order to enable accessibility and be usable with TalkBack
                widgetView.setContentDescription(R.id.iv_ultraviolet_widget_image, ultravioletImageContents.contentDescription)

                pushWidgetUpdate(context, appWidgetId, widgetView)

                return false
            }
        })
        .into(appWidgetTarget)
}