【问题标题】:iOS UIButtons in StackView aren't being tappedStackView 中的 iOS UIButtons 没有被点击
【发布时间】:2020-07-23 22:44:55
【问题描述】:

我在 ButtonView 类中有按钮,用于添加一些背景和标签。这些ButtonViews 被添加到UIStackView,这是PlayOverlay 类中的一个视图。 PlayOverlay 充当不同类型叠加层的父类,在这个例子中我只包含了BeginOverlay

BeginOverlayPlaySecVC 提供。 BeginOverlay 中的按钮由于某种原因无法点击。我已经尝试过 XCode 中的 UIDebugging 来查看它们前面是否有任何视图,而没有。它们是最前面的视图。当 UIDebugging 告诉我ButtonView 的宽度、高度以及 x 和 y 不明确时,我确实遇到了一个错误。这是因为我对它没有任何限制,如下所示,因为它们被布置在堆栈视图中。如何使这些按钮可点击?

视图控制器:

import UIKit

fileprivate struct scvc {
    static let overlayWidth: CGFloat = 330
    static let overlayFromCenter: CGFloat = 25
    static let hotspotSize: CGFloat = 30
    static let detailHeight: CGFloat = 214
    static let detailWidth: CGFloat = 500
    static let arrowMargin: CGFloat = 9
    static let arrowSize: CGFloat = 56
    static let zoomRect: CGFloat = 200
    static let overlayHeight: CGFloat = 267
}

enum playState {
    case play
    case shuffle
    case favorites
}

protocol PlaySec: class {
}

class PlaySecVC: UIViewController, PlaySec {

    // MARK: UIComponents
    lazy var scrollView: UIScrollView = {
        let _scrollView = UIScrollView(frame: .zero)
        _scrollView.translatesAutoresizingMaskIntoConstraints = false
        _scrollView.clipsToBounds = false
        //_scrollView.isUserInteractionEnabled = true

        return _scrollView
    }()

    lazy var imageView: UIImageView = {
        let _imageView = UIImageView(frame: .zero)
        _imageView.translatesAutoresizingMaskIntoConstraints = false
        _imageView.contentMode = .scaleAspectFit
        //_imageView.isUserInteractionEnabled = true

        return _imageView
    }()

    lazy var beginOverlay: BeginOverlay = {
        let _beginOverlay = BeginOverlay(frame: .zero)
        _beginOverlay.translatesAutoresizingMaskIntoConstraints = false

        return _beginOverlay
    }()

    lazy var detailView: UIView = {
        let _detailView = UIView(frame: .zero)
        _detailView.translatesAutoresizingMaskIntoConstraints = false
        _detailView.isHidden = true
        //_detailView.isUserInteractionEnabled = false

        return _detailView
    }()

    lazy var leftArrow: UIButton = {
        let _leftArrow = UIButton(frame: .zero)
        _leftArrow.translatesAutoresizingMaskIntoConstraints = false
        _leftArrow.isHidden = false
        _leftArrow.setImage(#imageLiteral(resourceName: "Left-Arrow-Outline"), for: .normal)

        return _leftArrow
    }()

    lazy var rightArrow: UIButton = {
        let _rightArrow = UIButton(frame: .zero)
        _rightArrow.translatesAutoresizingMaskIntoConstraints = false
        _rightArrow.isHidden = false
        _rightArrow.setImage(#imageLiteral(resourceName: "Right-Arrow-Outline"), for: .normal)

        return _rightArrow
    }()

    var state: playState = .play

    // MARK: Setup

    private func setup() {
        let viewController = self
    }

    private func setupConstraints() {
        view.addSubview(scrollView)
        scrollView.addSubview(imageView)
        view.addSubview(detailView)
        view.addSubview(beginOverlay)
        view.addSubview(leftArrow)
        view.addSubview(rightArrow)

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            imageView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            imageView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),

            beginOverlay.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            beginOverlay.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -25),
            beginOverlay.widthAnchor.constraint(equalToConstant: scvc.overlayWidth),
            beginOverlay.heightAnchor.constraint(equalToConstant: scvc.overlayHeight),

            detailView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            detailView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            detailView.heightAnchor.constraint(equalToConstant: scvc.detailHeight),
            detailView.widthAnchor.constraint(equalToConstant: scvc.detailWidth),

            leftArrow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: scvc.arrowMargin),
            leftArrow.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            leftArrow.widthAnchor.constraint(equalToConstant: scvc.arrowSize),
            leftArrow.heightAnchor.constraint(equalToConstant: scvc.arrowSize),

            rightArrow.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -1 * scvc.arrowMargin),
            rightArrow.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            rightArrow.widthAnchor.constraint(equalToConstant: scvc.arrowSize),
            rightArrow.heightAnchor.constraint(equalToConstant: scvc.arrowSize),
        ])

    }

    func favorite() {
    }

    func play() {
        state = .play
    }

    func favoritesPlay() {
        play()
        state = .favorites
    }

    func shufflePlay() {
        play()
        state = .shuffle
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
        setupConstraints()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        /*var touch: UITouch? = touches.first

        if (touch?.view != detailView && !detailView.isHidden) {
            detailView.isHidden = true
        }*/
        super.touchesBegan(touches, with: event)
    }
}

叠加层:

fileprivate struct sizeConstants {
    static let pillHeight: CGFloat = 38
    static let pillCornerRadius: CGFloat = sizeConstants.pillHeight / 2
    static let titleFontSize: CGFloat = 13
    static let detailFontSize: CGFloat = 10
    static let imageCenterToLeading: CGFloat = 3
    static let circleDiameter: CGFloat = 66
    static let circleRadius: CGFloat = sizeConstants.circleDiameter / 2
    static let buttonTextHPadding: CGFloat = 4
    static let buttonTextVPadding: CGFloat = 2
    static let badgeSpacing: CGFloat = 5.5
    static let titleBadgeSpacing: CGFloat = 19
    static let badgeImageSize: CGFloat = 32
    static let badgeTextFromCenter: CGFloat = 0
    static let badgeTextToImage: CGFloat = 8
    static let buttonBackgroundToText: CGFloat = 6
    static let circleButtonSize: CGFloat = 48
    static let rectButtonWidth: CGFloat = 36
    static let rectButtonHeight: CGFloat = 39
    static let badgesToButtons: CGFloat = 21.5
}


class ButtonView: UIView {
    lazy var buttonBackgroundView: UIView = {
        let _buttonBackgroundView = UIView(frame: .zero)
        _buttonBackgroundView.translatesAutoresizingMaskIntoConstraints = false
        _buttonBackgroundView.backgroundColor = .black
        _buttonBackgroundView.layer.cornerRadius = sizeConstants.circleRadius

        return _buttonBackgroundView
    }()

    lazy var textBackgroundView: UIView = {
        let _textBackgroundView = UIView(frame: .zero)
        _textBackgroundView.translatesAutoresizingMaskIntoConstraints = false
        _textBackgroundView.backgroundColor = .black
        _textBackgroundView.layer.cornerRadius = _textBackgroundView.frame.height / 2

        return _textBackgroundView
    }()

    lazy var button: UIButton = {
        let _button = UIButton(frame: .zero)
        _button.translatesAutoresizingMaskIntoConstraints = false

        return _button
    }()

    lazy var label: UILabel = {
        let _label = UILabel(frame: .zero)
        _label.translatesAutoresizingMaskIntoConstraints = false
        _label.font = .systemFont(ofSize: 15)
        _label.textColor = .white

        return _label
    }()

    var isRect: Bool = false

    convenience init(rect: Bool) {
        self.init(frame: .zero)
        self.isRect = rect
        setupViews()
    }

    override func updateConstraints() {
        NSLayoutConstraint.activate([
            buttonBackgroundView.topAnchor.constraint(equalTo: topAnchor),
            buttonBackgroundView.centerXAnchor.constraint(equalTo: centerXAnchor),
            buttonBackgroundView.widthAnchor.constraint(equalToConstant: sizeConstants.circleDiameter),
            buttonBackgroundView.heightAnchor.constraint(equalToConstant: sizeConstants.circleDiameter),

            button.centerXAnchor.constraint(equalTo: buttonBackgroundView.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: buttonBackgroundView.centerYAnchor),

            textBackgroundView.topAnchor.constraint(equalTo: buttonBackgroundView.bottomAnchor, constant: sizeConstants.buttonBackgroundToText),
            textBackgroundView.centerXAnchor.constraint(equalTo: centerXAnchor),
            textBackgroundView.heightAnchor.constraint(equalTo: label.heightAnchor, constant: sizeConstants.buttonTextVPadding),
            textBackgroundView.widthAnchor.constraint(equalTo: label.widthAnchor, constant: sizeConstants.buttonTextHPadding),

            label.centerXAnchor.constraint(equalTo: centerXAnchor),
            label.centerYAnchor.constraint(equalTo: textBackgroundView.centerYAnchor),
        ])

        if (isRect) {
            NSLayoutConstraint.activate([
                button.widthAnchor.constraint(equalToConstant: sizeConstants.rectButtonWidth),
                button.heightAnchor.constraint(equalToConstant: sizeConstants.rectButtonHeight),
            ])
        } else {
            NSLayoutConstraint.activate([
                button.widthAnchor.constraint(equalToConstant: sizeConstants.circleButtonSize),
                button.heightAnchor.constraint(equalToConstant: sizeConstants.circleButtonSize),
            ])
        }
        super.updateConstraints()
    }

    private func setupViews() {
        addSubview(buttonBackgroundView)
        addSubview(textBackgroundView)
        addSubview(label)
        addSubview(button)

        label.sizeToFit()

        setNeedsUpdateConstraints()
    }

    func setButtonProps(image: UIImage, text: String, target: Any, selector: Selector) {
        self.button.addTarget(target, action: selector, for: .touchUpInside)
        self.button.setImage(image, for: .normal)
        self.label.text = text
    }
    @objc private func tapped() {
        print("tapped")
    }
}

class PlayOverlay: UIView {

    override init(frame: CGRect) {
        super.init(frame: .zero)
    }

    lazy var badgeStackView: UIStackView = {
        let _badgeStackView = UIStackView(frame: .zero)
        _badgeStackView.translatesAutoresizingMaskIntoConstraints = false
        _badgeStackView.axis = .vertical
        _badgeStackView.spacing = sizeConstants.badgeSpacing
        _badgeStackView.distribution = .equalSpacing

        return _badgeStackView
    }()

    lazy var buttonStackView: UIStackView = {
        let _buttonStackView = UIStackView(frame: .zero)
        _buttonStackView.translatesAutoresizingMaskIntoConstraints = false
        _buttonStackView.axis = .horizontal
        _buttonStackView.distribution = .equalSpacing

        return _buttonStackView
    }()

    var vc: PlaySecVC!

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

    override func updateConstraints() {
        NSLayoutConstraint.activate([
            badgeStackView.topAnchor.constraint(equalTo: topAnchor, constant: sizeConstants.titleBadgeSpacing),
            badgeStackView.centerXAnchor.constraint(equalTo: centerXAnchor),
            badgeStackView.widthAnchor.constraint(equalTo: widthAnchor),

            buttonStackView.topAnchor.constraint(equalTo: badgeStackView.bottomAnchor, constant: sizeConstants.badgesToButtons),
            buttonStackView.widthAnchor.constraint(equalTo: widthAnchor),
            buttonStackView.centerXAnchor.constraint(equalTo: centerXAnchor),
            buttonStackView.bottomAnchor.constraint(equalTo: bottomAnchor),
        ])

        super.updateConstraints()
    }
}

class BeginOverlay: PlayOverlay {

    override init(frame: CGRect) {
        super.init(frame: .zero)
    }

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

    private func setupViews() {
        addSubview(badgeStackView)
        addSubview(buttonStackView)

        let shuffleButton = ButtonView(rect: false)
        shuffleButton.setButtonProps(image: UIImage()/* replaced with empty image for demo */, text: "SHUFFLE", target: self, selector: #selector(shuffle))

        let favoritesButton = ButtonView(rect: false)
        favoritesButton.setButtonProps(image: UIImage()/* replaced with empty image for demo */, text: "FAVORITES", target: self, selector: #selector(favorites))

        let playButton = ButtonView(rect: false)
        playButton.setButtonProps(image: UIImage()/* replaced with empty image for demo */, text: "PLAY", target: self, selector: #selector(play))

        buttonStackView.addArrangedSubview(shuffleButton)
        buttonStackView.addArrangedSubview(favoritesButton)
        buttonStackView.addArrangedSubview(playButton)
    }

    @objc private func shuffle() {
        vc.shufflePlay()
    }

    @objc private func favorites() {
        vc.favoritesPlay()
    }

    @objc private func play() {
        vc.play()
    }
}

【问题讨论】:

  • 您有示例代码吗?因为我试图运行你的代码并且由于约束问题而崩溃。

标签: ios swift uiview uiviewcontroller uibutton


【解决方案1】:

这里是修复的地方。使用 Xcode 11.4 / iOS 13.4 测试

    lazy var buttonStackView: UIStackView = {
        let _buttonStackView = UIStackView(frame: .zero)
        _buttonStackView.translatesAutoresizingMaskIntoConstraints = false
        _buttonStackView.axis = .horizontal
        _buttonStackView.distribution = .fillEqually // << here !!!

        return _buttonStackView
    }()

这是完整的测试模块(为了比较,以防我更改了其他任何内容)。刚刚从模板创建单视图 iOS 项目并在 Storyboard 中分配控制器类。

fileprivate struct scvc {
    static let overlayWidth: CGFloat = 330
    static let overlayFromCenter: CGFloat = 25
    static let hotspotSize: CGFloat = 30
    static let detailHeight: CGFloat = 214
    static let detailWidth: CGFloat = 500
    static let arrowMargin: CGFloat = 9
    static let arrowSize: CGFloat = 56
    static let zoomRect: CGFloat = 200
    static let overlayHeight: CGFloat = 267
}

enum playState {
    case play
    case shuffle
    case favorites
}

protocol PlaySec: class {
}

class PlaySecVC: UIViewController, PlaySec {

    // MARK: UIComponents
    lazy var scrollView: UIScrollView = {
        let _scrollView = UIScrollView(frame: .zero)
        _scrollView.translatesAutoresizingMaskIntoConstraints = false
        _scrollView.clipsToBounds = false
        //_scrollView.isUserInteractionEnabled = true

        return _scrollView
    }()

    lazy var imageView: UIImageView = {
        let _imageView = UIImageView(frame: .zero)
        _imageView.translatesAutoresizingMaskIntoConstraints = false
        _imageView.contentMode = .scaleAspectFit
        //_imageView.isUserInteractionEnabled = true

        return _imageView
    }()

    lazy var beginOverlay: BeginOverlay = {
        let _beginOverlay = BeginOverlay(frame: .zero)
        _beginOverlay.translatesAutoresizingMaskIntoConstraints = false
        return _beginOverlay
    }()

    lazy var detailView: UIView = {
        let _detailView = UIView(frame: .zero)
        _detailView.translatesAutoresizingMaskIntoConstraints = false
        _detailView.isHidden = true
        //_detailView.isUserInteractionEnabled = false

        return _detailView
    }()

    lazy var leftArrow: UIButton = {
        let _leftArrow = UIButton(frame: .zero)
        _leftArrow.translatesAutoresizingMaskIntoConstraints = false
        _leftArrow.isHidden = false
        _leftArrow.setImage(UIImage(systemName: "arrow.left")!, for: .normal)

        return _leftArrow
    }()

    lazy var rightArrow: UIButton = {
        let _rightArrow = UIButton(frame: .zero)
        _rightArrow.translatesAutoresizingMaskIntoConstraints = false
        _rightArrow.isHidden = false
        _rightArrow.setImage(UIImage(systemName: "arrow.right")!, for: .normal)

        return _rightArrow
    }()

    var state: playState = .play

    // MARK: Setup

    private func setup() {
//        let viewController = self
        self.beginOverlay.vc = self
    }

    private func setupConstraints() {
        view.addSubview(scrollView)
        scrollView.addSubview(imageView)
        view.addSubview(detailView)
        view.addSubview(beginOverlay)
        view.addSubview(leftArrow)
        view.addSubview(rightArrow)

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            imageView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            imageView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),

            beginOverlay.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            beginOverlay.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -25),
            beginOverlay.widthAnchor.constraint(equalToConstant: scvc.overlayWidth),
            beginOverlay.heightAnchor.constraint(equalToConstant: scvc.overlayHeight),

            detailView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            detailView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            detailView.heightAnchor.constraint(equalToConstant: scvc.detailHeight),
            detailView.widthAnchor.constraint(equalToConstant: scvc.detailWidth),

            leftArrow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: scvc.arrowMargin),
            leftArrow.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            leftArrow.widthAnchor.constraint(equalToConstant: scvc.arrowSize),
            leftArrow.heightAnchor.constraint(equalToConstant: scvc.arrowSize),

            rightArrow.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -1 * scvc.arrowMargin),
            rightArrow.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            rightArrow.widthAnchor.constraint(equalToConstant: scvc.arrowSize),
            rightArrow.heightAnchor.constraint(equalToConstant: scvc.arrowSize),
        ])

    }

    func favorite() {
    }

    func play() {
        state = .play
    }

    func favoritesPlay() {
        play()
        state = .favorites
    }

    func shufflePlay() {
        play()
        state = .shuffle
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
        setupConstraints()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        /*var touch: UITouch? = touches.first

        if (touch?.view != detailView && !detailView.isHidden) {
            detailView.isHidden = true
        }*/
        super.touchesBegan(touches, with: event)
    }
}

fileprivate struct sizeConstants {
    static let pillHeight: CGFloat = 38
    static let pillCornerRadius: CGFloat = sizeConstants.pillHeight / 2
    static let titleFontSize: CGFloat = 13
    static let detailFontSize: CGFloat = 10
    static let imageCenterToLeading: CGFloat = 3
    static let circleDiameter: CGFloat = 66
    static let circleRadius: CGFloat = sizeConstants.circleDiameter / 2
    static let buttonTextHPadding: CGFloat = 4
    static let buttonTextVPadding: CGFloat = 2
    static let badgeSpacing: CGFloat = 5.5
    static let titleBadgeSpacing: CGFloat = 19
    static let badgeImageSize: CGFloat = 32
    static let badgeTextFromCenter: CGFloat = 0
    static let badgeTextToImage: CGFloat = 8
    static let buttonBackgroundToText: CGFloat = 6
    static let circleButtonSize: CGFloat = 48
    static let rectButtonWidth: CGFloat = 36
    static let rectButtonHeight: CGFloat = 39
    static let badgesToButtons: CGFloat = 21.5
}


class ButtonView: UIView {
    lazy var buttonBackgroundView: UIView = {
        let _buttonBackgroundView = UIView(frame: .zero)
        _buttonBackgroundView.translatesAutoresizingMaskIntoConstraints = false
        _buttonBackgroundView.backgroundColor = .black
        _buttonBackgroundView.layer.cornerRadius = sizeConstants.circleRadius

        return _buttonBackgroundView
    }()

    lazy var textBackgroundView: UIView = {
        let _textBackgroundView = UIView(frame: .zero)
        _textBackgroundView.translatesAutoresizingMaskIntoConstraints = false
        _textBackgroundView.backgroundColor = .black
        _textBackgroundView.layer.cornerRadius = _textBackgroundView.frame.height / 2

        return _textBackgroundView
    }()

    lazy var button: UIButton = {
        let _button = UIButton(frame: .zero)
        _button.translatesAutoresizingMaskIntoConstraints = false

        return _button
    }()

    lazy var label: UILabel = {
        let _label = UILabel(frame: .zero)
        _label.translatesAutoresizingMaskIntoConstraints = false
        _label.font = .systemFont(ofSize: 15)
        _label.textColor = .white

        return _label
    }()

    var isRect: Bool = false

    convenience init(rect: Bool) {
        self.init(frame: .zero)
        self.isRect = rect
        setupViews()
    }

    override func updateConstraints() {
        NSLayoutConstraint.activate([
            buttonBackgroundView.topAnchor.constraint(equalTo: topAnchor),
            buttonBackgroundView.centerXAnchor.constraint(equalTo: centerXAnchor),
            buttonBackgroundView.widthAnchor.constraint(equalToConstant: sizeConstants.circleDiameter),
            buttonBackgroundView.heightAnchor.constraint(equalToConstant: sizeConstants.circleDiameter),

            button.centerXAnchor.constraint(equalTo: buttonBackgroundView.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: buttonBackgroundView.centerYAnchor),

            textBackgroundView.topAnchor.constraint(equalTo: buttonBackgroundView.bottomAnchor, constant: sizeConstants.buttonBackgroundToText),
            textBackgroundView.centerXAnchor.constraint(equalTo: centerXAnchor),
            textBackgroundView.heightAnchor.constraint(equalTo: label.heightAnchor, constant: sizeConstants.buttonTextVPadding),
            textBackgroundView.widthAnchor.constraint(equalTo: label.widthAnchor, constant: sizeConstants.buttonTextHPadding),

            label.centerXAnchor.constraint(equalTo: centerXAnchor),
            label.centerYAnchor.constraint(equalTo: textBackgroundView.centerYAnchor),
        ])

        if (isRect) {
            NSLayoutConstraint.activate([
                button.widthAnchor.constraint(equalToConstant: sizeConstants.rectButtonWidth),
                button.heightAnchor.constraint(equalToConstant: sizeConstants.rectButtonHeight),
            ])
        } else {
            NSLayoutConstraint.activate([
                button.widthAnchor.constraint(equalToConstant: sizeConstants.circleButtonSize),
                button.heightAnchor.constraint(equalToConstant: sizeConstants.circleButtonSize),
            ])
        }
        super.updateConstraints()
    }

    private func setupViews() {
        addSubview(buttonBackgroundView)
        addSubview(textBackgroundView)
        addSubview(label)
        addSubview(button)

        label.sizeToFit()

        setNeedsUpdateConstraints()
    }

    func setButtonProps(image: UIImage, text: String, target: Any, selector: Selector) {
        self.button.addTarget(target, action: selector, for: .touchUpInside)
        self.button.setImage(image, for: .normal)
        self.label.text = text
    }
    @objc private func tapped() {
        print("tapped")
    }
}

class PlayOverlay: UIView {

    override init(frame: CGRect) {
        super.init(frame: .zero)
    }

    lazy var badgeStackView: UIStackView = {
        let _badgeStackView = UIStackView(frame: .zero)
        _badgeStackView.translatesAutoresizingMaskIntoConstraints = false
        _badgeStackView.axis = .vertical
        _badgeStackView.spacing = sizeConstants.badgeSpacing
        _badgeStackView.distribution = .equalSpacing

        return _badgeStackView
    }()

    lazy var buttonStackView: UIStackView = {
        let _buttonStackView = UIStackView(frame: .zero)
        _buttonStackView.translatesAutoresizingMaskIntoConstraints = false
        _buttonStackView.axis = .horizontal
        _buttonStackView.distribution = .fillEqually

        return _buttonStackView
    }()

    var vc: PlaySecVC!

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

    override func updateConstraints() {
        NSLayoutConstraint.activate([
            badgeStackView.topAnchor.constraint(equalTo: topAnchor, constant: sizeConstants.titleBadgeSpacing),
            badgeStackView.centerXAnchor.constraint(equalTo: centerXAnchor),
            badgeStackView.widthAnchor.constraint(equalTo: widthAnchor),

            buttonStackView.topAnchor.constraint(equalTo: badgeStackView.bottomAnchor, constant: sizeConstants.badgesToButtons),
            buttonStackView.widthAnchor.constraint(equalTo: widthAnchor),
            buttonStackView.centerXAnchor.constraint(equalTo: centerXAnchor),
            buttonStackView.bottomAnchor.constraint(equalTo: bottomAnchor),
        ])

        super.updateConstraints()
    }
}

class BeginOverlay: PlayOverlay {

    override init(frame: CGRect) {
        super.init(frame: .zero)
        self.setupViews()
    }

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

    private func setupViews() {
        addSubview(badgeStackView)
        addSubview(buttonStackView)

        let shuffleButton = ButtonView(rect: false)
        shuffleButton.setButtonProps(image: UIImage(systemName: "shuffle")!/* replaced with empty image for demo */, text: "SHUFFLE", target: self, selector: #selector(shuffle))

        let favoritesButton = ButtonView(rect: false)
        favoritesButton.setButtonProps(image: UIImage(systemName: "bookmark")!/* replaced with empty image for demo */, text: "FAVORITES", target: self, selector: #selector(favorites))

        let playButton = ButtonView(rect: false)
        playButton.setButtonProps(image: UIImage(systemName: "play")!/* replaced with empty image for demo */, text: "PLAY", target: self, selector: #selector(play))

        buttonStackView.addArrangedSubview(shuffleButton)
        buttonStackView.addArrangedSubview(favoritesButton)
        buttonStackView.addArrangedSubview(playButton)
    }

    @objc private func shuffle() {
        vc.shufflePlay()
    }

    @objc private func favorites() {
        vc.favoritesPlay()
    }

    @objc private func play() {
        vc.play()
    }
}

注意:如前所述,最好检查所有约束并修复运行时歧义。

【讨论】:

    【解决方案2】:

    我做了一些研究,发现由于BeginOverlay 内部有 2 个UIStackView,因此包含 3 个UIButton 的第二个位置存在歧义。下面的图片可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多