Author: Vũ Đức Cương

  • Một số animation cho UITableView

    Một số animation cho UITableView

    TableView là được sử dụng rất nhiều trong các ứng dụng của chúng ta. Vì vậy, việc tạo thêm một số hiệu ứng cho TableView khiến cho ứng dụng trở lên sinh động và bớt nhàm chán hơn. Chỉ với một vài câu lệnh, mọi thứ sẽ trở lên mới mẻ và dễ gần hơn rất nhiều lần.

    Hầu như các animation của tableview sẽ được tạo trong method dưới đây:

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        // Add animations here
    }

    Chúng ta bắt đầu với hiệu ứng đơn giản nhất nhưng được sử dụng nhiều nhất:

    Kết quả đạt được:

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            cell.alpha = 0
            UIView.animate(withDuration: 0.5,
                           delay: 0.1 * Double(indexPath.row),
                animations: {
                    cell.alpha = 1
            })
        }

    Hiệu ứng Bounce animation:

    Bounce animation
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
          cell.transform = CGAffineTransform(translationX: 0, y: 60)
            UIView.animate(
                withDuration: 1,
                delay: 0.05 * Double(indexPath.row),
                usingSpringWithDamping: 0.4,
                initialSpringVelocity: 0.1,
                options: [.curveEaseInOut],
                animations: {
                    cell.transform = CGAffineTransform(translationX: 0, y: 0)
            })
    }

    Move and Fade Animation

    Kết hợp hai hiệu ứng trên và chung ta ngừng sử dụng hiệu ứng Spring cho Cell, một hiệu ứng mới được tạo thành.

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cell.transform = CGAffineTransform(translationX: 0, y: 30)
            cell.alpha = 0
    
            UIView.animate(
                withDuration: 1,
                delay: 0.05 * Double(indexPath.row),
                options: [.curveEaseInOut],
                animations: {
                    cell.transform = CGAffineTransform(translationX: 0, y: 0)
                    cell.alpha = 1
            })
    }

    Slide in Animation

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            cell.transform = CGAffineTransform(translationX: tableView.bounds.width, y: 0)
    
            UIView.animate(
                withDuration: 1,
                delay: 0.5 * Double(indexPath.row),
                options: [.curveEaseInOut],
                animations: {
                    cell.transform = CGAffineTransform(translationX: 0, y: 0)
            })
        }

    Trên đây là một số ví dụ về việc thêm animation vào tableview bằng các hiệu ứng cơ bản của UIView( transform, alpha …) ngoài ra với 1 số hiệu ứng khác như Flip, Change color … cũng được sử dụng rất nhiều trong các hiệu ứng animation. Chúng ta hoàn toàn có thể tạo ra các animation mang mang màu sắc của cá nhân như các họa sĩ code vậy.
    Một lưu ý đó là khi muốn kiểm soát tốt hơn các animation thì chúng ta nên tạo ra một class riêng  để xử lý việc chạy animation. Nó đồng thời cũng kiểm soát việc animation chỉ chạy một lần duy nhất với tất cả các cell.

  • [iOS] – Ai cũng có thể làm Animation (Part 3)

    [iOS] – Ai cũng có thể làm Animation (Part 3)

    Ở part cuối của Animation Basic này, mình xin giới thiệu đến mọi người phần ảo diệu nhất của animation với UIView đó là UIView.transition. Transitions được dùng khi chúng ta muốn tạo hiệu ứng cho việc hidden view hay add hoặc remove một view lên hoặc khỏi một view cha của nó hay thay thế 2 views cho nhau khá tương đồng với các slide chúng ta hay gặp trong power point.

    UIView Transitions và các hiệu ứng của View

    UIView.transition(with: self.view, duration: 2.0, options:[.transitionCrossDissolve, .repeat], animations: {
            self.view.addSubview(self.animatedView)
    }, completion: nil)

    Tương tự keyframe và animation, transition cũng gồm các thuộc tính cơ bản:

    • withView: view thực hiện animation
    • duration: thời gian thực hiện animation
    • options: nơi thêm các hiệu ứng thay đổi view
    • animations: closure chỉ ra animation đối tượng gì
    • completion: khi animation kết thúc, closure này sẽ được thực thi

    Các tùy chọn hiệu ứng options cho Transition

    • transitionFlipFromLeft/ transitionFlipFromRight
    UIView.transition(with: self.animationView, duration: 1, options: [.transitionFlipFromLeft, .repeat], animations: {
                self.animationImage.alpha = 1
            }, completion: { _ in
                self.animationImage.removeFromSuperview()
            })
    • transitionCurlUp/ transitionCurlDown
    UIView.transition(with: self.animationView, duration: 1, options: [.transitionCurlUp], animations: {
                self.animationImage.alpha = 0
                self.animationImage2.alpha = 1
            }, completion: { _ in
                self.animationImage.removeFromSuperview()
            })
    • transitionCrossDissolve
    UIView.transition(with: self.animationView, duration: 4, options: [.transitionCrossDissolve], animations: {
                self.animationImage.alpha = 1
            }, completion: { _ in
            })
    • transitionFlipFromTop/transitionFlipFromBottom
    UIView.transition(with: self.animationView, duration: 2, options: [.transitionFlipFromBottom], animations: {
                self.animationImage.alpha = 1
                self.animationImage2.removeFromSuperview()
    
            }, completion: { _ in
            })

    Transition rất đơn giản và cực kỳ hiệu quả, nó giúp app của chúng ta trở lên thân thiện, gần gũi hơn đối với người dùng. Tuy nhiên, nếu trong một màn hình có quá nhiều chuyển động sẽ dễ gấy rối mắt vì vậy hãy sử dụng các hiệu ứng animation một cách hiệu quả để đạt được kết quả tối ưu nhất.

    Cảm ơn mọi người đã theo dõi loạt bài về Basic Animation của mình!
    Hi vọng sẽ được mọi người ủng hộ ở những bài tiếp theo.

  • [iOS] – Ai cũng có thể làm Animation (Part 2)

    [iOS] – Ai cũng có thể làm Animation (Part 2)

    Như phần trước, mình đã đề cập đến những khái niệm cơ bản về animation trong iOS. Với phần này, mình sẽ đi sâu hơn về các thuộc tính và hiệu ứng của UIView để làm ra một animation đẹp mắt.

    Một số thuộc tính cơ bản của UIView.animation

    UIView.animate(duration: 1, usingSpringWithDamping: 0.2, initSpringVelocity: 0, delay: 0, options: [], animations: { 
    self.imageView.transform = CGAffineTransform(translationX: 0, y: 200)
    }, completion: nil)

    withDuration: giá trị TimeInterval (typealias cho Double) thời gian thực hiện animation tính bằng giây.

    delay: độ trễ tính bằng giây (TimeInterval cũng vậy) trước khi animation bắt đầu. Nếu bạn muốn bắt đầu hoạt hình ngay lập tức, bạn có thể bỏ qua tham số này (chỉ trong một số trường hợp nhất định) hoặc đặt thành 0.

    usingSpringWithDamping: độ nẩy của view khi gần đến điểm kết thúc( thuộc tính này giống với sự dao động của một vật thể khi được treo trên một cái lò xo trong thực tế).

    initSpringVelocity: Tốc độ di chuyển của view bắt đầu ở thời điểm xuất phát.

    Animation with Spring

    options: hiệu ứng hoạt hình của view trên quãng đường. Dưới đây là 1 số thuộc tính cơ bản của options:

    • .repeat: dùng để lặp lại animation vô hạn.
    • .autoreverse: là hiệu ứng view tới điểm kết thúc và trở lại điểm xuất phát.
    //Repeate
    UIView.animate(duration: 1, options: [.repeat], animations: { 
    self.imageView.transform = CGAffineTransform(translationX: 0, y: 200)
    }, completion: nil)
    //Autoreverse
    UIView.animate(duration: 1, options: [.autoreverse], animations: { 
    self.imageView.transform = CGAffineTransform(translationX: 0, y: 200)
    }, completion: nil)
    • .curveLinear: animation không có sự thay đổi về tốc độ từ khi bắt đầu tới điểm kết thúc.
    • .curveEaseIn: Tăng tốc khi bắt đầu animation
    • .curveEaseOut: Giảm tốc khi kết thúc animation
    • .curveEaseInOut: Kết hợp của .CurveEaseIn và .CurveEaseOut, tăng tốc khi bắt đầu animation và giảm tốc khi kết thúc animation.

    Keyframes giúp tạo các chuỗi animation riêng biệt

    Chúng ta có thể sử dụng các UIView.animation chồng lên nhau để tạo thành các chuỗi animation tuy nhiên sẽ gây lộn xộn các dòng code. Mọi việc sẽ trở lên dễ dàng hơn rất nhiều với keyframes hỗ trợ rất tốt xử lý các chuỗi animation kế tiếp nhau.

    Tương tự UIView.animation, câu lệnh của keyframe cũng gồm 1 số thuộc tính:

    UIView.animateKeyframesWithDuration(1.5, delay: 0.0, options: [], animations: {
    //add keyframes
    
    }, completion: nil)
    • duration : tổng thời gian diễn ra animation.
    • options : một danh sách các tuỳ chọn về cách thức animation.
    • animations : closure chỉ ra animation các key frames nào.
    • completion : khi animation kết thúc, closure này sẽ được thực thi.

    Tạo keyframe:

    UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.25, animations: {
        self.imageView.transform = CGAffineTransform(translationX: 0, y: 200)
    })
    • relativeStartTime : là thời điểm bắt đầu tính theo % trên tổng thời gian diễn ra animation. RelativeStartTime có giá trị 0 -> 1. Ví dụ: relativeStartTime = 0.2 -> animation sẽ bắt đầu sau 20% * tổng thời gian animation.
    • relativeDuration : là lượng thời gian tương đối tính theo % diễn ra animation cho keyframes với tổng thời gian diễn ra toàn bộ animation. Ví dụ: relativeDuration  = 0.25 tức là animation sẽ diễn ra trong 25% * tổng thời gian animation.
    • animations : closure chỉ ra animation đối tượng gì.

    Một ví dụ về ứng dụng của keyframe.

                UIView.animateKeyframes(withDuration: 2, delay: 0, options: [], animations: {
                UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
                    let translation = CGAffineTransform(translationX: 0, y: -200)
                    let rotation = CGAffineTransform(rotationAngle: CGFloat.pi)
                    self.imageView.transform = translation.concatenating(rotation)
                })
                UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.25, animations: {
                    self.imageView.transform = CGAffineTransform(translationX: -150, y: 200)
                })
                UIView.addKeyframe(withRelativeStartTime: 0.6, relativeDuration: 0.3, animations: {
                    let translation = CGAffineTransform(translationX: 0, y: 0)
                    let rotation = CGAffineTransform(rotationAngle: -CGFloat.pi)
                    self.imageView.transform = translation.concatenating(rotation)
                })
            }, completion: nil)

    Phần tiếp theo, mình sẽ giới thiệu về UIView.transtion.
    Cảm ơn mọi người đã ghé đọc bài viết của mình 🙂

  • [iOS] – Ai cũng có thể làm Animation (Part 1)

    [iOS] – Ai cũng có thể làm Animation (Part 1)

    Xin chào mọi người,

    Hôm nay, mình sẽ chia sẻ đôi chút kiến thức của mình về tạo animation giúp app của chúng ta trở lên thú vị và thu hút hơn đối với người dùng.

    Những điều cơ bản để tạo được animation

    Về cơ bản, animation là tổ hợp các thay đổi về frame, bounds, center, transform, alpla, backgroundColor của đối tượng trên mặt phẳng và không gian chứa đối tượng ấy. Tất cả những animaton phức tạp đều được tạo thành từ những phần tử cơ bản nói trên vì vậy khi gặp 1 yêu cầu về animation phức tạp, bạn đừng vội lo lắng, thay vào đó, hãy phân tích animation ấy và đưa về các khái niệm cơ bản nhất và thực hiện từng bước các thay đổi điều kì diệu sẽ xuất hiện và bạn sẽ rất thích thú với những gì mình làm được. 🙂


    UIView.animation thường được sử dụng với những animation đơn giản:

    UIView.animate(withDuration: 0, animations: {})

    Thay đổi màu sắc và hình dạng của View

    self.animationView.backgroundColor = UIColor.purple
    self.animationView.alpha = 1
    self.animationView.layer.cornerRadius = 50

    Làm thế nào để thay đổi được kích thước và vị trí?

    Hãy cùng tìm hiểu 3 câu lệnh sau đây để thực hiện được điều trên,

    imageView.transform = CGAffineTransform(scaleX: 2, y: 2)
    imageView.transform = CGAffineTransform(translationX: 0, y: 100)
    imageView.transform = CGAffineTransform(rotationAngle: CGFloat.pi)

    Ngoài ra, chúng ta còn có một số cách sau để thay đổi kích thước và vị trí của đối tượng,.

     imageView.frame.origin.x += 100
     imageView.frame.origin.y += 100
     imageView.center.x = 100
     imageView.frame.origin = CGPoint(x: 100, y: 100)  

    Hãy cùng nhau thử trộn các thay đổi trên vào xem kết quả chúng ta sẽ được gì nhé!

            UIView.animate(withDuration: 2, animations: {
                self.imageView.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
            })
            
            UIView.animate(withDuration: 2, animations: {
                self.imageView.transform = CGAffineTransform(translationX: 0, y: -200)
                let scaleImage = CGAffineTransform(scaleX: 4, y: 4)
                let rotateImage = CGAffineTransform(rotationAngle: CGFloat.pi * 2)
                self.imageView.transform = scaleImage.concatenating(rotateImage)
                
                self.imageView.alpha = 1
            })

    Chúng ta đã cùng nhau hoàn thành 1 trong những animation cơ bản nhất của một app.
    Hi vọng những kiến thức mình chia sẻ có ích với tất cả mọi người!