androidimageviewandroid-widgetandroid-glidetalkback

How to update ImageView contentDescription with Glide in a Widget


I have an Android widget for the home screen, whose layout is basically an 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>

The ImageView will be updated over the time with the "current" value, which is represented with an image (a drawable) using this code:

/**
* Updates ultraviolet index widget view.
*/
@JvmStatic
private fun updateWidgetViews(context: Context, appWidgetId: Int, @DrawableRes drawableId: Int) {
    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)

    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(drawableId)
        .into(appWidgetTarget)

    pushWidgetUpdate(context, appWidgetId, widgetView)
}

/**
* Pushes update for a given widget.
*/
@JvmStatic
fun pushWidgetUpdate(context: Context, appWidgetId: Int, remoteViews: RemoteViews) {
    val manager = AppWidgetManager.getInstance(context)
    // Remember to check always for null in platform types (types ended in !).
    // See: https://stackoverflow.com/a/43826700/5189200
    manager?.let {
        manager.updateAppWidget(appWidgetId, remoteViews)
        Timber.d("Widget %d was updated", appWidgetId)
    }
}

My question is how to also update the contentDescription property in the widget's ImageView with a description on every update and using Glide, so that my widget is more accessible and it can be used with TalkBack. I have searched, but I haven't found any example with Glide and a remote view.

Thanks in advance,

Xavi


Solution

  • You can add listener to Glide when load an image. So, when load image success, you update the contentDescription of imageView.

    You can read how to add listener to Gilde in this: https://github.com/codepath/android_guides/wiki/Displaying-Images-with-the-Glide-Library#loading-errors

    GlideApp.with(context)
        .load("http://via.placeholder.com/300.png")
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.imagenotfound)
        .listener(new RequestListener<Drawable>() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                // log exception
                Log.e("TAG", "Error loading image", e);
                return false; // important to return false so the error placeholder can be placed
            }
    
            @Override
            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                // load image success, update the contentDescription here
                return false;
            }
        })
        .into(ivImg);