I'm trying to make a horizontal UIStackView with 2 images and a label:
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#.
You can achieve this layout easily with a "horizontal" stack view.
Note: I don't use xamarin / c#, so I'll just describe what you want to do.
header.AddArrangedSubview(ic_qol);
header.AddArrangedSubview(qol_title);
header.AddArrangedSubview(ic_edit);
View.AddSubview(header);
The last step will be to add constraints to put the stack view at the top, spanning the width of the view:
// Get the parent view's layout
var margins = View.LayoutMarginsGuide;
// Pin the top edge of the stackView to the margin
header.TopAnchor.ConstraintEqualTo (margins.TopAnchor).Active = true;
// Pin the leading edge of the stackView to the margin
header.LeadingAnchor.ConstraintEqualTo (margins.LeadingAnchor).Active = true;
// Pin the trailing edge of the stackView to the margin
header.TrailingAnchor.ConstraintEqualTo (margins.TrailingAnchor).Active = true;
The result should look about like this:
Each imageView is constrained to 40-pts width and height-equalTo-width. The label has a cyan background to make it easy to see the layout, and text alignment is center. The outlines are just there so we can see the stackView's frame.
and at runtime, without the frame outlines:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.