繁体   English   中英

如何在 UILabel 和两个 UIImageView 之间设置约束?

[英]How to put a constraint between a UILabel and two UIImageView?

我正在尝试使用 2 个图像和一个标签制作一个水平的 UIStackView:

  1. 第一个图像ico_qol应该锚定在视图的左侧。
  2. 第二个图像ico_edit应该锚定在视图的右侧。
  3. 标签应锚定在两个图像之间。
  4. 视图的大小应与相同图像的高度一致。 它应该跨越整个屏幕宽度。

我想要实现的是这样的(蓝色的选定元素):

在此处输入图片说明

这是我的代码:

   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;
            }
        }
    }

我试图将标签的前导锚点约束到图像的尾随锚点,但由于以下异常而失败:

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.

我知道他们的单位可能不兼容,但无论如何我该怎么做? 如何使单位兼容?

致谢:我使用的扩展方法最初是在本视频教程中创建的。 我将它们移植到 c#。

您可以使用“水平”堆栈视图轻松实现此布局。

注意:我不使用 xamarin/c#,所以我只会描述你想要做什么。

  • 创建堆栈视图
  • 将其属性设置为
    • 轴:水平
    • 分布:填充
    • 对齐方式:居中(这是子视图的垂直对齐方式)
    • 间距:8(您可能希望子视图之间有一点空间)
  • 创建 2 个图像视图
    • 将图像加载到每个图像视图中
    • 根据需要在图像视图上设置宽度和高度约束(看起来您使用的是图像高度和宽度的 1/2?)
  • 创建标签
  • 将图像视图和标签作为排列的子视图添加到堆栈视图
    • header.AddArrangedSubview(ic_qol);
    • header.AddArrangedSubview(qol_title);
    • header.AddArrangedSubview(ic_edit);
  • 将堆栈视图添加到视图中
    • View.AddSubview(header);

最后一步是添加约束以将堆栈视图放在顶部,跨越视图的宽度:

// 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;

结果应该是这样的:

在此处输入图片说明

每个 imageView 被限制为 40 pts 宽度和高度等于宽度。 标签有青色背景,便于查看布局,文字居中对齐。 轮廓就在那里,所以我们可以看到 stackView 的框架。

在运行时,没有框架轮廓:

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM