UIButtons 不响应使用 UIScrollView 的 ViewController 上的触摸

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

我正在开发嵌入了 UIScrollView 的 ViewController。我有:视图 ->scrollView ->contentView (UIView) ->backgroundImageView ->SettingsItemsView (UIView) ->UIButtons。因此,在 SettingsItemsView 内的 UIButtons 上添加目标后,它们都不会响应触摸。由于 UIScrollView 很可能存在冲突,但我还没有设法解决它。提前致谢!附上代码

控制器

final class SettingsViewController: ViewController {
    
    var viewModel: SettingsViewModel!
    
    private let scrollView: UIScrollView = {
        let sv = UIScrollView()
        sv.alwaysBounceVertical = true
        sv.delaysContentTouches = false
        return sv
    }()
    
    private let contentView: UIView = {
        let view = UIView()
        return view
    }()
    
    private let backgroundImageView: UIImageView = {
        let iv = UIImageView()
        iv.image = Asset.Images.settingsBackground.image
        iv.contentMode = .scaleToFill
        iv.isUserInteractionEnabled = true
        iv.clipsToBounds = true
        return iv
    }()
    
    private let settingsItemsView: SettingsItemsView = {
        let view = SettingsItemsView()
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        let titleLabel = UILabel()
        titleLabel.text = "Settings"
        if let font = FontFamily.JosefinSans.semiBold.font(size: 24) {
            titleLabel.font = font
        }
        titleLabel.textColor = Asset.Colors.white.color
        navigationItem.titleView = titleLabel
    }
    
    override func arrangeSubviews() {
        super.arrangeSubviews()
        view.addSubview(backgroundImageView)
        backgroundImageView.addSubview(scrollView)
        scrollView.addSubview(contentView)
        contentView.addSubview(settingsItemsView)
    }
    
    override func setupViewConstraints() {
        super.setupViewConstraints()
        
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        contentView.translatesAutoresizingMaskIntoConstraints = false
        backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
        
        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),
            
            contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            
            backgroundImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            backgroundImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            backgroundImageView.topAnchor.constraint(equalTo: view.topAnchor),
            backgroundImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])

        settingsItemsView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            settingsItemsView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            settingsItemsView.widthAnchor.constraint(equalToConstant: 343),
            settingsItemsView.heightAnchor.constraint(equalToConstant: 350),
            settingsItemsView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 40)
        ])
    }
}

设置视图

final class SettingsItemsView: UIView {
    // Temporary image
    private var tempImage = UIImage(systemName: "apple.logo")

    private lazy var items: [SettingsItem] = [
        SettingsItem(option: SettingsOptions.privacy),
        SettingsItem(option: SettingsOptions.termsOfUse),
        SettingsItem(option: SettingsOptions.feedback),
        SettingsItem(option: SettingsOptions.share),
        SettingsItem(option: SettingsOptions.rate),
    ]

    private func configureOptions() -> [SettingsItemButton] {
        var options: [SettingsItemButton] = []

        for item in items {
            let button = SettingsItemButton(image: item.option.image!, name: item.option.name, option: item.option)
            button.clipsToBounds = true
            button.backgroundColor = .clear
            button.addTarget(self, action: #selector(testTapped(_:)), for: .touchUpInside)
            button.isUserInteractionEnabled = true
            options.append(button)
        }
        return options
    }

    @objc func testTapped(_ sender: SettingsItemButton) {
        print("Tapped: \(sender)")
    }

    private let stackView: UIStackView = {
        let stack = UIStackView()
        stack.axis = .vertical
        stack.distribution = .equalCentering
        stack.spacing = 0
        return stack
    }()

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

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    private func setupView() {
        addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        stackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        stackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        setupStyle()
        addSubviews()
    }

    private func addSubviews() {
        configureOptions().forEach { stackView.addArrangedSubview($0) }
    }

    private func setupStyle() {
        backgroundColor = Asset.Colors.tabBarBackground.color
        layer.cornerRadius = 22
        clipsToBounds = true
    }
}

按钮

final class SettingsItemButton: UIButton {
    
    var option: SettingsOptions!

    private let itemImage: UIImageView = {
        let btn = UIImageView()
        btn.tintColor = Asset.Colors.white.color
        btn.contentMode = .scaleAspectFill
        btn.backgroundColor = .blue
        return btn
    }()
    
    private let itemCheckMark: UIImageView = {
        let btn = UIImageView()
        btn.image = Asset.Images.arrowRight.image
        btn.tintColor = Asset.Colors.white.color
        btn.backgroundColor = .blue
        return btn
    }()
    
    private let itemName: UILabel = {
        let label = UILabel()
        if let customFont = FontFamily.Outfit.medium.font(size: 17) {
            label.font = customFont
        }
        label.textColor = Asset.Colors.white.color
        label.backgroundColor = .blue
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupSubviews()
        setupConstraints()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    convenience init(image: UIImage, name: String, option: SettingsOptions) {
        self.init(frame: .zero)
        configure(image: image, name: name, option: option)
    }
    
    func configure(image: UIImage, name: String, option: SettingsOptions) {
        self.option = option
        itemImage.image = image
        itemName.text = name
    }
    
    func setupConstraints() {
        itemImage.translatesAutoresizingMaskIntoConstraints = false
        itemName.translatesAutoresizingMaskIntoConstraints = false
        itemCheckMark.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            itemImage.centerYAnchor.constraint(equalTo: centerYAnchor),
            itemImage.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 24),
            itemImage.heightAnchor.constraint(equalToConstant: 24),
            itemImage.widthAnchor.constraint(equalToConstant: 24),
            
            itemName.centerYAnchor.constraint(equalTo: centerYAnchor),
            itemName.leadingAnchor.constraint(equalTo: itemImage.trailingAnchor, constant: 16),
            
            itemCheckMark.centerYAnchor.constraint(equalTo: centerYAnchor),
            itemCheckMark.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            itemCheckMark.heightAnchor.constraint(equalToConstant: 32),
            itemCheckMark.widthAnchor.constraint(equalToConstant: 24)
        ])
    }
    
    func setupSubviews() {
        addSubview(itemImage)
        addSubview(itemName)
        addSubview(itemCheckMark)
    }
}

我尝试使用 UICollectionView 而不是 UIStackView。但单元上没有按钮,单元本身也没有对触摸做出响应。我还尝试将不同图层上的 isUserInteractionEnabled 属性设置为 false,以防止一些冲突。

ios swift xcode autolayout
1个回答
0
投票

深入研究代码并进行一些编辑以使其运行后...

您的按钮不会响应点击,因为容纳它们的堆栈视图延伸到其超级视图的边界之外。

在您的

SettingsViewController
中,您的
contentView
没有高度。如果您设置
.clipsToBounds = true
:

private let contentView: UIView = {
    let view = UIView()
    // set clips to bounds true
    view.clipsToBounds = true
    return view
}()

并运行应用程序,您将不再看到按钮。

如果添加此行:

    NSLayoutConstraint.activate([
        settingsItemsView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
        settingsItemsView.widthAnchor.constraint(equalToConstant: 343),
        settingsItemsView.heightAnchor.constraint(equalToConstant: 350),
        settingsItemsView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 40),
        
        // add this line
        settingsItemsView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20.0),
        
    ])

您的

contentView
现在将具有高度...您将再次看到按钮...并且您现在可以点击它们。

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