Rnta kokoi
Rnta kokoi

Reputation: 51

Image with rounded corners

I am trying to get an image in the shape of rectangle with rounded Cornes. I have tried to use nugget fftransformations and frame. So far I am not getting the result I want. Using the nugget turns the image into square no matter what size I give to it. Using frame for some reason doesn't actually round the corners. enter image description here

<StackLayout VerticalOptions="CenterAndExpand">
<ffimageloading:CachedImage VerticalOptions="CenterAndExpand"
           WidthRequest="530" HeightRequest="334"  
            DownsampleToViewSize="true"
            Source = "http://loremflickr.com/530/334/nature?filename=simple.jpg">
           <ffimageloading:CachedImage.Transformations>
                <fftransformations:RoundedTransformation Radius="10"/>
            </ffimageloading:CachedImage.Transformations>
        </ffimageloading:CachedImage>
      <ffimageloading:CachedImage VerticalOptions="CenterAndExpand"
           WidthRequest="530" HeightRequest="334"  
            DownsampleToViewSize="true"
            Source = "http://loremflickr.com/530/334/nature?filename=simple.jpg">
           <ffimageloading:CachedImage.Transformations>
                <fftransformations:CornersTransformation CornersTransformType="AllRounded"/>
            </ffimageloading:CachedImage.Transformations>
        </ffimageloading:CachedImage>
      <Grid VerticalOptions="CenterAndExpand">
             <Frame Padding="0"  WidthRequest="530" HeightRequest="334"  
        HorizontalOptions="Center"
        VerticalOptions="Center" CornerRadius="20" >
                <Image  Source = "http://loremflickr.com/530/330/nature?filename=simple.jpg"  Aspect="AspectFill"  />
          </Frame>
      </Grid>
     </StackLayout>

Upvotes: 1

Views: 570

Answers (1)

Serg Tomcat
Serg Tomcat

Reputation: 933

Some time ago I needed corner effects on other controls. And it applies to image too. All you need is to create Effect:

 public class RoundCornersEffect : RoutingEffect
     {
          public RoundCornersEffect() : base($"MySuperApp.{nameof(RoundCornersEffect)}")
          {
          }

          public static readonly BindableProperty CornerRadiusProperty =
              BindableProperty.CreateAttached(
                  "CornerRadius",
                  typeof(int),
                  typeof(RoundCornersEffect),
                  0,
                  propertyChanged: OnCornerRadiusChanged);

          public static int GetCornerRadius(BindableObject view) =>
              (int)view.GetValue(CornerRadiusProperty);

          public static void SetCornerRadius(BindableObject view, int value) =>
              view.SetValue(CornerRadiusProperty, value);

          private static void OnCornerRadiusChanged(BindableObject bindable, object oldValue, object newValue)
          {
               if (!(bindable is View view))
                    return;

               var cornerRadius = (int)newValue;
               var effect = view.Effects.OfType<RoundCornersEffect>().FirstOrDefault();

               if (cornerRadius > 0 && effect == null)
                    view.Effects.Add(new RoundCornersEffect());

               if (cornerRadius == 0 && effect != null)
                    view.Effects.Remove(effect);
          }
     }

And implement it on both platforms:

IOS:

public class RoundCornersEffectIOS : PlatformEffect
     {
          protected override void OnAttached()
          {
               try
               {
                    PrepareContainer();
                    SetCornerRadius();
               }
               catch (Exception e)
               {
                    Debug.WriteLine(e);
               }
          }

          protected override void OnDetached()
          {
               try
               {
                    Container.Layer.CornerRadius = new nfloat(0);
               }
               catch (Exception e)
               {
                    Debug.WriteLine(e);
               }
          }

          protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
          {
               if (args.PropertyName == RoundCornersEffect.CornerRadiusProperty.PropertyName)
                    SetCornerRadius();
          }

          private void PrepareContainer()
          {
               Container.ClipsToBounds = true;
               Container.Layer.AllowsEdgeAntialiasing = true;
               Container.Layer.EdgeAntialiasingMask = CAEdgeAntialiasingMask.All;
          }

          private void SetCornerRadius()
          {
               var cornerRadius = RoundCornersEffect.GetCornerRadius(Element);
               Container.Layer.CornerRadius = new nfloat(cornerRadius);
          }
     }

Droid:

public class RoundCornersEffectDroid : PlatformEffect
     {
          private Android.Views.View View => Control ?? Container;

          protected override void OnAttached()
          {
               try
               {
                    PrepareContainer();
                    SetCornerRadius();
               }
               catch (Exception e)
               {
                    Debug.WriteLine(e);
               }
          }

          protected override void OnDetached()
          {
               try
               {
                    View.OutlineProvider = ViewOutlineProvider.Background;
               }
               catch (Exception e)
               {
                    Debug.WriteLine(e);
               }
          }

          protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
          {
               if (args.PropertyName == RoundCornersEffect.CornerRadiusProperty.PropertyName)
                    SetCornerRadius();
          }

          private void PrepareContainer()
          {
               View.ClipToOutline = true;
          }

          private void SetCornerRadius()
          {
               var cornerRadius = RoundCornersEffect.GetCornerRadius(Element) * GetDensity();
               View.OutlineProvider = new RoundedOutlineProvider(cornerRadius);
          }

          private static double GetDensity() =>
              DeviceDisplay.MainDisplayInfo.Density;

          private class RoundedOutlineProvider : ViewOutlineProvider
          {
               private readonly double _radius;

               public RoundedOutlineProvider(double radius)
               {
                    _radius = radius;
               }

               public override void GetOutline(Android.Views.View view, Outline outline)
               {
                    outline?.SetRoundRect(0, 0, view.Width, view.Height, (float)_radius);
               }
          }
     }

Then you can use it in control:

<Image Source="mylogo.png" VerticalOptions="Center" Aspect="AspectFit" myeffects:RoundCornersEffect.CornerRadius="5"/>

Upvotes: 1

Related Questions