首页 > 解决方案 > UIStackView 灵活宽度和等宽项

问题描述

TL;博士

UIStackView我想用灵活宽度的项目替换自定义(不同于其他项目)宽度项目并将所有UIStackView项目居中。

更多信息:

我有一个UIStackView很少的习惯UIView's

self.handleButtonStack.axis = .horizontal
self.handleButtonStack.alignment = .center
self.handleButtonStack.distribution = .fillProportionally
self.handleButtonStack.spacing = 10.0
    
let hbVideo = HandleButton(image: "icon", title: "", type: .video, delegate: self)
hbVideo.widthAnchor.constraint(equalToConstant: 50).isActive = true

let hbInstagram = HandleButton(image: "icon", title: "", type: .instagram, delegate: self)
hbInstagram.widthAnchor.constraint(equalToConstant: 50).isActive = true

let hbWhatsApp = HandleButton(image: "icon", title: "", type: .whatsapp, delegate: self)
hbWhatsApp.widthAnchor.constraint(equalToConstant: 50).isActive = true

let hbHints = HandleButton(image: "icon", title: "title", type: .hint, delegate: self)
hbHints.widthAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true

self.handleButtonStack.addArrangedSubview(hbVideo)
self.handleButtonStack.addArrangedSubview(hbInstagram)
self.handleButtonStack.addArrangedSubview(hbWhatsApp)
self.handleButtonStack.addArrangedSubview(hbHints)

在用户执行某些操作后,我想更改UIStackView并删除hbHints按钮并使项目居中。

我这样做是这样的:

if let subviews = self.handleButtonStack.arrangedSubviews as? [HandleButton] {
    if let hintsButton = subviews.last {
        self.handleButtonStack.removeFully(view: hintsButton)
        let leadingSpacer = self.createSpacer(width: 50)
        let trailingSpacer = self.createSpacer(width: 50)
        self.handleButtonStack.insertArrangedSubview(leadingSpacer, at: 0)
        self.handleButtonStack.insertArrangedSubview(trailingSpacer, at: subviews.count)
    }
}

并添加这样的垫片:

func createSpacer(width: CGFloat) -> UIView {
    let space = UIView(frame: .zero)
    space.backgroundColor = .red
    space.translatesAutoresizingMaskIntoConstraints = false
    if width != 0 {
        space.widthAnchor.constraint(equalToConstant: width).isActive = true
    }
    return space
}

我的问题是约束因错误而中断,我不知道为什么。是否可以添加一个灵活的宽度作为我将其放置到位时伸展的垫片?

我已经尝试过的:

没有成功。

这是限制破坏日志:

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x283414050 H:[UIStackView:0x124599e30]-(0)-|   (active, names: '|':UIView:0x1245e9f20 )>",
    "<NSLayoutConstraint:0x2834142d0 H:|-(0)-[UIStackView:0x124599e30]   (active, names: '|':UIView:0x1245e9f20 )>",
    "<NSLayoutConstraint:0x283416e90 UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide'.trailing == UIView:0x1245e9f20.trailing + 40   (active)>",
    "<NSLayoutConstraint:0x283416620 UIView:0x1245e9f20.leading == UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide'.leading + 40   (active)>",
    "<NSLayoutConstraint:0x283428b90 MyApp.HandleButton:0x124589460.width == 50   (active)>",
    "<NSLayoutConstraint:0x283428af0 MyApp.HandleButton:0x124589e40.width == 50   (active)>",
    "<NSLayoutConstraint:0x283428a50 MyApp.HandleButton:0x124589610.width == 50   (active)>",
    "<NSLayoutConstraint:0x2834281e0 'UISV-canvas-connection' UIStackView:0x124599e30.leading == UIView:0x124576f20.leading   (active)>",
    "<NSLayoutConstraint:0x283428230 'UISV-canvas-connection' H:[UIView:0x1245897c0]-(0)-|   (active, names: '|':UIStackView:0x124599e30 )>",
    "<NSLayoutConstraint:0x2834282d0 'UISV-fill-proportionally' UIView:0x124576f20.width == 0   (active)>",
    "<NSLayoutConstraint:0x28342bc50 'UISV-fill-proportionally' UIView:0x1245897c0.width == 0   (active)>",
    "<NSLayoutConstraint:0x283428280 'UISV-spacing' H:[UIView:0x124576f20]-(10)-[MyApp.HandleButton:0x124589460]   (active)>",
    "<NSLayoutConstraint:0x28342acb0 'UISV-spacing' H:[MyApp.HandleButton:0x124589460]-(10)-[MyApp.HandleButton:0x124589e40]   (active)>",
    "<NSLayoutConstraint:0x28342af80 'UISV-spacing' H:[MyApp.HandleButton:0x124589e40]-(10)-[MyApp.HandleButton:0x124589610]   (active)>",
    "<NSLayoutConstraint:0x28342b2a0 'UISV-spacing' H:[MyApp.HandleButton:0x124589610]-(10)-[UIView:0x1245897c0]   (active)>",
    "<NSLayoutConstraint:0x283429810 'UIView-Encapsulated-Layout-Width' MyApp.AngleColorsView:0x124599fc0.width == 414   (active)>",
    "<NSLayoutConstraint:0x283415f90 'UIViewSafeAreaLayoutGuide-left' H:|-(0)-[UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide'](LTR)   (active, names: '|':MyApp.AngleColorsView:0x124599fc0 )>",
    "<NSLayoutConstraint:0x283416440 'UIViewSafeAreaLayoutGuide-right' H:[UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide']-(0)-|(LTR)   (active, names: '|':MyApp.AngleColorsView:0x124599fc0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x283428a50 MyApp.HandleButton:0x124589610.width == 50   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

标签: iosswiftuistackview

解决方案


在这里你不需要给出任何中心对齐。根据您的要求,您不需要我认为因为您为所有视图和最后一个视图提供约束,您还提供了更大的ThanOrEqual 约束,它会自动拉伸您的视图以填补空白。

因此,请尝试将对齐方式从 .center 更改为 .fill。

然后,在您删除最后一个视图后,您不必添加任何空格来填充缺失的字段。相反,您可以为堆栈视图本身提供约束。

对于堆栈视图的前导和尾随锚点,请给出更大的ThanOrEqualTo 约束而不是相等,并且还向堆栈视图添加中心对齐约束。

因此,当您现在删除视图时,堆栈视图会自动将视图安排在您需要的中心对齐位置。

希望这是您预期的最终结果。

GIF 中的预期输出


推荐阅读