自定义,可重复使用的动画代码应该放在哪里?

时间:2016-03-22 22:40:54

标签: ios animation design-patterns core-animation cocoa-design-patterns

概述:我目前有一个实现自定义动画逻辑的自定义UIView子类,我不确定视图类是放置该代码的最佳位置。

我在Swift中创建一个iOS应用程序,它使用的是一个UIView子类,我称之为DoorView。 DoorView表示滑动门,响应于轻扫手势,执行滑动动画以打开。

这是我现在拥有的完整动画:

enter image description here

在尝试保持我的View Controller亮起时,我将处理这些动画的实际核心动画代码放入我的DoorView类中。我的视图控制器通过检查手势是否与打开给定门所需的手势相匹配来处理手势,如果是,则在DoorView上调用open()方法。

所以在ViewController中:

@IBAction func swipe(sender: UISwipeGestureRecognizer) {
        if (sender.direction.rawValue == currentDoorView.door.swipeDirection.rawValue) {
            self.currentDoorView.open()
        }
    }

这是我的DoorView类中的open()方法: 注意:这只是滑动动画,将来会使用Sliding-type检查来区分其他类型的门(例如铰链)。

func open(withDuration duration: CFTimeInterval = 1.0) {

    /// We only slideOpen if switch statement below determines self.door is Sliding,
    /// so we downcast as SlidingDoor so we can switch on door.slideDirection.
    /// For each slideDirection case, a different translation is created,
    /// which is then passed into the slideAnimation below.
    func slideOpen() {

        let slidingDoor = self.door as! SlidingDoor
        let translation: CATransform3D

        switch slidingDoor.slideDirection {
        case .Down:
            let height = baseLayer.bounds.height
            translation = CATransform3DMakeTranslation(0, height, 0)
        case .Left:
            let width = openingLayer.bounds.size.width
            translation = CATransform3DMakeTranslation(-width, 0, 0)
        case .Right:
            let width = openingLayer.bounds.size.width
            translation = CATransform3DMakeTranslation(width, 0, 0)
        case .Up:
            let height = baseLayer.bounds.height
            translation = CATransform3DMakeTranslation(0, -height, 0)
        }

        let slideAnimation = {
            (completion:(() -> ())?) in
            CATransaction.begin()
            CATransaction.setCompletionBlock(completion)
            CATransaction.setAnimationDuration(duration)
            self.openingLayer.transform = translation
            CATransaction.commit()
        }

        /// Actual call to slideAnimation closure. 
        /// Upon completion, notify delegate and call walkThroughDoor()
        slideAnimation({
            self.delegate?.doorDidOpen(self)
            self.walkThroughDoor()
        })
    }

    /// Switch to determine door type, and thus appropriate opening animation.
    switch self.door {
    case is Sliding:
        slideOpen()
    default:
        print("is not sliding")
    }
}

将动画逻辑放在视图类中是否可以?这是我的第一直觉因为a)这些动画特定于我的DoorView,并且b)因为animateWithDuration是UIView的类方法,所以似乎有一些先例可以让视图/视图类本身处理动画。

但我继续开发我的应用程序,我将添加更多带有自己动画的门类型,我担心DoorView会因动画代码而变得太胖。我应该在那时开始制作DoorView子类(即SlidingDoorView,HingedDoorView等)吗?

或者应该由视图控制器处理视图动画?除了VC膨胀之外,我的问题是,如果我想在其他视图控制器中使用DoorViews,我将需要复制代码。这样,我的DoorViews打包了他们自己的动画,我所有的VC需要做的就是调用open()。

1 个答案:

答案 0 :(得分:1)

我认为你可以做到这两个选项,并且两者都同样可以接受。

<强> 1。使用扩展程序从门视图代码中分离动画代码

在您的主要DoorView课程中输入门类型的新枚举,以便了解它的门类型。

然后创建一个新的swift文件并将其命名为DoorAnimation.swift并将其放入:

extension DoorView {
  func open(withDuration duration: CFTimeInterval = 1.0) {
    switch doorType {
      case .Hinged:
        openHingedDoor(duration)
      case .Sliding:
        openSlidingDoor(duration)
    }
  }

  func openSlidingDoor(withDuration duration: CFTimeInterval = 1.0) {
    // Enter the custom code 
    // You can call use self to access the current door view instance
  }

  func openHingedDoor(withDuration duration: CFTimeInterval = 1.0) {
    // Enter hinged door animation code
  }
}

<强> 2。 Subclass DoorView

在DoorView中创建一个函数:

func open() {
  print("WARNING: This requires an override.")
}

然后在每个子类中覆盖open()。

两种结构都有其优点和缺点。我说如果门不做太多选择1是很好的。如果他们有很多功能,那么选择2会更好。