在 iOS 堆栈视图中水平居中视图

Posted

技术标签:

【中文标题】在 iOS 堆栈视图中水平居中视图【英文标题】:Center views horizontally in iOS stack view 【发布时间】:2020-03-31 14:55:42 【问题描述】:

我正在尝试实现以下布局(视图水平居中):

所以我像这样设置了一个堆栈视图:

let quickPromptsView: UIStackView = 
    let sv = UIStackView()
    sv.axis = .horizontal
    sv.alignment = .center
    sv.distribution = .equalSpacing
    sv.spacing = 10
    sv.translatesAutoresizingMaskIntoConstraints = false
    return sv
()

向堆栈视图添加按钮:

func addOptions(options: [DialogNodeOutputOptionsElement]) 
    DispatchQueue.main.async 
        // clear all subviews
        self.quickPromptsView.subviews.forEach  (view) in
            view.removeFromSuperview()
        
        for option in options 
            let button = QuickPromptButton()
            button.setTitle(option.label, for: .normal)
            button.addTarget(self, action: #selector(self.didTapQuickPrompt), for: .touchUpInside)
            self.quickPromptsView.addArrangedSubview(button)
        
    

按钮类:

class QuickPromptButton: UIButton 

    var userFacingValue: String?
    var answerValue: String?

    override init(frame: CGRect) 
        super.init(frame: frame)
        layer.borderColor = UIColor.primaryColor.cgColor
        layer.borderWidth = 1
        layer.cornerRadius = 15
        setTitleColor(.primaryColor, for: .normal)
    

    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

这就是我添加堆栈视图的方式,我将它添加到 MessageKit 的另一个堆栈部分中

func configureQuickPromptsView() 
    view.addSubview(quickPromptsView)
    quickPromptsView.heightAnchor.constraint(equalToConstant: 40).isActive = true

    // this stack view belongs to the MessageKit library
    messageInputBar.topStackView.axis = .horizontal
    messageInputBar.topStackView.distribution = .fill
    messageInputBar.topStackView.addArrangedSubview(quickPromptsView)

但是,这就是我得到的:

堆栈视图具有 100% 的屏幕宽度。我已经尝试了每一种类型的distribution,但没有奏效。我还尝试在极端情况下插入透明的UIViews 以强制居中,但这似乎是一种技巧。有什么想法吗?

【问题讨论】:

约束 ?????????? @Sh_Khan 堆栈视图的工作是自动管理其排列的视图,而无需向子视图添加额外的约束。 我的意思是约束本身而不是子视图 @Sh_Khan 你会添加什么约束?在堆栈视图上水平居中? 您能否显示将两个文本气泡添加到堆栈视图的代码? 【参考方案1】:

只需在其父视图中水平居中堆栈视图即可。

以下示例使用UIKitPlus 库(它是纯 UIKit,但具有声明性并支持 LivePreview、ios9+)

UView 
    UHStack 
        UView 
            UText("Yes")
                .color(.green)
                .edgesToSuperview(h: 8, v: 4)
        
        .border(1, .green)
        .circle()
        UView 
            UText("No")
                .color(.red)
                .edgesToSuperview(h: 8, v: 4)
        
        .border(1, .red)
        .circle()
        UView 
            UText("I don't know")
                .color(.darkGray)
                .edgesToSuperview(h: 8, v: 4)
        
        .border(1, .darkGray)
        .circle()
    
    .alignment(.center)
    .distribution(.equalSpacing)
    .spacing(10)
    .edgesToSuperview(v: 0)
    .centerXInSuperview() // this will center your stack view

.edgesToSuperview(h: 0)
.centerYInSuperview()

或者通过添加两个宽度相等的视图来使用小技巧,一个在堆栈的开头,一个作为堆栈中的最后一个视图。

let v1 = UView()
UHStack 
    v1
    UView 
        UText("Yes")
            .color(.green)
            .edgesToSuperview(h: 8, v: 4)
    
    .border(1, .green)
    .circle()
    UView 
        UText("No")
            .color(.red)
            .edgesToSuperview(h: 8, v: 4)
    
    .border(1, .red)
    .circle()
    UView 
        UText("I don't know")
            .color(.darkGray)
            .edgesToSuperview(h: 8, v: 4)
    
    .border(1, .darkGray)
    .circle()
    UView().width(to: v1)

.alignment(.center)
.spacing(10)
.edgesToSuperview(h: 0)
.centerYInSuperview()

不幸的是,堆栈视图本身无法自动居中内部视图,因此您必须帮助它做到这一点。

【讨论】:

这个问题针对 uikit not swiftui 感谢您的回答。我不认为水平居中是一个选项,因为我使用的是内置在库(MessageKit)中的堆栈视图,并且不想触及那里的约束。使用两个视图作为 hack 听起来不错,但是,我不确定如何在没有第三方库的情况下在 UIKit 中执行此操作 @Cesare 等宽是原生的,只需将第一个视图的宽度约束设置为第二个视图的宽度即可。以编程方式,您可以使用 UIView 的widthAnchor 属性来设置它:) @Sh_Khan 这个答案是用纯 UIKit 编写的,并且从 iOS9 开始工作 我会接受并添加 - 如果您使用第三方库,例如 MessageKit,您可以将容器视图 UIView 添加到将包含 的预构建堆栈视图另一个 堆栈视图,但这次您决定约束(例如水平居中)。 (不确定这是否有意义,但你去)

以上是关于在 iOS 堆栈视图中水平居中视图的主要内容,如果未能解决你的问题,请参考以下文章

iOS:无法更改水平堆栈视图中的宽度

iOS9:在另一个以编程方式添加的视图中居中以编程方式添加的视图

滚动视图的水平居中内容

限制在超级视图中水平和垂直居中阻止我更改框架

如何水平居中滚动视图的内容?

在情节提要中将视图水平居中并垂直放置在底部