水平 UIStackView 居中

horizontal UIStackView centering

我正在尝试通过水平 UIStack 视图实现以下目标:

将显示未知数量的复选框(最多 5 个)。我希望它们像下面这样居中和等间距(2 个单独的图像):

如果我只需要一个复选框,它就会居中。

这是我目前得到的:

我现在很清楚,堆栈视图的左侧和右侧固定了 2 个复选框,其余复选框根据要求进行分布和间隔。

我希望一切都从堆栈视图的中心分布。

这是显示堆栈视图配置的代码:

UIStackView firstFiveCheckboxesStackView = new UIStackView
{
     TranslatesAutoresizingMaskIntoConstraints = false,
     Axis = UILayoutConstraintAxis.Horizontal,
     Distribution = UIStackViewDistribution.EqualSpacing,
     Alignment = UIStackViewAlignment.Center,
     Spacing = 10
};

尝试使用 UIStackViewAlignment.Fill 并将所有复选框包装在 UIView 中。

对于第二行,您需要添加三个空视图以使项目与顶行对齐。

要获得您描述的布局,您需要做的不仅仅是设置分布 属性。

  • 假设您的 "checkbox" 视图具有固定宽度...
  • 将 Stack View 的分布设置为 .Fill
  • 添加一个 "spacer" 视图 in-between 每个 "checkbox" 视图
  • 在开头和结尾添加一个"spacer"视图
  • 将间隔视图的宽度设置为彼此相等

下面是 "spacer" 可见视图(青色背景)的外观:

背景清晰:

以及带有 5、4、3、2 和 1 个复选框的示例:

这是我用来获得这些结果的代码:

using Foundation;
using System;
using UIKit;

namespace MyTest
{
    public class CheckBoxView : UIView
    {
        public CheckBoxView()
        {
            Initialize();
        }
        public CheckBoxView(IntPtr handle) : base(handle)
        {
            Initialize();
        }

        void Initialize()
        {
            this.Layer.BorderColor = UIColor.Black.CGColor;
            this.Layer.BorderWidth = 1;
        }

        public override void LayoutSubviews()
        {
            base.LayoutSubviews();
            this.Layer.CornerRadius = Bounds.Width * (float)0.5;
        }

    }

    public partial class ViewController : UIViewController
    {
        public ViewController(IntPtr handle) : base(handle)
        {
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // change to .Cyan to see the spacers
            UIColor spacerColor = UIColor.Clear;

            UIStackView stacksView = new UIStackView
            {
                TranslatesAutoresizingMaskIntoConstraints = false,
                Axis = UILayoutConstraintAxis.Vertical,
                Distribution = UIStackViewDistribution.Fill,
                Alignment = UIStackViewAlignment.Fill,
                Spacing = 20
            };

            for (int j = 5; j > 0; j -= 3)
            {

                UIStackView stackView = new UIStackView
                {
                    TranslatesAutoresizingMaskIntoConstraints = false,
                    Axis = UILayoutConstraintAxis.Horizontal,
                    Distribution = UIStackViewDistribution.Fill,
                    Alignment = UIStackViewAlignment.Fill,
                    Spacing = 0
                };

                UIView spacerView;
                UIView prevSpacerView = null;
                for (int i = 0; i < j; i++)
                {
                    spacerView = new UIView();
                    spacerView.BackgroundColor = spacerColor;
                    var checkBox = new CheckBoxView();
                    stackView.AddArrangedSubview(spacerView);
                    stackView.AddArrangedSubview(checkBox);
                    checkBox.HeightAnchor.ConstraintEqualTo(40).Active = true;
                    checkBox.WidthAnchor.ConstraintEqualTo(checkBox.HeightAnchor).Active = true;
                    if (prevSpacerView != null)
                    {
                        spacerView.WidthAnchor.ConstraintEqualTo(prevSpacerView.WidthAnchor).Active = true;
                    }
                    prevSpacerView = spacerView;
                }
                spacerView = new UIView();
                spacerView.BackgroundColor = spacerColor;
                stackView.AddArrangedSubview(spacerView);
                spacerView.WidthAnchor.ConstraintEqualTo(prevSpacerView.WidthAnchor).Active = true;

                stacksView.AddArrangedSubview(stackView);
            }

            var sepView = new UIView();
            sepView.HeightAnchor.ConstraintEqualTo(60).Active = true;
            stacksView.AddArrangedSubview(sepView);

            for (int j = 5; j > 0; j--)
            {

                UIStackView stackView = new UIStackView
                {
                    TranslatesAutoresizingMaskIntoConstraints = false,
                    Axis = UILayoutConstraintAxis.Horizontal,
                    Distribution = UIStackViewDistribution.Fill,
                    Alignment = UIStackViewAlignment.Fill,
                    Spacing = 0
                };

                UIView spacerView;
                UIView prevSpacerView = null;
                for (int i = 0; i < j; i++)
                {
                    spacerView = new UIView();
                    spacerView.BackgroundColor = spacerColor;
                    var checkBox = new CheckBoxView();
                    stackView.AddArrangedSubview(spacerView);
                    stackView.AddArrangedSubview(checkBox);
                    checkBox.HeightAnchor.ConstraintEqualTo(40).Active = true;
                    checkBox.WidthAnchor.ConstraintEqualTo(checkBox.HeightAnchor).Active = true;
                    if (prevSpacerView != null)
                    {
                        spacerView.WidthAnchor.ConstraintEqualTo(prevSpacerView.WidthAnchor).Active = true;
                    }
                    prevSpacerView = spacerView;
                }
                spacerView = new UIView();
                spacerView.BackgroundColor = spacerColor;
                stackView.AddArrangedSubview(spacerView);
                spacerView.WidthAnchor.ConstraintEqualTo(prevSpacerView.WidthAnchor).Active = true;

                stacksView.AddArrangedSubview(stackView);
            }

            View.AddSubview(stacksView);
            var stackConstraints = new[]
            {
                stacksView.TopAnchor.ConstraintEqualTo(View.TopAnchor, constant: 100),
                stacksView.LeadingAnchor.ConstraintEqualTo(View.LeadingAnchor, constant: 40),
                stacksView.TrailingAnchor.ConstraintEqualTo(View.TrailingAnchor, constant: -40),
            };
            NSLayoutConstraint.ActivateConstraints(stackConstraints);

        }

        public override void DidReceiveMemoryWarning()
        {
            base.DidReceiveMemoryWarning();
        }
    }

}