StackView中的iOS UIButton未被点击

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

我在ButtonView类中有按钮,以添加一些背景和标签。这些ButtonViews被添加到UIStackView类中的视图PlayOverlay中。 PlayOverlay充当不同类型叠加层的父类,在此示例中,我仅包含BeginOverlay

BeginOverlayPlaySecVC表示。由于某些原因,无法点击BeginOverlay中的按钮。我已经尝试过使用XCode进行UIDebugging,以查看它们前面是否有任何视图,并且没有。它们是最前面的视图。当UIDebugging告诉我ButtonView的宽度,高度以及x和y不明确时,我确实得到一个错误。这是因为我对此没有任何约束,如下所示,因为它们被放置在堆栈视图中。如何使这些按钮可轻敲?

ViewController:

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个回答
1
投票

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

UI Debugging Image

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