Skip to content

Instantly share code, notes, and snippets.

@andreinitescu
Created April 28, 2015 09:06
Show Gist options
  • Save andreinitescu/c907c2951a719ed3ac34 to your computer and use it in GitHub Desktop.
Save andreinitescu/c907c2951a719ed3ac34 to your computer and use it in GitHub Desktop.
public class ImageEx : Image
{
public static readonly BindableProperty AspectExProperty =
BindableProperty.Create<ImageEx, AspectEx>(p => p.AspectEx, AspectEx.AspectFit, BindingMode.OneWay, null, OnAspectExPropertyChanged);
static void OnAspectExPropertyChanged(BindableObject bindable, AspectEx oldValue, AspectEx newValue)
{
var aspectEx = (AspectEx)newValue;
Aspect aspect;
if (Enum.TryParse (aspectEx.ToString (), out aspect)) {
(bindable as ImageEx).Aspect = aspect;
}
}
public AspectEx AspectEx
{
get { return (AspectEx)base.GetValue(AspectExProperty); }
set { base.SetValue(AspectExProperty, value); }
}
protected override SizeRequest OnSizeRequest(Double widthConstraint, Double heightConstraint)
{
// the returned sizeRequest contains the dimensions of the image
SizeRequest sizeRequest = base.OnSizeRequest(double.PositiveInfinity, double.PositiveInfinity);
switch (AspectEx) {
case AspectEx.Uniform:
var innerAspectRatio = sizeRequest.Request.Width / sizeRequest.Request.Height;
if (Double.IsInfinity (heightConstraint)) {
if (Double.IsInfinity (widthConstraint)) {
// both destination constraints are infinity
// use the view's size request dimensions
widthConstraint = sizeRequest.Request.Width;
heightConstraint = sizeRequest.Request.Height;
} else {
// destination height constraint is infinity
heightConstraint = widthConstraint * sizeRequest.Request.Height / sizeRequest.Request.Width;
}
} else if (Double.IsInfinity (widthConstraint)) {
// destination width constraint is infity
widthConstraint = heightConstraint * sizeRequest.Request.Width / sizeRequest.Request.Height;
} else {
// both of the destination width and height constraints are non-infinity
var outerAspectRatio = widthConstraint / heightConstraint;
var resizeFactor = (innerAspectRatio >= outerAspectRatio) ?
(widthConstraint / sizeRequest.Request.Width) :
(heightConstraint / sizeRequest.Request.Height);
widthConstraint = sizeRequest.Request.Width * resizeFactor;
heightConstraint = sizeRequest.Request.Height * resizeFactor;
}
sizeRequest = new SizeRequest (new Size (widthConstraint, heightConstraint));
break;
case AspectEx.None:
sizeRequest = new SizeRequest (new Size (sizeRequest.Request.Width / 2, sizeRequest.Request.Height / 2));
break;
}
return sizeRequest;
}
}
public enum AspectEx
{
/// <summary>Scale the image to fit the view. Some parts may be left empty (letter boxing).</summary>
AspectFit,
/// <summary>Scale the image to fill the view. Some parts may be clipped in order to fill the view.</summary>
/// <remarks />
AspectFill,
/// <summary>Scale the image so it exactly fill the view. Scaling may not be uniform in X and Y.</summary>
Fill,
/// <summary>Scale the image to fill the view while it preserves its native aspect ratio.</summary>
Uniform,
/// <summary>The image preserves its original size.</summary>
None
}
@kosta59
Copy link

kosta59 commented May 3, 2017

Hello im getting an error for ios

System.ArgumentException: NaN is not a valid value for height
on line

sizeRequest = new SizeRequest(new Size(widthConstraint, heightConstraint));

any ideas

@jaybaldwin
Copy link

I'm getting NaN for height also. The issue is the code attempts to calculate a ratio based on the image ... width / height. Problem is, when I ran it, height is 0, so it tries to divide some number by 0, which results in either Infinity in some languages, or NaN in iOS. Either option is bad, so it is what it is.

I added this below the var innerAspectRatio = ... line and it works:
if (double.IsNaN(innerAspectRatio)) return sizeRequest;

@marcdieters
Copy link

Thank you for this, it's working great after a lot of obsolete tags are included. Can you update the code so these obsolete tags can be removed ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment