Почему мой UIButton не полностью доступен для нажатия (UIKit в Swift)

Это моя кнопка:

import UIKit

class PassButton: UIButton {

    var videoVC: VideoGameVC?
    
    required init(isEnabled: Bool = false) {
        super.init(frame: .zero)
        
        self.isEnabled = true
        self.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)

        let imageViewBackground = UIImageView(frame: CGRect(x:0, y:0, width: 70, height: 80))
        imageViewBackground.image = UIImage(named: "pass_button")
        imageViewBackground.contentMode = UIView.ContentMode.scaleAspectFill
        addSubview(imageViewBackground)
        sendSubviewToBack(imageViewBackground)
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    @objc func pressed(_ sender: UIButton) {
        print("presovan")
    }
   
    
}

и вот как я добавляю его в другой контроллер представления:

func configPassButton() {
        passButton = PassButton()
        guard let passButton = passButton else { return }
        view.addSubview(passButton)
        passButton.translatesAutoresizingMaskIntoConstraints = false
        passButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
        passButton.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 20).isActive = true
        
        
    }

он отображается так, как я хочу, но область, которую можно коснуться, очень мала. Постукивать можно только в верхнем левом углу, причем очень маленьком (около 10% всей поверхности). Как я могу исправить, чтобы все можно было нажимать?


58
2

Ответы:

Вместо того, чтобы вручную добавлять подпредставление для фонового изображения, возможно, используйте свойство .setBackgroundImage() кнопки. Кроме того, размер кадра был установлен для ImageView, но, если я не заметил этого, размер кадра не был установлен для самой кнопки. Возможно, поэтому область нажатия кнопки не полностью соответствует размеру изображения.

Чтобы исправить это, удалите эти строки, устанавливающие фоновое изображение:

let imageViewBackground = UIImageView(frame: CGRect(x:0, y:0, width: 70, height: 80))
imageViewBackground.image = UIImage(named: "pass_button")
imageViewBackground.contentMode = UIView.ContentMode.scaleAspectFill
addSubview(imageViewBackground)
sendSubviewToBack(imageViewBackground) 

И замените приведенные выше строки этими, чтобы установить фоновое изображение кнопки, режим содержимого, ширину и высоту:

self.setBackgroundImage(UIImage(named: "pass_button"), for: .normal)
self.layoutIfNeeded()
self.subviews.first?.contentMode = .scaleAspectFill
self.widthAnchor.constraint(equalToConstant: 70).isActive = true
self.heightAnchor.constraint(equalToConstant: 80).isActive = true

После этих изменений кнопка должна стать полностью доступной для нажатия.

Другой вариант

Мне только что пришло в голову, что если вы хотите использовать подпредставление imageViewBackground вместо .setBackgroundImage(), установка размера кнопки, а затем обрезка фонового изображения также будет работать. Например, добавив это после sendSubviewToBack():

self.widthAnchor.constraint(equalToConstant: 70).isActive = true
self.heightAnchor.constraint(equalToConstant: 80).isActive = true
self.clipsToBounds = true

Решено

Предположим, у вас есть изображение с соотношением сторон 70:80. например это:

Ваш код отображает это следующим образом:

но, как вы знаете, вы можете нажать только в верхнем левом углу.

Если мы добавим к кнопке красную рамку в 2 точки:

passButton.layer.borderColor = UIColor.red.cgColor
passButton.layer.borderWidth = 2

это выглядит так:

рамка кнопки - это только 30 x 34 ... и 70 x 80 imageView выходит за пределы кнопки. Таким образом, можно нажать только на саму рамку кнопки.

Если вы задаете ограничения ширины и высоты кнопки:

passButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true
passButton.heightAnchor.constraint(equalToConstant: 80.0).isActive = true

то мы видим это:

и всю кнопку можно нажать.

Однако добавление UIImageView в качестве подпредставления — ужасный подход.

Гораздо более уместно установить свойство фонового изображения:

// safely handle optional
if let img = UIImage(named: "pass_button") {
    setBackgroundImage(img, for: [])
}

Опять же, нам также необходимо установить ограничения ширины и высоты, но теперь мы используем «стандартную» кнопку вместо подкласса с добавленными подпредставлениями:

let passButton = UIButton()

passButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(passButton)

NSLayoutConstraint.activate([
    passButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
    passButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20.0),
    passButton.widthAnchor.constraint(equalToConstant: 70.0),
    passButton.heightAnchor.constraint(equalToConstant: 80.0),
])

if let img = UIImage(named: "pass_button") {
    passButton.setBackgroundImage(img, for: [])
}

Если соотношение сторон вашего изображения не такое же, как у вашей кнопки, нужно еще немного поработать... но при использовании исходного кода у вас возникнет та же проблема - поэтому я предполагаю, что вы используете изображение с соотношением сторон 70:80. для начала.