使用Android中的数据绑定在ImageView的android:src中设置可绘制资源ID

Yur*_*yuk 72 android android-layout android-databinding

我正在尝试使用数据绑定将drawable资源ID设置为ImageView的android:src

这是我的对象:

public class Recipe implements Parcelable {
    public final int imageResource; // resource ID (e.g. R.drawable.some_image)
    public final String title;
    // ...

    public Recipe(int imageResource, String title /* ... */) {
        this.imageResource = imageResource;
        this.title = title;
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

这是我的布局:

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

    <data>
        <variable
            name="recipe"
            type="com.example.android.fivewaystocookeggs.Recipe" />
    </data>

    <!-- ... -->

    <ImageView
        android:id="@+id/recipe_image_view"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:src="@{recipe.imageResource}" />

    <!-- ... -->

</layout>
Run Code Online (Sandbox Code Playgroud)

最后,活动类:

// ...

public class RecipeActivity extends AppCompatActivity {

    public static final String RECIPE_PARCELABLE = "recipe_parcelable";
    private Recipe mRecipe;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mRecipe = getIntent().getParcelableExtra(RECIPE_PARCELABLE);
        ActivityRecipeBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_recipe);
        binding.setRecipe(mRecipe);
    }

    // ...

}
Run Code Online (Sandbox Code Playgroud)

它根本不显示图像.我究竟做错了什么?

顺便说一句,它完全符合标准方式:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_recipe);

    final ImageView recipeImageView = (ImageView) findViewById(R.id.recipe_image_view);
    recipeImageView.setImageResource(mRecipe.imageResource);

}
Run Code Online (Sandbox Code Playgroud)

Joe*_*her 92

截至2016年11月10日的答复

下面的Splash评论强调,没有必要使用自定义属性类型(如imageResource),我们可以改为创建多个方法,android:src如下所示:

public class DataBindingAdapters {

    @BindingAdapter("android:src")
    public static void setImageUri(ImageView view, String imageUri) {
        if (imageUri == null) {
            view.setImageURI(null);
        } else {
            view.setImageURI(Uri.parse(imageUri));
        }
    }

    @BindingAdapter("android:src")
    public static void setImageUri(ImageView view, Uri imageUri) {
        view.setImageURI(imageUri);
    }

    @BindingAdapter("android:src")
    public static void setImageDrawable(ImageView view, Drawable drawable) {
        view.setImageDrawable(drawable);
    }

    @BindingAdapter("android:src")
    public static void setImageResource(ImageView imageView, int resource){
        imageView.setImageResource(resource);
    }
}
Run Code Online (Sandbox Code Playgroud)

老答案

您可以随时尝试使用适配器:

public class DataBindingAdapters {

    @BindingAdapter("imageResource")
    public static void setImageResource(ImageView imageView, int resource){
        imageView.setImageResource(resource);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以像这样在xml中使用适配器

<ImageView
    android:id="@+id/recipe_image_view"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="centerCrop"
    imageResource="@{recipe.imageResource}" />
Run Code Online (Sandbox Code Playgroud)

请务必注意xml中的名称与BindingAdapter注释(imageResource)匹配

DataBindingAdapters类不需要在任何地方声明,DataBinding机制无论如何都会找到它(我相信)

  • @YuriySeredyuk Nooooo!哈哈,拜托.这样做会覆盖整个应用程序**中xml中"android:src"的每一次使用,你绝对不会**想要这样做.要使imageResource工作,你必须改变imageView的xml,就像我上面所做的那样,数据绑定将找出放在那里的内容 (5认同)

hqz*_*zwb 66

根本不需要定制BindingAdapter。只需使用

app:imageResource="@{yourResId}"
Run Code Online (Sandbox Code Playgroud)

它会正常工作。

检查这个它是如何工作。

  • 这应该会得到更多的支持,因为这是 2020 年左右的一个很好的答案 (3认同)

qin*_*iao 22

限定:

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

使用:

<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}"/>
Run Code Online (Sandbox Code Playgroud)


Mah*_*raa 12

在创建自己的属性时,切勿覆盖标准SDK属性@BindingAdapter!

这不是一个很好的方法,原因如下:它会阻止在该属性上获得Android SDK更新的新修补程序的好处.此外,它可能会使开发人员感到困惑,并且对于可重用性肯定很棘手(因为它未被覆盖而无法被覆盖)

您可以使用不同的命名空间:

custom:src="@{recipe.imageResource}"
Run Code Online (Sandbox Code Playgroud)

要么

mybind:src="@{recipe.imageResource}"
Run Code Online (Sandbox Code Playgroud)

------开始更新2.Jul.2018

建议不要使用命名空间,因此最好依赖前缀或不同的名称:

app:custom_src="@{recipe.imageResource}"
Run Code Online (Sandbox Code Playgroud)

要么

app:customSrc="@{recipe.imageResource}"
Run Code Online (Sandbox Code Playgroud)

------结束更新2.Jul.2018

但是,我会建议不同的解决方案:

android:src="@{ContextCompat.getDrawable(context, recipe.imageResource)}"
Run Code Online (Sandbox Code Playgroud)

上下文视图始终在绑定表达式中可用 @{ ... }


Tom*_*dek 11

基于 Maher Abuthraa 的回答,这就是我最终在 XML 中使用的内容:

android:src="@{context.getDrawable(recipe.imageResource)}"
Run Code Online (Sandbox Code Playgroud)

context变量在没有任何导入的绑定表达式中使用。此外,不需要定制BindingAdapter。唯一警告:该方法getDrawable仅自 API 21 起可用。


Khe*_*raj 8

###你可以做的越多 DataBindingAdapter

###Set 任何这些类型:

android:src="@{model.profileImage}"

android:src="@{roundIcon ? @drawable/ic_launcher_round : @drawable/ic_launcher_round}"

android:src="@{bitmap}"

android:src="@{model.drawableId}"

android:src="@{@drawable/ic_launcher}"

android:src="@{file}"

android:src="@{`https://placekitten.com/200/200`}"
Run Code Online (Sandbox Code Playgroud)

对于 mipmap 资源

android:src="@{@mipmap/ic_launcher}" <!--This will show Token recognition error at '@mipmap -->


android:src="@{R.mipmap.ic_launcher}" <!-- correct with improt R class -->
Run Code Online (Sandbox Code Playgroud)

设置错误图像/占位符图像

placeholderImage="@{@drawable/img_placeholder}"
errorImage="@{@drawable/img_error}"


<ImageView
    placeholderImage="@{@drawable/ic_launcher}"
    errorImage="@{@drawable/ic_launcher}"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:src="@{`https://placekitten.com/2000/2000`}"
    />
Run Code Online (Sandbox Code Playgroud)

###测试了所有类型

标准委员会

因此,使用单个绑定适配器即可实现。只需复制此方法项目。

public class BindingAdapters {
    @BindingAdapter(value = {"android:src", "placeholderImage", "errorImage"}, requireAll = false)
    public static void loadImageWithGlide(ImageView imageView, Object obj, Object placeholder, Object errorImage) {
        RequestOptions options = new RequestOptions();
        if (placeholder instanceof Drawable) options.placeholder((Drawable) placeholder);
        if (placeholder instanceof Integer) options.placeholder((Integer) placeholder);

        if (errorImage instanceof Drawable) options.error((Drawable) errorImage);
        if (errorImage instanceof Integer) options.error((Integer) errorImage);

        RequestManager manager = Glide.with(App.getInstance()).
                applyDefaultRequestOptions(options);
        RequestBuilder<Drawable> builder;

        if (obj instanceof String) {
            builder = manager.load((String) obj);
        } else if (obj instanceof Uri)
            builder = manager.load((Uri) obj);
        else if (obj instanceof Drawable)
            builder = manager.load((Drawable) obj);
        else if (obj instanceof Bitmap)
            builder = manager.load((Bitmap) obj);
        else if (obj instanceof Integer)
            builder = manager.load((Integer) obj);
        else if (obj instanceof File)
            builder = manager.load((File) obj);
        else if (obj instanceof Byte[])
            builder = manager.load((Byte[]) obj);
        else builder = manager.load(obj);
        builder.into(imageView);
    }
}
Run Code Online (Sandbox Code Playgroud)

###Reason 我使用 Glide 加载所有对象

如果你问我为什么使用 Glide 来加载 drawable/resource id,我可以使用 imageView.setImageBitmap();or imageView.setImageResource();。所以原因是

  • Glide 是一个高效的图像加载框架,它包装了媒体解码、内存和磁盘缓存。所以你不必担心大尺寸的图像和缓存。
  • 在加载图像时保持一致性。现在所有类型的图像资源都由 Glide 加载。

如果您使用 Piccaso、Fresso 或任何其他图像加载库,您可以在loadImageWithGlidemethod 中进行更改


小智 7

根本不需要自定义 BindingAdapter。只需使用

数据

<data>
    <import type="com.example.R"/>
      :
</data>
Run Code Online (Sandbox Code Playgroud)

图片视图:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:imageResource="@{gender == 0 ? R.drawable.male : R.drawable.female}" />
Run Code Online (Sandbox Code Playgroud)


joe*_*cks 6

对于Kotlin,将其放置在顶层utils文件中,不需要静态/随播上下文:

@BindingAdapter("android:src")
fun setImageViewResource(view: ImageView, resId : Int) {
    view.setImageResource(resId)
}
Run Code Online (Sandbox Code Playgroud)