Невозможно нажать UIButton после установки альфа на 0.0, даже при сбросе на 1.0 - PullRequest
0 голосов
/ 09 октября 2018

У меня есть простой код:

func tappedButton() {
   self.button.alpha = 1.0
    UIView.animate(withDuration: 1.0, delay: 4.0, options: .curveLinear, animations: {
        self.button.alpha = 0.0
    }) { _ in }
}

Эта функция направлена ​​на то, чтобы снова показать кнопку в течение 4 секунд, а затем скрыть ее (с анимацией в 1 секунду).Однако, хотя кнопка полностью видна в течение этих 4 секунд, нажатие на нее больше не работает.

Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Вам нужно использовать allUserInteraction в настройках, а также проверять наличие прикосновений.Анимация добавляется сразу, и хотя вы видите кнопку в системе, она уже скрыта.Что это значит?Это означает, что вы смотрите фильм.Но, по крайней мере, с включенным userInteraction вы можете проверить сенсорные события.Это здорово, но откуда мы знаем, что кнопка действительно показывает или нет?Ну, вы должны использовать две разные проверки, скорее всего.Один, который проверяет истинную альфа-версию UIView кнопки, а другой - непрозрачность на уровне представления.Я никогда полностью не смотрел на связь между анимациями UIView и Core Animation, за исключением того, что я думаю, что анимации UIView являются оберткой для Core Animations.UIView анимации определенно обновляют модель представления немедленно.Таким образом, альфа-анимация скорее всего интерпретируется как анимация непрозрачности на слое.Вооружившись этим, мы можем проверить непрозрачность слоя презентации по касаниям и увидеть, что кнопка нажимается, даже если модель представления считает, что альфа равна 0. Эта проверка на уровне презентации будет работать, пока непрозрачность выше 0.Итак, поехали.

 import UIKit

class ViewController: UIViewController {

    lazy var testButton : UIButton = {
        let v = UIButton(frame: CGRect(x: 20, y: 50, width: self.view.bounds.width - 40, height: 50))
        v.backgroundColor = UIColor.blue
        v.addTarget(self, action: #selector(buttonClicked), for: .touchUpInside)
        return v
    }()



    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(testButton)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        UIView.animate(withDuration: 1.0, delay: 4.0, options: .allowUserInteraction, animations: {
            self.testButton.alpha = 0
        }, completion: nil)

        //test the layer
         //test the layer for opacity
        if let presentation = testButton.layer.presentation()?.animation(forKey: "opacity"){
            print("the animation is already added so normal clicks won't work")
        }
    }

    @objc func buttonClicked(){
        print("clicked")
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        if let touch = touches.first{
            let location = touch.location(in: self.view)
            if self.testButton.frame.contains(location){
                //but what you might not know is the animation is probably already running
                //and so the check above misses this
                if let buttonPres = testButton.layer.presentation(),
                    let _ = buttonPres.animation(forKey: "opacity"),
                    let opacity = buttonPres.value(forKey: "opacity") as? CGFloat{
                    if opacity > 0{
                        buttonClicked()
                    }
                }
            }
        }
    }
}
0 голосов
/ 09 октября 2018

В соответствии с документацией для метода hittest (_: with :) из UIView https://developer.apple.com/documentation/uikit/uiview/1622469-hittest

Этот метод игнорирует объекты просмотра, которые скрыты, которые отключили взаимодействие с пользователем или имеютальфа уровень менее 0,01.Этот метод не учитывает содержимое представления при определении попадания.Таким образом, представление все еще может быть возвращено, даже если указанная точка находится в прозрачной части содержимого этого представления.

Это означает, что любое представление, особенно кнопка, с альфа 0.0 не будет затронуто.

Однако проблема здесь в том, что кнопка все еще видна, по крайней мере, для вас.Такое поведение odd происходит потому, что фактическое альфа-значение кнопки уже установлено равным 0.0, когда анимация начинается.Анимации работают, изменяя визуальную иерархию и переводя разницу с параметрами, которые вы задаете функции.В вашем случае у вас есть два состояния: вид с видимой кнопкой и другой вид без кнопки.Только визуальная часть анимирована, но соответствующие значения уже установлены.Решение будет:

func tappedButton() {
   self.button.alpha = 1.0
    UIView.animate(withDuration: 1.0, delay: 4.0, options: .curveLinear, animations: { [weak self] in
        self?.button.alpha = 0.01
    }) { [weak self] _ in self?.button.alpha = 0.0 }
}

РЕДАКТИРОВАТЬ: Это решение выглядит как взломать, но работает.Я использую этот подход, потому что обработчик завершения всегда вызывается со значением true.

func tapped() {
    let duration = 1.0
    let delay = 2.0
    let delayDuration = delay + duration
    UIView.animate(withDuration: duration, delay: delay, options: [.curveLinear, .allowUserInteraction], animations: { [weak self] in
        self?.saveButton.alpha = 0.1
    })
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayDuration, execute: { [weak self] in
        self?.saveButton.alpha = 0.0
    })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...