I have an ImageView
whose resource ID should be calculated based on some logic in the view model. So, I'd like to do something like this:
< ImageView android:src="@{viewModel.icon}" />
@Bindable
public int getIcon() {
switch (foo) {
case BAR:
return R.drawable.bar;
...
}
}
However, this code does not work. android:src
is expecting a Drawable
instead of an int
. I am aware of setImageResource()
but I don't want to use it. I want to stick to the principle that "the view is a function of the view model", i.e. no side effects.
I have tried context.getResources().getDrawable(resourceId)
and it worked. But it's a little clumsy since I need to keep a context
around, either in the view model or as a global/static reference, although it looks like it's still within the realm of the model view paradigm.
Is anyone aware of an elegant solution? Thanks.
This might get solve your problem.
object BindingAdapters {
@BindingAdapter("android:src")
fun setSrcCompat(imageView: ImageView, resId: Int) {
imageView.setImageResource(resId)
}
}
In Android Data Binding, you cant directly bind an int
resource ID to android:src
attribute, as it expects a Drawable
. To overcome this, you can use a custom BindingAdapter
to convert the resource ID to a Drawable
before setting it to the ImageView
. Heres how you can do it:
First, create a custom binding adapter class. In your app module, create a class like this:
javaimport android.widget.ImageView;
import androidx.databinding.BindingAdapter;
import androidx.core.content.ContextCompat;
public class BindingAdapters {
@BindingAdapter("app:srcCompat")
public static void setImageResource(ImageView imageView, int resource) {
imageView.setImageResource(resource);
}
@BindingAdapter("app:srcCompat")
public static void setImageDrawable(ImageView imageView, int resource) {
imageView.setImageDrawable(ContextCompat.getDrawable(imageView.getContext(), resource));
}
}
Next, make sure to include this class in your layout XML. In your layout file, add the following attribute to the root layout:
xmlxmlns:app="http://schemas.android.com/apk/res-auto"
Now, you can use your custom binding adapter in the layout:
xml< ImageView
app:srcCompat="@{viewModel.icon}" />
With this setup, when you set viewModel.icon
to a resource ID, the custom binding adapter will convert it to a Drawable
using ContextCompat.getDrawable()
.
Remember to include the BindingAdapters
class in your module, and make sure your layout is set up for data binding.
This approach allows you to keep the logic in your view model while maintaining separation of concerns in the MVVM pattern.