Search code examples
c#androidxamarinxamarin.formsxamarin.android

Drawable not appearing on Button Xamarin Forms Android


Xamarin.Forms - Android. I'm using a Button Renderer on the Android platform to add an image onto an Android.Widget.Button. The Image file is stored in an Assets folder and not the usual Drawable folder. I am setting the ImageSource of the button in XAML as normal and then in the renderer I am getting the image location and searching for it in the asset folder. The drawable is created correctly and confirmed by checking the width and height which match, etc. but it is just not showing on the button itself. The image file has build action of AndroidAsset but I've also tried AndroidResource and it still doesn't work.

FileImageSource fis = (FileImageSource)Element.ImageSource;
Stream stream = context.Assets.Open("images/" + fis.File);
Drawable d = Drawable.CreateFromStream(stream, null);
stream.Close();
Control.SetCompoundDrawablesWithIntrinsicBounds(null, d, null, null);

Solution

  • public class ButtonView : Button {
    
        public new static readonly BindableProperty ImageSourceProperty = BindableProperty.Create(nameof(ImageSource), typeof(string), typeof(ButtonView), null);
            public new string ImageSource {
                get { return (string)GetValue(ImageSourceProperty); }
                set { SetValue(ImageSourceProperty, value); }
            }
        }
    }
    

    Then on the renderer:

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) {
        base.OnElementPropertyChanged(sender, e);
        if(e.PropertyName == ButtonView.ImageSourceProperty.PropertyName) {
            SetImage();
        }
    }
    
    private void SetImage() {
        if (Element is ButtonView btn){
            Stream stream = context.Assets.Open("images/" + btn.ImageSource);
            Drawable d = Drawable.CreateFromStream(stream, null);
            stream.Close();
            Control.SetCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
        }
    }