Khởi tạo một animation cho Play/Pause Button

217

IDEA xin giới thiệu tới các bạn bài hướng dẫn chuyên sâu từ tác giả Neeraj Kumar về cách để tạo một button play/pause với kỹ thuật morphing sử dụng Core Graphics.

 

Animation là những thành phần không thể thiếu trong bất kỳ ứng dụng iOS nào. Tác giả vừa mới bắt đầu bước vào nghiên cứu về animation (từ beginner tới complex) và tác giả dự tính sẽ chia sẻ với tất cả mọi người.

Đây là một số nguồn học animation mà tác giả gợi ý:

  1. orodov — iOS Animations by Tutorials.- Another Gem by Ray wenderlich team.
  2. iOS Core Animation advance techniques by Nick lockwood —
  3. Hướng dẫn phổ biến khác: Raywenderlich,Objc.io, iOS Goodies.

Tiếp theo sẽ là các hướng dẫn từng bước thực hiện:

  1. Giải thích cấu trúc của animation. Ghi chú lại những gì đang xảy ra và chuyển đổi nó thành những thành phần trong iOS. (Điều quan trọng là khi bạn nhận lấy những animations/interactions từ designer để phân tích nó thành những thành phần đơn giản từ khía cạnh thực hiện)
  2. Thảo luận một chút về Layers và các subclass của nó mà chúng ta sẽ sử dụng.
  3. Thực hiện từng bước:
    • Tạo Play View và backing layer của nó.
    • Thêm play animation.
    • Tạo Pause View và backing layer của nó.
    • Thêm pause animation.
    • Tích hợp 2 views với nhau bên trong một final view gọi là “PlayPauseView”.
    • Thêm animation cho PlayPauseView.
    • Thêm một button trong suốt hoặc một tap gesture cho PlayPauseView để bắt sự kiện tương tác với người dùng, sau đó thực hiện animate theo trạng thái hiện tại.

Deconstructing the animation

Play View observations

  1. Triangle collapsing. — Khi chiều cao của view sẽ animate tới giá trị 0.0 thì hình tam giác sẽ co lại.
  2. Frame movement. — Chúng ta có thể sử dụng animations của UIView để di chuyển frame.
  3. Visibility — Trạng thái của view sẽ đi từ hidden trước để bắt đầu hiện ra và ngược lại. Chúng ta kiểm soát trạng thái visibility bằng thuộc tính “alpha” trong iOS.

Pause View observations

  1. Bars width — Chiều rộng của các thanh sẽ di chuyển animate từ 0 đến max và ngược lại.
  2. Frame movement — Chúng ta cũng sử dụng animation của UIView để di chuyển frame.
  3. Visibility — Trạng thái của view sẽ đi từ hidden trước để bắt đầu hiện ra và ngược lại.

Dường chúng ta đã xác định được từng bước cần thực hiện.

Layers — Introduction

Tất cả UIView đều có một backinglayer để xử lý việc render, layout và animation cho UIView. Đó chính là các class của CALayer. Bạn có thể sử dụng chúng như thế này:

“layer” ở trên chính là backing layer hỗ trợ cho UIView.

CGPath — “graphics path is a mathematical description of a series of shapes or lines. CGPathRef defines an opaque type that represents an immutable graphics path” (Ref. — Apple Docs).

CAShapeLayer (subclass của CALayer) — Đây là một layer subclass để vẽ bản thân nó sử dụng đường path nhất định. Nó có những lợi thế hơn CoreGraphics như nhanh hơn và hiệu suất memory cao hơn (Vui lòng đọc thêm CAShapeLayer từ NickLockwood’s book đã gợi ý ở trên).

Implementation

PlayView

Chúng ta sẽ tạo PlayView như một subclass của UIView với backing layer tuỳ biến, đây sẽ là subclass của CAShapeLayer.

Một snipper từ TriangleShapeLayer: (Hình tam giác Play)

Nó sẽ override thuộc tính “bounds” của view. Khi thuộc tính “bounds” được thiết lập, nó gọi  “shapeForBounds” và tạo đường path theo giá trị bounds mới.

Lưu ý: Khi bounds/frame của một view thay đổi thì shape của chúng cũng sẽ điều chỉnh theo.

Snippet từ PlayView:

Kết quả:

play

Để thực hiện animation như thế này chúng ta cần 3 thứ:

1*0UF76ypI21KNIx3CgMsMkA

  1. Chiều cao của hình tam giác đi dần về 0 — Khi chúng ta thay đổi chiều cao của PlayView thì backing layer shape (hình tam giác) của nó cũng sẽ animate theo. Khi chúng ta thêm animation cho thuộc tính bounds của UIView chúng ta cần nói cho đường path để thực hiện animate, tốt nhất là chúng ta sẽ override method “addAnimation(anim: CAAnimation!, forKey key: String!)” và thêm một “CABasicAnimation cho đường path để animate theo bounds.
    Đây là đoạn snippet —

Đoạn snippet ở trên cho thấy nếu một animation được thêm vào cho size của view thì sau đó sẽ thực hiện animate cho đường path từ oldBounds đến newBounds.

  1. Alpha sẽ đi từ 1 tới 0.
  2. Dịch chuyển frame.

Bây giờ chúng ta thực hiện một UIView animation đơn giản cho PlayView và thay đổi tất cả những giá trị ở trên trong animation block và nó sẽ tái tạo lại animation.

Đoạn snipper như sau:

PauseView

Chúng ta sẽ thực hiện cho PauseView bằng cách tương tự. Một subclass UIView với CAShapeLayer tuỳ biến để hỗ trợ cho class PauseView.

1*og-3aB2iZ1xswwyif6aewg

Đoạn snippet từ PauseLayer:

Chúng ta đã override thuộc tính bounds và gọi “shapeForBounds” tham số “bounds” và “width” (cái mà nó quyết định chiều rộng của các thanh (dấu Pause). Tác giả đã cho nó bằng 1/3 chiều rộng của view nhưng có thể là con số khác). Chúng ta xác định các điểm và vẽ các đường bằng cách dùng UIBezierPath.

Animation sau đây cần 3 thứ:

1*k0BtYLFmoPnrK-kpHefn1g

  1. Thay đổi chiều rộng của các thanh từ 0 tới max (1/3 chiều rộng của view). Chúng ta animate chiều rộng của PauseView từ 0 tới max và đường path sẽ animate bản thân nó từ 0 tới max/3 hoặc ngược lại. Vì vậy chúng ta override method “addAnimation” trong PauseLayer. Đây là đoạn snippet:

Nếu animation mà thêm vào là “bounds.size” của PauseView thì sau đó animate cho đường path từ chiều rộng hiện tại tới giá trị chiều rộng mới của view (1/3 của view).

2. Thay đổi frame.

3. Thay đổi alpha.

Bây giờ sẽ thực hiện một UIView animation đơn giản cho PauseView và thay đổi tất cả những giá trị ở trên trong animation block và nó sẽ tái tạo animation ở phía trên.

Đây là đoạn snippet:

Đoạn snippet ngắn từ PauseView:

Bây giờ chúng ta sẽ tạo view cuối cùng là PlayPauseView cái mà xử lý trạng thái của view dù đó là trong trạng thái Play hay Pause và sẽ animate từ một trạng thái đến cái còn lại.

Dưới đây là đoạn snipper tạo animation từ một trạng thái đến cái còn lại:

Lưu ý: Tác giả cũng đã thêm một button trong suốt vào view này để bắt sự kiện hành động chạm vì vậy view này có thể được sử dụng như một button.

Kết quả cuối cùng sẽ như thế này:

final

Bạn có thể tìm bài hướng dẫn ở đây Neeraj’s blog.

Download source code: Github

Nguồn: IDE Academy via Maniacdev