Ios 在其父视图中正确居中UIView

Ios 在其父视图中正确居中UIView,ios,swift,Ios,Swift,我正在做一个槽UIView()。我已经创建了子类UIView(),一切都很好 现在我也在尝试使用autolayout来支持iPad 以下是我想要的: 我所取得的成就: public protocol GDTextSlotDelegate: class{ func onTextEntered(_ finalText: String) } @IBDesignable final public class GDTextSlot: UIView, UIKeyInput { publi

我正在做一个槽
UIView()
。我已经创建了子类
UIView()
,一切都很好

现在我也在尝试使用autolayout来支持iPad

以下是我想要的:

我所取得的成就:

public protocol GDTextSlotDelegate: class{
    func onTextEntered(_ finalText: String)
}

@IBDesignable
final public class GDTextSlot: UIView, UIKeyInput {
    public weak var delegate: GDTextSlotDelegate? = nil

  / ... /
}
@IBInspectable
public var numberOfSlots: Int = 4 {
    didSet{
        / .. /
    }
}

 @IBInspectable
public var baseWidth: CGFloat = 30.0 {
    didSet{
        / .. /
    }
}
还将生成一个新插槽:

/// Calculate X position of slot and make sure
/// the whole group is always in center of the view
private func calcX() -> CGFloat{
    return ((frame.width - (baseWidth * CGFloat(numberOfSlots))) / 2) + (CGFloat((currentSlot - 1)) * CGFloat(baseWidth))
}

private func calcFrame() -> CGRect{
    return CGRect(x: calcX(), y: 0, width: baseWidth, height: frame.height)
}

/// Initiate a new label for the slot!
private var label: UILabel{
    let lbl: UILabel = UILabel()
    lbl.frame = calcFrame()
    lbl.text = "_"
    lbl.textColor = UIColor.white
    lbl.font = UIFont.boldSystemFont(ofSize: 25)
    lbl.textAlignment = .center
    lbl.tag = currentSlot

    return lbl
}
最后一步:

public func generateSlots(){
    for index in 1...numberOfSlots{
        currentSlot = index
        addSubview(label)
    }
    currentSlot = 1
}
但是,在故事板上添加自动布局会使ipad上的视图变宽,这很好。但是插槽没有居中

这是我在iPad上的调试层次结构:


我非常感谢使用代码或自动布局的任何解决方案,谢谢为每个子视图设置第一组约束

每个子视图的秒更改对齐中心X倍增器


对于每个子视图,第一组约束的乘数应为0.25,第二组约束的乘数应为0.75,第三组约束的乘数应为1.25,第四组约束的乘数应为1.75

每个子视图的秒更改对齐中心X倍增器


第一个乘数应为0.25,第二个乘数应为0.75,第三个乘数应为1.25,第四个乘数应为1.75

当您对任意数量的对象进行相同排列时,请使用UIStackView。此屏幕截图显示了一个示例:

堆栈视图是具有中心对齐和填充均匀分布的水平堆栈视图。堆栈视图在其superview中有一个水平居中的约束(以及任意高度约束和顶部约束,两者在本例中都不相关)。这将导致其排列的子视图(插槽视图)的间距和大小相等,并且整个对象在堆栈视图的superview中居中

让我们分析一下我们是如何得到具体结果的

  • 插槽视图的高度由其高度约束确定

  • 插槽视图之间的间距由堆栈视图的间距设置确定

  • 因此,唯一需要指定的是插槽视图的宽度;这是由堆栈视图本身的宽度约束设置的。知道插槽视图的所需宽度后,只需将该宽度乘以插槽视图的数量,将堆栈视图间距乘以插槽视图数量的1,将这两个值相加,然后将堆栈视图宽度约束常量设置为该值


因此,无论superview的大小如何,插槽视图最终看起来都完全相同,并在其superview中水平居中。真正酷的部分是,我们可以增加或减少插槽视图的数量,这一切都可以继续完美地工作,因为堆栈视图完成了排列它们的所有工作。

当您对任意数量的对象进行相同的排列时,请使用UIStackView。此屏幕截图显示了一个示例:

堆栈视图是具有中心对齐和填充均匀分布的水平堆栈视图。堆栈视图在其superview中有一个水平居中的约束(以及任意高度约束和顶部约束,两者在本例中都不相关)。这将导致其排列的子视图(插槽视图)的间距和大小相等,并且整个对象在堆栈视图的superview中居中

让我们分析一下我们是如何得到具体结果的

  • 插槽视图的高度由其高度约束确定

  • 插槽视图之间的间距由堆栈视图的间距设置确定

  • 因此,唯一需要指定的是插槽视图的宽度;这是由堆栈视图本身的宽度约束设置的。知道插槽视图的所需宽度后,只需将该宽度乘以插槽视图的数量,将堆栈视图间距乘以插槽视图数量的1,将这两个值相加,然后将堆栈视图宽度约束常量设置为该值


因此,无论superview的大小如何,插槽视图最终看起来都完全相同,并在其superview中水平居中。真正酷的部分是,我们可以增加或减少插槽视图的数量,这一切都可以继续完美地工作,因为堆栈视图完成了排列它们的所有工作。

@carbon\u exister为故事板方法提供了一个很好的解决方案。用代码来做也很简单。在您的情况下,请使用
UIStackView

public func generateSlots(){ 
    //Stack View
    var stackView = UIStackView()

    stackView.axis = UILayoutConstraintAxis.horizontal
    stackView.distribution = UIStackViewDistributionEqualSpacing
    stackView.alignment = UIStackViewAlignmentCenter
    stackView.spacing = //spacing between each label
    for index in 1...numberOfSlots{
        currentSlot = index
        var slotLabel = UILabel()
        //customize your label here: don't need x and y
        //these are width and height constraints for each label
        view3.heightAnchor.constraint(equalToConstant: 20).isActive = true
        view3.widthAnchor.constraint(equalToConstant: baseHeight).isActive = true
        stackView.addArrangedSubview(label)
    }
    currentSlot = 1

    stackView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(stackView)
}

@Castan_exister为故事板方法提供了一个很好的解决方案。用代码来做也很简单。在您的情况下,请使用
UIStackView

public func generateSlots(){ 
    //Stack View
    var stackView = UIStackView()

    stackView.axis = UILayoutConstraintAxis.horizontal
    stackView.distribution = UIStackViewDistributionEqualSpacing
    stackView.alignment = UIStackViewAlignmentCenter
    stackView.spacing = //spacing between each label
    for index in 1...numberOfSlots{
        currentSlot = index
        var slotLabel = UILabel()
        //customize your label here: don't need x and y
        //these are width and height constraints for each label
        view3.heightAnchor.constraint(equalToConstant: 20).isActive = true
        view3.widthAnchor.constraint(equalToConstant: baseHeight).isActive = true
        stackView.addArrangedSubview(label)
    }
    currentSlot = 1

    stackView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(stackView)
}

您需要将水平视图中心设置为等于父视图中心,然后更改constraintWell的乘数,谢谢。我不会问我是否知道:我是新来的autolayout@RawandAhmad
frame
是父视图的框架吗?@RawandAhmad是否介意发布当前代码结果的图像(不是故事板)?@RawandAhmad检查我的答案,让我知道它是否适合您:)您需要将水平视图中心设置为等于父视图中心,然后更改constraintWell的乘数,谢谢。我不会问我是否知道:我是新来的autolayout@RawandAhmad
frame
是父视图的框架吗?@RawandAhmad是否介意发布当前代码结果的图像(不是故事板)?@RawandAhmad检查我的答案,并让我知道它是否适用于您:)非常感谢您的回答,我可以用代码来做吗?我真的不能用Storyboard来做。你可以用代码来做,但是代码太多,速度不快。在故事板中,我花了2分钟,没有code@RawandAhmad在代码中模仿图片应该不会太麻烦谢谢你的回答,我可以在代码中这样做吗?我真的不能用Storyboard来做。你可以用代码来做,但是代码太多,速度不快。在故事板中,我花了2分钟,没有code@RawandAhmad用代码模拟图片应该不会太麻烦