iOS CustomView с AutoLayout в navigationItem не получает клики - PullRequest
0 голосов
/ 21 ноября 2018

Я создал собственное представление для navigationItem, но почему-то оно не получает никаких событий щелчка:

Код для customView ниже

class CustomNavigationView: UIView {

let backButton: UIButton = {
    let button = UIButton(type: .custom)
    button.setImage(UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil), for: .normal)
    button.isUserInteractionEnabled = true
    return button
}()

var profileImage: UIImageView = {
    let imageView = UIImageView()
    imageView.image = UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil)
    return imageView
}()

var profileName: UILabel = {
    let label = UILabel()
    label.text = "No Name"
    label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
    label.textColor = UIColor(red: 96, green: 94, blue: 94)
    return label
}()

var onlineStatusIcon: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor(28, green: 222, blue: 20)
    return view
}()

var onlineStatusText: UILabel = {
    let label = UILabel()
    label.text = "Online"
    label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
    label.textColor = UIColor(red: 113, green: 110, blue: 110)
    return label
}()

lazy var profileView: UIStackView = {
    let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
    stackView.alignment = .fill
    stackView.axis = .vertical
    stackView.distribution = .fillEqually
    stackView.spacing = 2
    return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
    print("Back Button click successfully")
}

private func setupConstraints() {
    self.addViewsForAutolayout(views: [backButton, profileImage, onlineStatusIcon, profileView])
    //Setup constraints
    backButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5).isActive = true
    backButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
    backButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
    backButton.widthAnchor.constraint(equalToConstant: 20).isActive = true

    profileImage.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 20).isActive = true
    profileImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
    profileImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5).isActive = true
    profileImage.widthAnchor.constraint(equalToConstant: 35).isActive = true
    profileImage.layer.cornerRadius = 18
    profileImage.clipsToBounds = true

    onlineStatusIcon.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor, constant: 0).isActive = true
    onlineStatusIcon.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: -8).isActive = true
    onlineStatusIcon.widthAnchor.constraint(equalToConstant: 10).isActive = true
    onlineStatusIcon.heightAnchor.constraint(equalToConstant: 10).isActive = true
    onlineStatusIcon.layer.cornerRadius = 5
    onlineStatusIcon.clipsToBounds = true

    profileView.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 5).isActive = true
    profileView.topAnchor.constraint(equalTo: profileImage.topAnchor).isActive = true
    profileView.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor).isActive = true

}

required init() {
    super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
    setupConstraints()
    addButtonTarget()
}

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

func addButtonTarget() {
    // Setup button callback
    backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

    print("Target added")
}
}

И я устанавливаю это представление как кнопку NavigationbarLeftЭлемент на мой взгляд Контроллер:

class ViewController:  UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    let customView = CustomNavigationView()
    self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: customView)
}
}

Вид отображается правильно, но щелчки не работают вообще.Я использовал отладку вида, чтобы проверить, находится ли какой-то другой слой поверх этого, что может вызывать проблемы, но ничего подобного нет.Я также проверил кадр backButton при добавлении цели с использованием точек отладки.

Есть ли решение этой проблемы.Не работает ли autolayout с пользовательским представлением в элементе навигации?Или я что-то упускаю?

Вы можете запустить приведенный выше фрагмент кода и увидеть, что щелчки не работают.

Это как-то связано с автоматическим макетом.Если я жестко закодирую позицию кадра, то щелчки работают.

class CustomNavigationView: UIView {

let backButton: UIButton = {
    let button = UIButton(frame: CGRect(x: 5, y: 5, width: 30, height: 30))
    button.setImage(UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil), for: .normal)
    button.isUserInteractionEnabled = true
    return button
}()

var profileImage: UIImageView = {
    let imageView = UIImageView(frame: CGRect(x: 40, y: 5, width: 30, height: 30))
    imageView.image = UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil)
    return imageView
}()

var profileName: UILabel = {
    let label = UILabel(frame: CGRect(x: 80, y: 5, width: 50, height: 15))
    label.text = "No Name"
    label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
    label.textColor = UIColor(red: 96, green: 94, blue: 94)
    return label
}()

var onlineStatusIcon: UIView = {
    let view = UIView(frame: CGRect(x: 65, y: 30, width: 10, height: 10))
    view.backgroundColor = UIColor(28, green: 222, blue: 20)
    return view
}()

var onlineStatusText: UILabel = {
    let label = UILabel(frame: CGRect(x: 80, y: 25, width: 50, height: 10))
    label.text = "Online"
    label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
    label.textColor = UIColor(red: 113, green: 110, blue: 110)
    return label
}()

lazy var profileView: UIStackView = {
    let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
    stackView.alignment = .fill
    stackView.axis = .vertical
    stackView.distribution = .fillEqually
    stackView.spacing = 2
    return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
    print("Back button is successfully called")
}

private func setupConstraints() {
    self.addSubview(backButton)
    self.addSubview(profileImage)
    self.addSubview(onlineStatusIcon)
    self.addSubview(profileView)
}

required init() {
    super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
    setupConstraints()
    addButtonTarget()
}

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

func addButtonTarget() {
    // Setup button callback
    backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

    print("Target added")
}
}

1 Ответ

0 голосов
/ 21 ноября 2018

Проблема связана с добавленными вручную ограничениями.При использовании отладчика представления ширина CustomNavigationView после его добавления на панель составляет 0.

Чтобы заставить контейнер расширяться, добавьте следующее ограничение в setupConstraints():

profileView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true

Теперь, когда контейнер расширяется в соответствии с его содержимым, события касания должны распространяться на кнопку, как и ожидалось.

...