Skip to content

Instantly share code, notes, and snippets.

@ilyaqznetsow
Last active July 26, 2019 08:44
Show Gist options
  • Save ilyaqznetsow/51922fae06dfc9a24cb342abbdd2dcbf to your computer and use it in GitHub Desktop.
Save ilyaqznetsow/51922fae06dfc9a24cb342abbdd2dcbf to your computer and use it in GitHub Desktop.
Xamarin iOS Fluent Layout Extensions
public partial class FirstViewSample : MvxViewController
{
public FirstViewSample() : base("FirstView", null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
#region init
var relativeSizeView = new UIView {
BackgroundColor = UIColor.Orange
}.EnableAutoLayout();
var relativePositionView = new UIView {
BackgroundColor = UIColor.Purple.ColorWithAlpha(0.3f)
}
.EnableAutoLayout();
#endregion
#region add
View.AddSubview(relativeSizeView);
View.AddSubview(relativePositionView);
#endregion
#region constraints
relativeSizeView
.WithRelativeSize(View, 0.5f, 0.5f)
.WithSameBottom(View)
.WithSameLeading(View);
relativePositionView
.ToRightOf(relativeSizeView)
.WithRelativeSize(View, 0.5f, 0.5f);
#endregion
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
/// <summary>
/// Fluent auto layout extensions.
/// original: https://github.com/jzeferino/Xamarin.iOS.FluentAutoLayoutExtensions
/// </summary>
public static partial class FluentLayoutExtensions
{
private const float DefaultMargin = 0;
private const float DefaultMultiplier = 1;
/// <summary>
/// Constraint with the same Top as <paramref name="anchorView"/> taking in account LayoutMarginsGuide.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameSafeTopSafeArea(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.TopAnchor.ConstraintEqualTo(anchorView.LayoutMarginsGuide.TopAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
public static TView Assign<TView, TAssignView>(this TView view, out TAssignView variable)
where TView : UIView, TAssignView
{
variable = view;
return view;
}
/// <summary>
/// Constraint with the same Bottom as <paramref name="anchorView"/> taking in account LayoutMarginsGuide.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameBottomSafeArea(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.BottomAnchor.ConstraintEqualTo(anchorView.LayoutMarginsGuide.BottomAnchor).Minus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint with the same Top as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameTop(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.TopAnchor.ConstraintEqualTo(anchorView.TopAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint with the same Bottom as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameBottom(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.BottomAnchor.ConstraintEqualTo(anchorView.BottomAnchor).Minus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint with the same Leading as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameLeading(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.LeadingAnchor.ConstraintEqualTo(anchorView.LeadingAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint with the same Trailing as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameTrailing(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.TrailingAnchor.ConstraintEqualTo(anchorView.TrailingAnchor).Minus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint Below <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Previous.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView Below(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.TopAnchor.ConstraintEqualTo(anchorView.BottomAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint Above <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView Above(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.BottomAnchor.ConstraintEqualTo(anchorView.TopAnchor).Minus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint to Right Of <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView ToRightOf(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.LeadingAnchor.ConstraintEqualTo(anchorView.TrailingAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint to Left Of <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView ToLeftOf(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.TrailingAnchor.ConstraintEqualTo(anchorView.LeadingAnchor).Minus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Center in X of <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameCenterX(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.CenterXAnchor.ConstraintEqualTo(anchorView.CenterXAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Center in Y of <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
/// <param name="priority">Priority.</param>
public static UIView WithSameCenterY(this UIView view, UIView anchorView, nfloat? margin = null, float? priority = null)
{
view.CenterYAnchor.ConstraintEqualTo(anchorView.CenterYAnchor).Plus(margin.GetValueOrDefault(DefaultMargin)).Priority(priority).Active();
return view;
}
/// <summary>
/// Set With with specified value.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="width">Width.</param>
/// <param name="priority">Priority.</param>
public static UIView WithWidth(this UIView view, nfloat width, float? priority = null)
{
view.WidthAnchor.ConstraintEqualTo(width).Priority(priority).Active();
return view;
}
/// <summary>
/// Set Height with specified value.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="height">Height.</param>
/// <param name="priority">Priority.</param>
public static UIView WithHeight(this UIView view, nfloat height, float? priority = null)
{
view.HeightAnchor.ConstraintEqualTo(height).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint to the same With as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The constraints.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
public static UIView WithSameWidth(this UIView view, UIView anchorView, nfloat? margin = null)
{
var marginValue = margin.GetValueOrDefault(DefaultMargin);
view.WithSameLeading(anchorView, marginValue).
WithSameTrailing(anchorView, marginValue);
return view;
}
/// <summary>
/// Constraint to the same Height as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The constraints.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
public static UIView WithSameHeight(this UIView view, UIView anchorView, nfloat? margin = null)
{
var marginValue = margin.GetValueOrDefault(DefaultMargin);
view.WithSameTop(anchorView, marginValue).
WithSameBottom(anchorView, marginValue);
return view;
}
/// <summary>
/// Constraint to a Width relative to <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="multiplier">Multiplier.</param>
/// <param name="priority">Priority.</param>
public static TView WithRelativeWidth<TView>(this TView view, UIView anchorView, nfloat? multiplier = null, float? priority = null) where TView : UIView
{
view.WidthAnchor.ConstraintEqualTo(anchorView.WidthAnchor, multiplier.GetValueOrDefault(DefaultMultiplier)).Priority(priority).Active();
return view;
}
public static TView WithRelativeSize<TView>(this TView view, UIView anchorView, nfloat? widthMultiplier = null, nfloat? heightMultiplier = null, float? priority = null) where TView : UIView
{
return view.WithRelativeWidth(anchorView, widthMultiplier, priority)
.WithRelativeHeight(anchorView, heightMultiplier, priority);
}
/// <summary>
/// Constraint to a Height relative to <paramref name="anchorView"/>.
/// </summary>
/// <returns>The view.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="multiplier">Multiplier.</param>
/// <param name="priority">Priority.</param>
public static TView WithRelativeHeight<TView>(this TView view, UIView anchorView, nfloat? multiplier = null, float? priority = null) where TView : UIView
{
view.HeightAnchor.ConstraintEqualTo(anchorView.HeightAnchor, multiplier.GetValueOrDefault(DefaultMultiplier)).Priority(priority).Active();
return view;
}
/// <summary>
/// Constraint to the same size as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The constraints.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margin">Margin.</param>
public static UIView FullSizeOf(this UIView view, UIView anchorView, nfloat margin) =>
FullSizeOf(view, anchorView, new Margins((float)margin));
/// <summary>
/// Constraint to the same size as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The constraints.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="top">Top.</param>
/// <param name="left">Left.</param>
/// <param name="bottom">Bottom.</param>
/// <param name="right">Right.</param>
public static UIView FullSizeOf(this UIView view, UIView anchorView, nfloat? top = null, nfloat? left = null, nfloat? bottom = null, nfloat? right = null) =>
FullSizeOf(view, anchorView, new Margins((float)top.GetValueOrDefault(DefaultMargin), (float)left.GetValueOrDefault(DefaultMargin),
(float)bottom.GetValueOrDefault(DefaultMargin), (float)right.GetValueOrDefault(DefaultMargin)));
/// <summary>
/// Constraint to the same size as <paramref name="anchorView"/>.
/// </summary>
/// <returns>The constraints.</returns>
/// <param name="view">View.</param>
/// <param name="anchorView">Anchor view.</param>
/// <param name="margins">Margins.</param>
private static UIView FullSizeOf(this UIView view, UIView anchorView, Margins margins)
{
margins = margins ?? new Margins();
return view.WithSameTop(anchorView, margins.Top)
.WithSameBottom(anchorView, margins.Bottom)
.WithSameLeading(anchorView, margins.Left)
.WithSameTrailing(anchorView, margins.Right);
}
/// <summary>
/// Constraint with the specified Width and Height.
/// </summary>
/// <returns>The constraints.</returns>
/// <param name="view">View.</param>
/// <param name="width">Width.</param>
/// <param name="height">Height.</param>
public static UIView WithSize(this UIView view, float width, float height)
{
return view.WithWidth(width)
.WithHeight(height);
}
/// <summary>
/// Enables auto layout.
/// </summary>
/// <returns>The view.</returns>
/// <param name="origin">Origin.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static T EnableAutoLayout<T>(this T origin) where T : UIView
{
origin.TranslatesAutoresizingMaskIntoConstraints = false;
return origin;
}
/// <summary>
/// Add the specified <paramref name="constant"/> to a constraint.
/// </summary>
/// <returns>The constraint.</returns>
/// <param name="constraint">Constraint.</param>
/// <param name="constant">Constant.</param>
public static NSLayoutConstraint Plus(this NSLayoutConstraint constraint, nfloat constant)
{
constraint.Constant += constant;
return constraint;
}
/// <summary>
/// Removes the specified <paramref name="constant"/> to a constraint.
/// </summary>
/// <returns>The constraint.</returns>
/// <param name="constraint">Constraint.</param>
/// <param name="constant">Constant.</param>
public static NSLayoutConstraint Minus(this NSLayoutConstraint constraint, nfloat constant)
{
constraint.Constant -= constant;
return constraint;
}
/// <summary>
/// Set the specified <paramref name="priority"/> to a constraint.
/// </summary>
/// <returns>The constraint.</returns>
/// <param name="constraint">Constraint.</param>
/// <param name="priority">Priority.</param>
public static NSLayoutConstraint Priority(this NSLayoutConstraint constraint, float? priority = null)
{
if (priority.HasValue) {
constraint.Priority = priority.Value;
}
return constraint;
}
/// <summary>
/// Active a constraint.
/// </summary>
/// <returns>The constraint.</returns>
/// <param name="constraint">Constraint.</param>
/// <param name="active">If set to <c>true</c> active.</param>
public static NSLayoutConstraint Active(this NSLayoutConstraint constraint, bool active = true)
{
constraint.Active = active;
return constraint;
}
/// <summary>
/// Sets the content hugging priority.
/// </summary>
/// <param name="view">View.</param>
/// <param name="priority">Priority.</param>
/// <param name="axis">Axis.</param>
public static void SetContentHuggingPriority(this UIView view, UILayoutPriority priority, UILayoutConstraintAxis axis)
{
view.SetContentHuggingPriority((float)priority, axis);
}
/// <summary>
/// Sets the content compression resistance priority.
/// </summary>
/// <param name="view">View.</param>
/// <param name="priority">Priority.</param>
/// <param name="axis">Axis.</param>
public static void SetContentCompressionResistancePriority(this UIView view, UILayoutPriority priority, UILayoutConstraintAxis axis)
{
view.SetContentCompressionResistancePriority((float)priority, axis);
}
}
public class Margins
{
/// <summary>
/// Gets or sets the top margin.
/// </summary>
/// <value>The top.</value>
public float Top { get; set; }
/// <summary>
/// Gets or sets the bottom margin.
/// </summary>
/// <value>The bottom.</value>
public float Bottom { get; set; }
/// <summary>
/// Gets or sets the left margin.
/// </summary>
/// <value>The left.</value>
public float Left { get; set; }
/// <summary>
/// Gets or sets the right margin.
/// </summary>
/// <value>The right.</value>
public float Right { get; set; }
/// <summary>
/// Initializes a new instance of the
/// <see cref="T:Xamarin.iOS.FluentAutoLayoutExtensions.FluentAutoLayoutExtensions.Margins"/> class.
/// </summary>
public Margins()
{
}
/// <summary>
/// Initializes a new instance of the
/// <see cref="T:Xamarin.iOS.FluentAutoLayoutExtensions.FluentAutoLayoutExtensions.Margins"/> class.
/// </summary>
/// <param name="all">All.</param>
public Margins(float all)
{
Top = all;
Bottom = all;
Right = all;
Left = all;
}
/// <summary>
/// Initializes a new instance of the
/// <see cref="T:Xamarin.iOS.FluentAutoLayoutExtensions.FluentAutoLayoutExtensions.Margins"/> class.
/// </summary>
/// <param name="top">Top margin.</param>
/// <param name="left">Left margin.</param>
/// <param name="bottom">Bottom margin.</param>
/// <param name="right">Right margin.</param>
public Margins(float top, float left, float bottom, float right)
{
Top = top;
Bottom = bottom;
Right = right;
Left = left;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment