Tạo tính năng nifty UI như Twitter App

162

Bài viết này được submit bởi tác giả Yari lấy cảm hứng từ màn hình profile của ứng dụng Twitter. Có một số tính năng về giao diện rất hay trong màn hình profile với hình ảnh ở header mở rộng và co lại khi di chuyển lên và xuống, cách avatar thu nhỏ lại và phần user name di chuyển lên phần header khi cuộn lên.

Bài hướng dẫn của Yari sẽ chỉ cách để tạo những hiệu ứng như vậy bằng cách sử dụng Core Animation.

STRUCTURE’S DESCRIPTION

Trước khi đi vào bên trong code tác giả muốn đưa cho bạn một ý tưởng ngắn gọn về cách mà các UI được tổ chức.

Nhìn lại màn hình profile ở trên bạn có thể thấy hai đối tượng chính. Đầu tiên là một view đại diện cho các Header và view thứ hai là một scrollview trong đó có các hình ảnh profile (hãy gọi nó là Avatar) và các thông tin khác liên quan đến tài khoản như tên người dùng, và nút theo dõi. Trong màn hình này sẽ có thêm một view nữa gọi là Sizer chỉ để đảm bảo nội dung bên trong scrollview là đủ lớn để cho phép cuộn dọc được.

Như bạn thấy, cấu trúc của màn hình này rất đơn giản. Chỉ cần bạn lưu ý tác giả đã đặt phần Header ra ngoài Scrollview, chứ nó không nằm cùng với các thành phần khác, mặc dù điều này không cần thiết lắm nhưng nó sẽ giúp cấu trúc màn hình này linh hoạt hơn.

LET’S CODE

Nếu bạn nhìn kỹ ở animation cuối cùng, bạn sẽ nhận ra bạn có thể quản lý 2 hành động khác nhau:

  1. Người dùng kéo xuống (khi nội dung trong Scrollview ở trên top của màn hình).
  2. Người dùng cuộn xuống/lên.

Hành động thứ 2 lại có thể chia thành 4 bước:

2.1) Khi cuộn lên, header sẽ điều chỉnh lại size xuống cho tới khi nó đạt đến size mặc định của Navigation Bar và sau đó nó sẽ bám sát top của màn hình.

2.2) Khi cuộn lên, Avatar sẽ trở nên nhỏ đi.

2.3) Khi header cố định, Avatar di chuyển ra phía sau nó.

2.4) Khi top của Label user name chạm tới header, một label trắng sẽ xuất hiện từ tâm của bottom trong header. Hình ảnh của header sẽ được làm mờ đi.

Bây giờ chúng ta sẽ mở ViewController.swift và hãy thực hiện từng bước một.

SETUP THE CONTROLLER

Việc đầu tiên cần làm rõ là lấy thông tin của offset Scrollview. Chúng ta có thể dễ dàng thực hiện thông qua protocol UIScrollViewDelegate và gọi hàm scrollViewDidScroll.

Cách đơn giản để thực hiện chuyển động trên một view là sử dụng Core Animation transform 3 chiều và gán giá trị mới cho thuộc tính layer.transform.

Đây là những dòng code đầu tiên trong hàm scrollViewDidScroll:

Ở đây chúng ta sẽ lấy giá trị hiện tại của offset theo chiều dọc và khởi tạo 2 chuyển động mà chúng ta có thể thiết lập sau với hàm này.

PULL DOWN

Cách để quản lý hành động pull down:

Đầu tiên, chúng ta sẽ kiểm tra xem offset có giá trị đang âm: có nghĩa là người dùng đang pull down.

Phần code bên trong chỉ là một phép tính toán đơn giản.

Header phải scale để cạnh top của nó sẽ cố định với top của màn hình và hình ảnh bên trong sẽ được scale từ bottom của header.

Về cơ bản, sự chuyển động được thực hiện bằng cách scale và sau đó dịch chuyển tới top với một giá trị được tính từ headerSizevariation. Thật ra, bạn có đạt được kết quả tương tự khi di chuyển các điểm mốc của layer ImageView tới top và scale nó.

headerScaleFactor được tính toán theo tỷ lệ. Chúng ta muốn phần header scale tương ứng với offset. Nói cách khác: khi offset đạt đến gấp đôi chiều cao của header, tỷ lệ scale sẽ là 2.0.

Hành động thứ 2 là chúng ta cần quản lý việc cuộn lên/xuống. Hãy xem cách mà các chuyển động của từng thành phần khi hoàn tất trong UI này.

HEADER (FIRST PHASE)

Offset hiện tại sẽ lớn hơn 0. Header nên dịch chuyển chiều dọc theo offset cho tới khi nó đạt đến chiều cao mong muốn (chúng ta sẽ nói về việc làm mờ header sau).

Lúc này đoạn code rất đơn giản. Chúng ta chỉ cần dịch chuyển header bằng một giá trị xác định và đó sẽ là vị trí mà header sẽ dừng chuyển động.

AVATAR

Avatar được scale với logic tương tự như chúng ta sử dụng pull down nhưng trường hợp này  hình ảnh sẽ được gán liền với bottom chứ không phải top. Đoạn code sẽ tương tự ngoại trừ việc làm chậm animation scale bằng giá trị 1.4.


Như bạn thấy, chúng ta sử dụng hàm min để dừng việc scale Avatar khi header dừng chuyển đổi (offset_HeaderStop).

Ở vị trí này, chúng ta xác định layer frontmost phụ thuộc vào offset hiện tại. Tới khi offset nhỏ hơn hoặc bằng offset_HeaderStop thì layer frontmost là Avatar, ngược lại là header.

WHITE LABEL

Đây là đoạn code để thực hiện animate cho Label màu trắng:

Ở đây tác giả giới thiệu 2 biến mới: thứ nhất là offset_B_LabelHeader, khi offset bằng offset_B_LabelHeader thì label username màu đen chạm bottom của header.

Thứ hai là distance_W_LabelHeader: khoảng cách cần có giữa bottom của header và Label màu trắng để canh giữa Label bên trong header.

Sự biến đổi được tính toán bằng login sau: Label màu trắng phải xuất hiện ngay sau khi Label màu đen chạm vào header và nó sẽ dừng lại khi đạt đến khoảng giữa của header. Vậy chúng ta tạo ra Y transition bằng cách:

BLUR

Hiệu ứng cuối cùng là làm mờ header. Nó đã cho tác giả 3 thư viện để tìm ra giải pháp đúng đắn…Tác giả cũng đã cố gắng xây dựng helper OpenGL ES nhưng việc cập nhật độ mờ trong lúc realtime luôn rất lag khi kết thúc.

Sau đó tác giả đã nhận ra họ có thể tính toán độ mờ chỉ một lần, đặt lên những hình ảnh mờ và không mờ và chỉ sử dụng giá trị alpha. Họ chắc chắn đó cũng là những gì dev của Twitter đã làm.

Trong hàm viewDidAppear chúng ta tính toán làm mờ header và chúng ta ẩn nó đi, thiết lập giá trị alpha về 0:

View làm mờ được lấy bằng cách sử dụng FXBlurView.

Trong hàm scrollViewDidScroll chúng ta chỉ việc cập nhật giá trị alpha phụ thuộc vào offset:

Logic đằng sau phép tính toán này là giá trị tối đa phải bằng 1, việc làm mờ phải bắt đầu khi Label màu đen chạm đến header và nó phải dừng khi Label màu trắng ở vị trí cuối cùng.

Bạn có thể tìm bài hướng dẫn và download source code ở Think & Build.

Nguồn: IDE Academy via Maniacdev