Set drawable resource ID in android:src for ImageView using data binding in Android

后端 未结 15 2016
陌清茗
陌清茗 2020-12-04 09:27

I\'m trying to set drawable resource ID to android:src of ImageView using data binding

Here is my object:

public class Recipe implem         


        
15条回答
  •  情歌与酒
    2020-12-04 10:21

    I am not an expert in Android but I spent hours trying to decipher the existing solutions. The good thing is that I grasped the whole idea of data binding using BindingAdapter a bit better. For that, I am at least thankful for the existing answers (although heavily incomplete). Here a complete breakdown of the approach:

    I will also use the BindingAdapter in this example. Preparing the xml:

    
    
        
            
        
    
        
    
        
    
        
    
    

    So here I am keeping only the important stuff:

    • SomeViewModel is my ViewModel I use for data binding. You can also use a class that extends BaseObservable and use @Bindable. However, the BindingAdapter in this example, doesn't have to be in a ViewModel or BaseObservable class! A plain class will do! This will be illustrated later.
    • app:appIconDrawable="@{model.packageName}". Yes... this was really causing me headaches! Let's break it down:
      • app:appIconDrawable: This can be anything: app:iCanBeAnything! Really. You can also keep "android:src"! However, take a note on your choice, we will use it later!
      • "@{model.packageName}": If you worked with data binding, this is familiar. I'll show how this is used later.

    Let's assume we use this simple Observable class:

    public class SomeViewModel extends BaseObservable {
       private String packageName; // this is what @{model.packageName}
                                   // access via the getPackageName() !!!
                                   // Of course this needs to be set at some
                                   // point in your program, before it makes
                                   // sense to use it in the BindingAdapter.
    
       @Bindable
       public String getPackageName() {
           return packageName;
       }
    
       public void setPackageName(String packageName) {
           this.packageName = packageName;
           notifyPropertyChanged(BR.packageName);
       }
    
       // The "appIconDrawable" is what we defined above! 
       // Remember, they have to align!! As we said, we can choose whatever "app:WHATEVER".
       // The BindingAdapter and the xml need to be aligned, that's it! :)
       //
       // The name of the function, i.e. setImageViewDrawable, can also be 
       // whatever we want! Doesn't matter.
       @BindingAdapter({"appIconDrawable"})
       public static void setImageViewDrawable(ImageView imageView, String packageName) {
           imageView.setImageDrawable(Tools.getAppIconDrawable(imageView.getContext(), packageName));
       }
    }
    

    As promised, you can also move the public static void setImageViewDrawable(), to some other class, e.g. maybe you can have a class that has a collection of BindingAdapters:

    public class BindingAdapterCollection {
       @BindingAdapter({"appIconDrawable"})
       public static void setImageViewDrawable(ImageView imageView, String packageName) {
           imageView.setImageDrawable(Tools.getAppIconDrawable(imageView.getContext(), packageName));
       }
    }
    

    Another important remark is that in my Observable class I used String packageName to pass extra info to the setImageViewDrawable. You can also choose for example int resourceId, with the corresponding getters/setters, for which the adapter becomes:

    public class SomeViewModel extends BaseObservable {
       private String packageName; // this is what @{model.packageName}
                                   // access via the getPackageName() !!!
       private int resourceId;     // if you use this, don't forget to update
                                   // your xml with: @{model.resourceId}
    
       @Bindable
       public String getPackageName() {
           return packageName;
       }
    
       public void setPackageName(String packageName) {
           this.packageName = packageName;
           notifyPropertyChanged(BR.packageName);
       }
    
       @Bindable
       public int getResourceId() {
           return packageName;
       }
    
       public void setResourceId(int resourceId) {
           this.resourceId = resourceId;
           notifyPropertyChanged(BR.resourceId);
       }
    
       // For this you use: app:appIconDrawable="@{model.packageName}" (passes String)
       @BindingAdapter({"appIconDrawable"})
       public static void setImageViewDrawable(ImageView imageView, String packageName) {
           imageView.setImageDrawable(Tools.getAppIconDrawable(imageView.getContext(), packageName));
       }
    
       // for this you use: app:appIconResourceId="@{model.resourceId}" (passes int)
       @BindingAdapter({"appIconResourceId"})
       public static void setImageViewResourceId(ImageView imageView, int resource) {
           imageView.setImageResource(resource);
       }
    }
    

提交回复
热议问题