0
votes

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

2 Answers

0
votes

You can create a custom renderer like following code.

[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(CustomButton.Droid.CustomButton))]
namespace CustomButton.Droid
{
   public class CustomButton:ButtonRenderer
    {
        Context mcontext;
        public CustomButton(Context context) : base(context)
        {
            mcontext = context;
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);

            AssetManager assets = mcontext.Assets;

            Stream input = assets.Open("main.png");

            var mydraw=Drawable.CreateFromStream(input, null);
            Control.Background = mydraw;
        }
    }
}

use it in xamarin forms.

   <StackLayout>
    <!-- Place new controls here -->
    <Label Text="Welcome to Xamarin.Forms!" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Button Text="Button"/>
</StackLayout>

Here is running screenshot.

enter image description here

Update

If I used Control.SetCompoundDrawablesWithIntrinsicBounds(null, mydraw, null, null); it could show the image above the text.

 protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);

            AssetManager assets = mcontext.Assets;

            Stream input = assets.Open("person.jpg");

            var mydraw = Drawable.CreateFromStream(input, null);
            Control.SetCompoundDrawablesWithIntrinsicBounds(null, mydraw, null, null);
        }

Here is running screenshot. enter image description here

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