I'm trying to make a horizontal UIStackView with 2 images and a label:
- The first image ico_qol should be anchored to the left side of the view.
- The second image ico_edit should be anchored to the right side of the view.
- The label should be anchored in between the two images.
- The view should be sized to the height of the images which are the same. It should span the entire screen width.
What I'm trying to achieve is something like this (selected elements in blue):
Here is my code:
public partial class ViewController : UIViewController
{
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
UIStackView header = new UIStackView();
header.Axis = UILayoutConstraintAxis.Horizontal;
View.AddSubview(header);
//< color name = "healthy_green" >#409900</color>
var healthy_green = new UIColor(red: 0.25f, green: 0.60f, blue: 0.00f, alpha: 1.00f);
//< color name = "optimistic_orange" >#FF5F00</color>
var optimistic_orange = new UIColor(red: 1.00f, green: 0.37f, blue: 0.00f, alpha: 1.00f);
// Enable Auto Layout
header.TranslatesAutoresizingMaskIntoConstraints = false;
var ic_qol_image = UIImage.FromBundle("ic_qol");
ic_qol_image.ApplyTintColor(healthy_green);
var ic_qol = new UIImageView(ic_qol_image);
ic_qol.SizeToImage();
var qol_title = new UILabel { TranslatesAutoresizingMaskIntoConstraints = false, Text = @"Quality of Life" };
var ic_edit_image = UIImage.FromBundle("ic_edit");
ic_edit_image.ApplyTintColor(optimistic_orange);
var ic_edit = new UIImageView(ic_edit_image);
ic_edit.SizeToImage();
var qolHeaderViews = new UIView[] { ic_qol, qol_title, ic_edit };
header.AddSubviews(qolHeaderViews);
header.Anchor(top: View.SafeAreaLayoutGuide.TopAnchor, leading: View.LeadingAnchor, trailing: View.TrailingAnchor);
ic_qol.Anchor(top: header.TopAnchor, leading: header.LeadingAnchor);
ic_edit.Anchor(top: header.TopAnchor, trailing: header.TrailingAnchor);
qol_title.Anchor(top: View.SafeAreaLayoutGuide.TopAnchor, leading: ic_qol.RightAnchor, trailing: ic_edit.RightAnchor, padding: new UIEdgeInsets(0, 10, 0, 0)); <=== fails here.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
internal static class extensions
{
// https://stackoverflow.com/a/48601685/15186
internal static void SizeToImage(this UIImageView uIImageView)
{
//Grab loc
var xC = uIImageView.Center.X;
var yC = uIImageView.Center.Y;
//Size to fit
uIImageView.Frame = new CGRect(x: 0, y: 0, width: uIImageView.Image.Size.Width / 2, height: uIImageView.Image.Size.Height / 2);
//Move to loc
uIImageView.Center = new CGPoint(x: xC, y: yC);
}
internal static void FillParentView(this UIView uIView)
{
uIView.Anchor(top: uIView.Superview?.TopAnchor, leading: uIView.Superview?.LeadingAnchor, bottom: uIView.Superview?.BottomAnchor, trailing: uIView.Superview.TrailingAnchor);
}
internal static void AnchorSize(this UIView uIView, UIView to)
{
uIView.WidthAnchor.ConstraintEqualTo(to.WidthAnchor).Active = true;
uIView.HeightAnchor.ConstraintEqualTo(to.HeightAnchor).Active = true;
}
internal static void Anchor(this UIView uIView, NSLayoutYAxisAnchor top = null, NSLayoutXAxisAnchor leading = null, NSLayoutYAxisAnchor bottom = null, NSLayoutXAxisAnchor trailing = null, UIEdgeInsets padding = default, CGSize size= default)
{
uIView.TranslatesAutoresizingMaskIntoConstraints = false;
if (top != null)
{
uIView.TopAnchor.ConstraintEqualTo(top, padding.Top).Active = true;
}
if (leading != null)
{
uIView.LeadingAnchor.ConstraintEqualTo(leading, padding.Left).Active = true; <=== fails here.
}
if (bottom != null)
{
uIView.BottomAnchor.ConstraintEqualTo(bottom, -padding.Bottom).Active = true;
}
if (trailing != null)
{
uIView.TrailingAnchor.ConstraintEqualTo(trailing, -padding.Right).Active = true;
}
if ( size.Width != 0)
{
uIView.WidthAnchor.ConstraintEqualTo(size.Width).Active = true;
}
if ( size.Height != 0)
{
uIView.HeightAnchor.ConstraintEqualTo(size.Height).Active = true;
}
}
}
I'm trying to constraint the Leading anchor of the Label to the trailing anchor of the image but it fails with the following exception:
A constraint cannot be made between <NSLayoutXAxisAnchor:0x280bcb980 "UILabel:0x1015132a0'Quality of Life'.leading">' and '<NSLayoutXAxisAnchor:0x280bcb840 "UIImageView:0x101510ea0.right">' because their units are not compatible.
I understand that their units may be incompatible but how can I do that anyways? How to make the units compatible?
Credits: The extensions methods I'm using are originally created during this video tutorial. I ported them to c#.