97

How can we use data binding in android to put image resource in an ImageView?

  <ImageView
            android:id="@+id/is_synced"
            android:src="@{model.pending ? @mipmap/pending: @mipmap/synced}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

I want an image if pending is true and another image if pending is false. But it's showing error.How can I achieve this functionality?

George Thomas
  • 4,566
  • 5
  • 30
  • 65

9 Answers9

99

I tried this, and it works for me (buildToolsVersion: 24.0.1):

<ImageView
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_margin="8dp"
    android:scaleType="centerInside"
    app:imageResource="@{item.avatarResId}"/>

just use app:imageResource to replace android:src, android:src="@{item.avatarResId}" doesn't works else define a custom @BindAdapter("android:src") for it.

but use app:imageResource doesn't need define a @BindAdapter additionally, because the ImageView has a method called setImageResource(), when you use app:imageResource, it will call setImageResource() automatically.

Spark.Bao
  • 5,573
  • 2
  • 31
  • 36
73

The answer:

define:

@BindingAdapter({"android:src"})
public static void setImageViewResource(ImageView imageView, int resource) {
    imageView.setImageResource(resource);
}

use:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:scaleType="center"
    android:src="@{viewModel.imageRes, default=@drawable/guide_1}"/>
JJD
  • 50,076
  • 60
  • 203
  • 339
qinmiao
  • 5,559
  • 5
  • 36
  • 39
59

set image like this,

  <ImageView
        android:layout_width="28dp"
        android:layout_height="28dp"
        android:src="@{model.isActive ? @drawable/white_activated_icon :@drawable/activated_icon}"
        tools:src="@mipmap/white_activated_icon" />
Faysal Ahmed
  • 7,501
  • 5
  • 28
  • 50
luttu android
  • 1,443
  • 16
  • 22
18

If you would like to pass an argument into the method like an @IdRes you can use

XML:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="<package_name>.R" />
    </data>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        app:load_image="@{R.drawable.image}" />
</layout>

Code

@BindingAdapter("load_image")
public static void loadImage(ImageView view, @IdRes int imageId) {
    //Logic
}
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
  • I reluctantly ended up following this answer. I wish there was a way to use the `@+id/blah` syntax so that I didn't need to define a new `` resource element in a separate file... alasssssss – Eric Mar 05 '23 at 22:45
15

You can do this without doing anything programmatically if your data model contains the resource ID of the image.

Example:

<layout>

<data>
<import type="android.support.v4.content.ContextCompat" />            
<variable
name="roomInfoItem"
type="com.example......model.RoomInfoModel" /> </data>

<RelativeLayout> 

 <ImageView
    android:id="@+id/iv_room_info_item"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
 />

</RelativeLayout>

</layout>

Just add the following line to your imageView (I wasn't able to format the code when I was adding it there):

android:src="@{ContextCompat.getDrawable(context,roomInfoItem.resId)}"

where resId contains R.drawable.your_image_name

Derlin
  • 9,572
  • 2
  • 32
  • 53
Rohan Taneja
  • 9,687
  • 3
  • 36
  • 48
5

Accorrding to this great article: Loading images with Data Binding and Picasso

there are two ways to do it:

  1. Using @BindingAdapter
  2. ObservableField & custom Picasso Target

In Android Developers reference Data Binding Guide, you would find only the first one.

Please read both articles.

More informations:

Hope it help.

piotrek1543
  • 19,130
  • 7
  • 81
  • 94
  • @piotrek1543, I am trying to load imageView using picasso in an item inside recyclerView using databainding, apparently when I scroll the up and down the images load again even if they were loaded a minute again, https://github.com/pankajnimgade/Tutorial101/tree/master/app/src/main/java/data/binding/list/activities/three – Pankaj Nimgade May 11 '16 at 05:10
  • good article but , if you are getting data from an external server to populate the imageUrl, by the time the data arrives loadImage(ImageView view, String imageUrl) is already called --- seems there is no 2 way binding here? – Mike6679 Jan 31 '17 at 04:01
1

More details Refer here Details Loading images with data binding and Picasso

public class ProfileViewModel {
// The URL will usually come from a model (i.e Profile)
static final String IMAGE_URL = "http://cdn.meme.am/instances/60677654.jpg";
public ObservableField<Drawable> profileImage;
private BindableFieldTarget bindableFieldTarget;

public ProfileViewModel(Context context) {
    profileImage = new ObservableField<>();
    // Picasso keeps a weak reference to the target so it needs to be stored in a field
    bindableFieldTarget = new BindableFieldTarget(profileImage, context.getResources());
    Picasso.with(context)
            .load(IMAGE_URL)
            .placeholder(R.drawable.placeholder)
            .into(bindableFieldTarget);
}

public class BindableFieldTarget implements Target {

    private ObservableField<Drawable> observableField;
    private Resources resources;

    public BindableFieldTarget(ObservableField<Drawable> observableField, Resources resources) {
        this.observableField = observableField;
        this.resources = resources;
    }

    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        observableField.set(new BitmapDrawable(resources, bitmap));
    }

    @Override
    public void onBitmapFailed(Drawable errorDrawable) {
        observableField.set(errorDrawable);
    }

    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable) {
        observableField.set(placeHolderDrawable);
    }
}
}
sasikumar
  • 12,540
  • 3
  • 28
  • 48
0

The problem is with all the attributes which do on have setters with same name. e.g. android:x wont work if setX() method is not there in that view likewise if we had setSrc() method on ImageView your code would have worked without custom binding adapter

Amit Kaushik
  • 642
  • 7
  • 13
-1
<ImageView ...
        app:svg="@{@drawable/ic_car_placeholder}" />

then

@BindingAdapter({"app:svg"})
public static void setImageViewResource(ImageView imageView, Drawable resource) {
    imageView.setBackgroundDrawable(resource);
}
StepanM
  • 4,222
  • 1
  • 21
  • 25