UIStackView在代码中设置layoutMargins会破坏对齐方式。

问题描述 投票:0回答:1

我想在一个网站中为一些元素添加layoutMargins UIStackView 我在代码中创建.我试过在IB中做同样的事情,它工作得很完美,但当我添加了 layoutMargins 我设置 isLayoutMarginsRelativeArrangement = true 那么我的堆栈视图的对齐方式就会中断。

我的堆栈视图的代码如下。

@objc lazy var buttonsStackView: UIStackView = {
        let stack = UIStackView(arrangedSubviews: [doneButton, separatorView, giftButton])
        stack.layoutMargins = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4)
        stack.isLayoutMarginsRelativeArrangement = true
        stack.axis = .horizontal
        stack.frame = CGRect(x: 0, y: 0, width: 150, height: 44)
        stack.spacing = 4
        stack.distribution = .equalCentering
        stack.alignment = .center

        let bgView = UIView(frame: stack.bounds)
        stackViewBackground = bgView
        bgView.backgroundColor = ColorManager.shared.grayColor
        bgView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        stack.insertSubview(bgView, at: 0)

        separatorView.heightAnchor.constraint(equalTo: stack.heightAnchor, multiplier: 0.8).isActive = true

        return stack
    }()

SeparatorView只有一个1pt宽度的约束, 而两个按钮则没有约束,以保持它们的宽度。intrinsicContentSize.

以下是我的stackView在以下情况下的样子 isLayoutMarginsRelativeArrangementfalse:enter image description here

但很明显,左右边距是需要的,所以当设置 isLayoutMarginsRelativeArrangementtrue我的stackview的对齐方式发生了变化。enter image description here

不幸的是,我不能为这个特殊的视图使用IB,我需要从代码中初始化它。如果有任何关于如何解决这个问题的想法,我们将非常感激。谢谢你!我正在尝试添加layoutMargin。

ios swift uistackview
1个回答
0
投票

下面是一个将该视图变成自定义视图的例子,使用的是 separator 水平居中,按钮在每个 "边 "上居中。

protocol DoneGiftDelegate: class {
    func doneButtonTapped()
    func giftButtonTapped()
}

class DoneGiftView: UIView {

    weak var delegate: DoneGiftDelegate?

    let doneButton: UIButton = {
        let v = UIButton(type: .system)
        v.setTitle("Done", for: [])
        v.tintColor = .white
        return v
    }()

    let giftButton: UIButton = {
        let v = UIButton(type: .system)
        v.setImage(UIImage(systemName: "gift.fill"), for: [])
        v.tintColor = .white
        return v
    }()

    let separatorView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    func commonInit() -> Void {

        backgroundColor = .lightGray // ColorManager.shared.grayColor

        [doneButton, separatorView, giftButton].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            addSubview($0)
        }

        // width and height constraints: 150 x 44
        //  set Priority to 999 so it can be overriden by controller if desired
        let widthConstraint = widthAnchor.constraint(equalToConstant: 150.0)
        widthConstraint.priority = UILayoutPriority(rawValue: 999)
        let heightConstraint = heightAnchor.constraint(equalToConstant: 44.0)
        heightConstraint.priority = UILayoutPriority(rawValue: 999)

        NSLayoutConstraint.activate([

            // doneButton Leading to Leading
            doneButton.leadingAnchor.constraint(equalTo: leadingAnchor),
            // separator Leading to doneButton Trailing
            separatorView.leadingAnchor.constraint(equalTo: doneButton.trailingAnchor),
            // giftButton Leading to separator Trailing
            giftButton.leadingAnchor.constraint(equalTo: separatorView.trailingAnchor),
            // giftButton Trailing to Trailing
            giftButton.trailingAnchor.constraint(equalTo: trailingAnchor),

            // all centered vertically
            doneButton.centerYAnchor.constraint(equalTo: centerYAnchor),
            separatorView.centerYAnchor.constraint(equalTo: centerYAnchor),
            giftButton.centerYAnchor.constraint(equalTo: centerYAnchor),

            // doneButton Height = Height
            doneButton.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 1.0),
            // separator Height = 80% of Height
            separatorView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.8),
            // giftButton Height = Height
            giftButton.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 1.0),

            // separator Width = 1
            separatorView.widthAnchor.constraint(equalToConstant: 1.0),

            // doneButton Width = giftButton Width
            doneButton.widthAnchor.constraint(equalTo: giftButton.widthAnchor, multiplier: 1.0),

            // self Width and Height
            widthConstraint,
            heightConstraint,
        ])

        // add target actions for buttons
        doneButton.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
        giftButton.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)

    }

    @objc func buttonTapped(_ sender: UIButton) -> Void {
        if sender == doneButton {
            delegate?.doneButtonTapped()
        } else {
            delegate?.giftButtonTapped()
        }
    }

}

class DemoViewController: UIViewController, DoneGiftDelegate {

    let doneGiftView: DoneGiftView = DoneGiftView()

    let testView: UIView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        doneGiftView.translatesAutoresizingMaskIntoConstraints = false
        testView.translatesAutoresizingMaskIntoConstraints = false

        testView.addSubview(doneGiftView)
        view.addSubview(testView)

        // so we can see the view frame
        testView.backgroundColor = .cyan

        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            // testView Top: 100
            //  Leading / Trailing with 20-pts "padding"
            //  Height: 80
            testView.topAnchor.constraint(equalTo: g.topAnchor, constant: 100.0),
            testView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            testView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            testView.heightAnchor.constraint(equalToConstant: 80.0),

            // doneGiftView Trailing to testView Trailing
            doneGiftView.trailingAnchor.constraint(equalTo: testView.trailingAnchor),
            // doneGiftView centered vertically in testView
            doneGiftView.centerYAnchor.constraint(equalTo: testView.centerYAnchor),

        ])

        doneGiftView.delegate = self
    }

    func doneButtonTapped() {
        print("Done button tapped!")
        // do what we want when Done button tapped
    }
    func giftButtonTapped() {
        print("Gift button tapped")
        // do what we want when Gift button tapped
    }
}

结果示例:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.