How to set image borders for making it resizable

2 minute read

Sometimes app developers want to set a resizable image as background to better fit the contents. However, if you resize the image as it is, you may not get the shape you want.

Tizen provides an API to set border, a region of the image to be resized by scale to keep the correct aspect ratio. The following figures provide a visual explanation.

How to set image borders

To create image borders, use the ElmSharp.Image.SetBorder() method after image loading.

For information about using native controls in Xamarin.Forms, see Xamarin.Forms Custom Renderers

Create custom renderer

public class CustomImage : Image
{
    public static readonly BindableProperty BorderLeftProperty = BindableProperty.Create("BorderLeft", typeof(int), typeof(CustomImage), default(int));
    public static readonly BindableProperty BorderRightProperty = BindableProperty.Create("BorderRight", typeof(int), typeof(CustomImage), default(int));
    public static readonly BindableProperty BorderTopProperty = BindableProperty.Create("BorderTop", typeof(int), typeof(CustomImage), default(int));
    public static readonly BindableProperty BorderBottomProperty = BindableProperty.Create("BorderBottom", typeof(int), typeof(CustomImage), default(int));

    public CustomImage()
    {
    }

    public int BorderLeft
    {
        get { return (int)GetValue(BorderLeftProperty); }
        set { SetValue(BorderLeftProperty, value); }
    }

    public int BorderRight
    {
        get { return (int)GetValue(BorderRightProperty); }
        set { SetValue(BorderRightProperty, value); }
    }

    public int BorderTop
    {
        get { return (int)GetValue(BorderTopProperty); }
        set { SetValue(BorderTopProperty, value); }
    }

    public int BorderBottom
    {
        get { return (int)GetValue(BorderBottomProperty); }
        set { SetValue(BorderBottomProperty, value); }
    }
}
[assembly: ExportRenderer(typeof(CustomImage), typeof(CustomImageRenderer))]
class CustomImageRenderer : ImageRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Image> e)
    {
        base.OnElementChanged(e);
        UpdateBorder();
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if ((e.PropertyName == CustomImage.BorderBottomProperty.PropertyName)
            || (e.PropertyName == CustomImage.BorderLeftProperty.PropertyName)
            || (e.PropertyName == CustomImage.BorderRightProperty.PropertyName)
            || (e.PropertyName == CustomImage.BorderTopProperty.PropertyName))
        {
            UpdateBorder();
        }
        base.OnElementPropertyChanged(sender, e);
    }

    void UpdateBorder()
    {
        var img = Element as CustomImage;
        Control.SetBorder(img.BorderLeft, img.BorderRight, img.BorderTop, img.BorderBottom);
    }

    protected override void UpdateAfterLoading()
    {
        base.UpdateAfterLoading();
        UpdateBorder(); // SetBorder should be called after image loading
    }
}

Note: Because ElmSharp.Image allows you to use the override UpdateAfterLoading() method for post processing, you can call the SetBorder() method after image loading.

Example

public class App : Application
{
    public App()
    {
        // The root page of your application
        MainPage = new ContentPage
        {
            BackgroundColor = Color.White,
            Content = new StackLayout
            {
                VerticalOptions = LayoutOptions.Center,
                Children = {
                    new CustomImage
                    {
                        Source = FileImageSource.FromFile("sample.png"),
                        HorizontalOptions = LayoutOptions.Center,
                        VerticalOptions = LayoutOptions.Center,
                        WidthRequest = 300,
                        HeightRequest = 100,
                        Aspect = Aspect.Fill,
                        BorderLeft = 50,
                        BorderRight = 50,
                        BorderTop = 50,
                        BorderBottom = 50
                    }
                }

            }
        };
    }
}


The sample application with original image (100x100).


The sample application with resized image (300x100).
You can check the image is resized, keeping the borders.

Categories:

Updated: