如何使用数据绑定将图像资源设置为ImageView?

99

我们如何在安卓中使用数据绑定将图片资源放置在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" />

如果pending为真,我希望显示一张图片;如果pending为假,我希望显示另一张图片。但是出现错误了。我该如何实现这个功能?


我在这里提供了一个好的解决方案。https://dev59.com/7lsV5IYBdhLWcg3wwxOX#52983092 - Khemraj Sharma
9个回答

103

我尝试过这个方法,对我有效(buildToolsVersion: 24.0.1):

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

只需使用 app:imageResource 替换 android:srcandroid:src="@{item.avatarResId}" 无效,否则需要为其定义自定义的 @BindAdapter("android:src")

但是使用 app:imageResource 不需要额外定义 @BindAdapter,因为 ImageView 已经有一个叫做 setImageResource() 的方法。当您使用 app:imageResource 时,它将自动调用 setImageResource() 方法。


谢谢,它起作用了。我只是将 android:src 替换为 app:imageResource - Waldmann
谢谢 @Spark.Bao,你救了我 :D 它有效了。 - aida
如果您找不到 app:imageResource,请尝试使用 app:loadImageResource - Hawklike
1
请记得在xml中添加<data><import type="your.package.R"/></data> - Zhou Hongbo

73

答案:这里

定义:

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

使用:

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

59

像这样设置图片:

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

我在RecyclerView适配器中使用了它,每个项目都有5个ImageView,这导致性能显着降低。因为对于每个onBindViewHolder调用,数据绑定都会检查if语句。现在我更喜欢这个答案:https://dev59.com/ylsW5IYBdhLWcg3wwZjG#37675475 - Mohammad Reza Khahani
这对我不起作用。 - Konstantin Konopko

18

如果您想像使用 @IdRes 一样将参数传递到方法中,您可以使用

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>

代码

@BindingAdapter("load_image")
public static void loadImage(ImageView view, @IdRes int imageId) {
    //Logic
}

我不情愿地最终遵循了这个答案。我希望有一种方法可以使用@+id/blah语法,这样我就不需要在单独的文件中定义一个新的<item name="blah" type="id" />资源元素...哎呀呀呀 - Eric

15

如果您的数据模型包含图像的资源ID,则可以在不进行任何编程的情况下完成此操作。

例如:

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

只需将以下代码行添加到您的imageView中(当我尝试添加它时,我无法格式化代码):

只需要将以下代码行添加到您的imageView中(当我添加它时,我无法对其进行格式化):

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

其中 resId 包含 R.drawable.your_image_name


1
这对我来说完美地运作了。即使使用了Lisa Wray的Groupie数据绑定库也是如此。 - Patty P
工作得很顺利,就像我预期的那样。 - Padma Kumar

5

@piotrek1543,我正在尝试使用Picasso在RecyclerView中的一个项目中使用databainding加载imageView。显然,当我向上或向下滚动时,即使它们在一分钟前已经加载过了,图像也会重新加载。https://github.com/pankajnimgade/Tutorial101/tree/master/app/src/main/java/data/binding/list/activities/three - Pankaj Nimgade
这是一篇不错的文章,但是如果你正在从外部服务器获取数据来填充imageUrl,那么在数据到达时,loadImage(ImageView view, String imageUrl) 已经被调用了 --- 这里似乎没有双向绑定? - Mike6679

1

更多细节请参见详情 使用数据绑定和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);
    }
}
}

0
问题出在于所有没有相同名称的setter属性。例如,如果视图中没有setX()方法,则android:x将无法工作;同样地,如果ImageView上有setSrc()方法,您的代码将可以在没有自定义绑定适配器的情况下工作。

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

那么

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接