【问题标题】:UIButton not showing selected state during CABasicAnimation在 CABasicAnimation 期间 UIButton 未显示选定状态
【发布时间】:2015-09-17 16:54:05
【问题描述】:

我有一个UIButton,我正在根据它后面的UICollectionView 的当前滚动位置设置动画。我正在执行的动画是将按钮图像从一个更改为另一个。

我正在使用以下代码来执行动画:

let buttonAnimation: CABasicAnimation = CABasicAnimation(keyPath: "contents")
buttonAnimation.fromValue = UIImage(named: "Search-Button")!.CGImage
buttonAnimation.toValue = UIImage(named: "Search-Button-Reverse")!.CGImage
buttonAnimation.duration = 1.0
self.searchButton.imageView!.layer.speed = 0.0; // Pause the animation
self.searchButton.imageView!.layer.addAnimation(buttonAnimation, forKey: "animateSearchButton")

然后我根据滚动视图内容偏移值scrollView.contentOffset.y 设置self.searchButton.imageView!.layer.timeOffset 来更新scrollViewDidScroll() { 中的动画状态。

这一切都很好,UIButton 的动画效果完全符合我的要求,但是当您按下它时通常显示的按钮的选定/突出显示状态不再起作用。我假设这是因为我通过设置layer.speed = 0.0 暂停了UIButton 内容上的任何动画,但是有什么办法可以解决这个问题吗?

我确实有过拥有 2 个UIButton's 的想法,每个图像一个,然后为每个图像的不透明度设置动画(一个淡出,另一个淡入),而不是为一个UIButton 的图像设置动画,但这看起来很混乱它还有一个问题,即使在不透明度为 0 之后,也不会通过顶部按钮将触摸传递到后面的按钮。

有人有什么建议吗?很高兴在 Objective-C 或 Swift 中查看解决方案,如果需要,我会自行转换。

【问题讨论】:

    标签: ios objective-c swift cabasicanimation quartz-core


    【解决方案1】:

    最后通过使用 2 UIButton's 解决了这个问题。前面的按钮有第一张图片,第二个按钮有第二张图片。

    所以按钮的动画如下:

    let fadeAnimation: CABasicAnimation = CABasicAnimation(keyPath: "opacity")
    fadeAnimation.fromValue = NSNumber(float: 1.0)
    fadeAnimation.toValue = NSNumber(float: 0.0)
    fadeAnimation.duration = 1.0
    fadeAnimation.removedOnCompletion = false
    self.searchButton.layer.speed = 0.0; // Pause the animation
    self.searchButton.layer.addAnimation(fadeAnimation, forKey: "opacitySearch")
    self.profileButton.layer.speed = 0.0; // Pause the animation
    self.profileButton.layer.addAnimation(fadeAnimation, forKey: "opacityProfile")
    
    let showAnimation: CABasicAnimation = CABasicAnimation(keyPath: "opacity")
    showAnimation.fromValue = NSNumber(float: 0.0)
    showAnimation.toValue = NSNumber(float: 1.0)
    showAnimation.duration = 1.0
    showAnimation.removedOnCompletion = false
    self.searchButtonReverse.layer.speed = 0.0; // Pause the animation
    self.searchButtonReverse.layer.addAnimation(showAnimation, forKey: "opacitySearchReverse")
    self.profileButtonReverse.layer.speed = 0.0; // Pause the animation
    self.profileButtonReverse.layer.addAnimation(showAnimation, forKey: "opacityProfileReverse")
    

    然后,正如我在问题中所述,我通过根据滚动视图内容偏移值 scrollView.contentOffset.y 设置 self.searchButton.imageView!.layer.timeOffset 来更新 scrollViewDidScroll() { 中的动画状态。

    此时唯一的问题是,虽然我们正在为第一个按钮的 opacity 值设置动画并且它在某个时候变为零,但实际的系统值没有更新,即即使看起来第一个按钮的opacity 是0,如果你要打印这个值,它仍然是它的初始值(或者它最后设置的值)。这意味着虽然前面的按钮已经消失并且现在显示的是后退按钮,但第一个按钮仍然会消耗触摸事件,因此后退按钮将永远不会显示其选定状态/被按下。

    为了克服这个问题,我将UIButtonoverride 子类化为在触摸事件发生时调用的pointInside() 方法(您可以将以下代码放在同一个swift 文件中的主类下方):

    class HeaderButton : UIButton {
        override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
            var useFrontButton = super.pointInside(point, withEvent: event)
            if self.layer.timeOffset > 0.5 {
                useFrontButton = false
            }
            return useFrontButton
        }
    }
    

    然后将 front button 设置为 HeaderButton 类型(我们刚刚创建的类)。

    现在每次按下前面的按钮,都会调用pointInside(),如果前面的按钮timeOffset的值大于0.5(即它的opacity小于0.5),则返回false并前面的按钮不会收到触摸。它将传递到后面的视图 - 您的后退按钮。

    【讨论】:

      【解决方案2】:

      如果这样按下按钮时更改了 alpha 值会怎样?

         if (button.selected) {
              self.button.alpha = 0.5;
          } else {
              self.button.alpha = 1.0;
          }
      

      我相信你会改变按钮出口的属性,而不是动作。

      【讨论】:

      • 你会把这个放在哪里?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多