如何使用 AutoLayout 制作均匀分布的图像行? [复制]

Posted

技术标签:

【中文标题】如何使用 AutoLayout 制作均匀分布的图像行? [复制]【英文标题】:How to make an evenly spaced row of images with AutoLayout? [duplicate] 【发布时间】:2016-06-10 00:32:28 【问题描述】:

我刚刚开始在 Swift 中开发这款纸牌游戏,我试图弄清楚如何在屏幕顶部附近水平放置一排 6 张纸牌。

我尝试将 6 个 imageViews 放在一个堆栈中,但我的手动约束最终导致最后一个图像拉伸到边缘:

有人可以告诉我如何设置一行 imageView 以使它们中的每一个都具有固定的宽度并且它们都居中吗?我是 AutoLayout 的新手,所以截图会很有帮助。

【问题讨论】:

尝试在每张图片和它旁边的图片之间设置等宽约束,看起来你的其余约束可能是正确的。 将左约束添加到第一个约束,尾随约束添加到最后一个约束,它们之间的水平间距,然后添加宽度约束,使它们的宽度都与第一个相同。此外,如果您愿意,UIStackView 是另一种很好地分隔一堆视图的方法。 【参考方案1】:

我建议使用 UIStackView。看看下面的 Ray Wenderlich 教程:

https://www.raywenderlich.com/114552/uistackview-tutorial-introducing-stack-views

但是,在进入更复杂的视图(例如前面提到的堆栈视图)之前;你应该学会使用自动布局以避免犯任何愚蠢的错误。

这是来自同一站点的另一个很棒的教程:

https://www.raywenderlich.com/115440/auto-layout-tutorial-in-ios-9-part-1-getting-started-2

编辑:

改进的答案:

UIStackView 允许您轻松地将元素排列成一行或一列。这可以为您节省大量时间,并使您的故事板看起来更简洁,因为需要的约束更少。

developer.apple.com上UIStackView的描述:

UIStackView 类提供了一个简化的界面,用于在列或行中布置视图集合。堆栈视图让您可以利用自动布局的强大功能,创建可以动态适应设备方向、屏幕尺寸和可用空间变化的用户界面。堆栈视图管理其排列子视图属性中所有视图的布局。这些视图沿堆栈视图的轴排列,基于它们在排列子视图数组中的顺序。确切的布局取决于堆栈视图的轴、分布、对齐方式、间距和其他属性。

UIStackViews 功能不会停留在简化的视图对齐方式上。实际上,您还可以更改定义堆栈视图的属性。

axis 属性决定堆栈的方向,要么 垂直或水平。

distribution 属性决定了排列视图的布局 沿堆栈的轴。

alignment 属性决定了排列视图的布局 垂直于堆栈的轴。

spacing 属性决定排列之间的最小间距 意见。

baselineRelativeArrangement 属性确定是否 视图之间的垂直间距是从基线开始测量的。

layoutMarginsRelativeArrangement 属性确定是否 堆栈视图相对于其布局边距布局其排列的视图。

尽管有上面提到的优点,UIStackView 也有局限性。

UIStackView 是 UIView 的非渲染子类;也就是说,它确实 不提供任何自己的用户界面。相反,它只是管理 其排列视图的位置和大小。结果,一些 属性(如 backgroundColor)对堆栈视图没有影响。 同样,您不能覆盖 layerClass、drawRect: 或 drawLayer:inContext:.

注意 UIStackView 不能滚动。如果您需要它滚动,请在 UIScrollView 中嵌入堆栈视图。

希望这会有所帮助!

【讨论】:

关于为什么UIStackView 适合此用例的更多详细信息(而不仅仅是可能停止工作并导致此答案无用的链接)会改善此答案,但总体而言你是对的;这是UIStackView 的绝佳用例 刚刚在答案中添加了一些元素,感谢您的观察!【参考方案2】:

我推荐纯编码,你了解更多。

如果您指定所有卡片的宽度和高度相同,则会确保最后一张卡片不会被拉伸。

这就是我经常构建 UI 的方式:

import UIKit

class ViewController: UIViewController 

    var container:UIView = UIView();
    var card1:UIView! = nil;
    var card2:UIView! = nil;
    var card3:UIView! = nil;
    var card4:UIView! = nil;
    var card5:UIView! = nil;
    var card6:UIView! = nil;

    override func viewDidLoad() 
        super.viewDidLoad()

        self.initViews();
        self.initConstraints();
    

    func cardView() -> UIView
    
        let card = UIView();
        card.backgroundColor = UIColor.orangeColor();
        return card;
    

    func initViews()
    
        self.card1 = self.cardView();
        self.card2 = self.cardView();
        self.card3 = self.cardView();
        self.card4 = self.cardView();
        self.card5 = self.cardView();
        self.card6 = self.cardView();

        self.container.addSubview(self.card1);
        self.container.addSubview(self.card2);
        self.container.addSubview(self.card3);
        self.container.addSubview(self.card4);
        self.container.addSubview(self.card5);
        self.container.addSubview(self.card6);

        self.view.addSubview(self.container);
    

    func initConstraints()
    
        self.container.translatesAutoresizingMaskIntoConstraints = false;
        self.card1.translatesAutoresizingMaskIntoConstraints = false;
        self.card2.translatesAutoresizingMaskIntoConstraints = false;
        self.card3.translatesAutoresizingMaskIntoConstraints = false;
        self.card4.translatesAutoresizingMaskIntoConstraints = false;
        self.card5.translatesAutoresizingMaskIntoConstraints = false;
        self.card6.translatesAutoresizingMaskIntoConstraints = false;

        var views = [String: AnyObject]();
        views["container"] = self.container;
        views["card1"] = self.card1;
        views["card2"] = self.card2;
        views["card3"] = self.card3;
        views["card4"] = self.card4;
        views["card5"] = self.card5;
        views["card6"] = self.card6;

        self.view.addConstraint(NSLayoutConstraint(item: self.container, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 0.0));

        self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[container]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));

        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[card1(60)]-10-[card2(==card1)]-10-[card3(==card1)]-10-[card4(==card1)]-10-[card5(==card1)]-10-[card6(==card1)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));

        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[card1(100)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[card2(==card1)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[card3(==card1)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[card4(==card1)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[card5(==card1)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[card6(==card1)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views));
    

你最终会得到这样的结果:

【讨论】:

又一个没有解释的懦夫投反对票。

以上是关于如何使用 AutoLayout 制作均匀分布的图像行? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用弹性框均匀分布图像和子元素?

使用css网格均匀分布的图像

如何将图像彼此对齐,以使它们沿页面宽度均匀分布? [关闭]

如何使用情节提要约束将两个 UIPickerView 并排均匀分布?

在 iOS 6 中使用 Auto Layout 在 superview 中均匀分布相同大小的 UIView

如何在训练、验证、测试样本中选择几乎均匀分布的类?