如何使用 DataBinding 将图像资源设置为 ImageView

如何在 android 中使用数据绑定将图像资源放入 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" />

我想要一个图像,如果挂起为真,另一个图像,如果挂起为假。但它显示错误。我如何实现这个功能?

86220 次浏览

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);
}
}
}

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.

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" />

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}"/>

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.

<ImageView ...
app:svg="@{@drawable/ic_car_placeholder}" />

then

@BindingAdapter({"app:svg"})
public static void setImageViewResource(ImageView imageView, Drawable resource) {
imageView.setBackgroundDrawable(resource);
}

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

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

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
}