16
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

スマートデバイス・テクノロジーAdvent Calendar 2015

Day 12

「Yo.」みたいなUITableViewのアニメーションを作る

Last updated at Posted at 2015-12-11

「Yo.」というアプリをご存知ですか?

「Yo」というメッセージを送り合うだけのアプリですが、UIが**「So Cool!」**
かなり前にelocogyさんから教わりました。

Yo..jpeg

Coolなアニメーション!

elocogyさんから、どうやって実装しているか相談があり、
いろいろ試行錯誤してみました。

力技ですが、実装してみました。
※まだ不完全です。

完成イメージ

タップされたセルが一番上に移動するアニメーションです。

demo.gif

実装のポイント

  1. タップされたセルのスナップショットをとる。
  2. スナップショットを一番上のセルまで移動させ、一定時間経過するとスナップショットを消す。
  3. タップしたセルを一番上に入れ替え、再描画する。

サンプル

貧素なソースコードですが、ご愛嬌!
まずは、動かすことに重点をおきました。(言い訳)

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!
    var snapshot: UIView?
    var itemLists = ["株式会社", "スマート", "デバイス", "テクノロジー","♥","♤","♣","◆"]

    override func viewDidLoad() {
        super.viewDidLoad()
        configureTableView()
    }

    func configureTableView() {
        tableView.dataSource = self
        tableView.delegate = self
        tableView.rowHeight = 44.0
    }

    //MARK:- UITableViewDataSource
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return itemLists.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
        cell.textLabel?.text = itemLists[indexPath.row]
        return cell
    }

    //MARK:- UITableViewDelegate
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath) {
        let text = itemLists[indexPath.row]

     //タップされたセルのスナップショットをとる
        let cell = tableView.cellForRowAtIndexPath(indexPath)
        snapshot = self.selectedCellSnapshot(cell!)        
        let center = cell?.center
        snapshot?.center = center!
        snapshot?.alpha = 1
        tableView.addSubview(snapshot!)
        
        UIView.animateWithDuration(0.75, animations: {[weak self] () -> Void in

            if let weakSelf = self {

             //スナップショットを一番上のセルまで移動する                
                weakSelf.snapshot?.center = center!
                var index = indexPath.row * Int(weakSelf.tableView.rowHeight)
                index *= -1
                weakSelf.snapshot?.transform = CGAffineTransformMakeTranslation(0, CGFloat(index))
                weakSelf.snapshot?.alpha = 0.98
                cell?.alpha = 0
            }
            
        }) {[weak self] (finished) -> Void in
            
            if let weakSelf = self {
             
                //一番上まで行ったら、スナップショットを消して、タップしたセルを一番上に入れる
                cell?.hidden = true
                weakSelf.itemLists.removeAtIndex(indexPath.row)
                var deleteIndexPaths: [NSIndexPath] = []
                deleteIndexPaths.append(indexPath)
                weakSelf.tableView.deleteRowsAtIndexPaths(deleteIndexPaths, withRowAnimation: UITableViewRowAnimation.Bottom)
                weakSelf.itemLists.insert(text, atIndex: 0)
                var insertIndexPaths: [NSIndexPath] = []
                insertIndexPaths.append(NSIndexPath(forRow: 0, inSection: 0))
                weakSelf.tableView.insertRowsAtIndexPaths(insertIndexPaths, withRowAnimation: UITableViewRowAnimation.Top)
                weakSelf.snapshot?.hidden = true
            }
        }
    }

    /**
     選択されたセルをキャプチャーする
    */
    func selectedCellSnapshot(inputView: UIView) -> UIView {
        UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0)  
       inputView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        let snapshot = UIImageView(image: image)
        snapshot.layer.masksToBounds = false
        snapshot.layer.cornerRadius = 0
        snapshot.layer.shadowOffset = CGSizeMake(-5, 0)
        snapshot.layer.shadowRadius = 5.0
        snapshot.layer.shadowOpacity = 0.4
        return snapshot
    }
}

最後に

もっと良い方法があったら、ご教授ください。
現状は、一番上のセルが画面に見えている状態でないと、
それっぽく動作しません。

また、デザイナーさんの無茶振りに答えられるように、
UIデザイン(AutoLayoutを含む)及び、アニメーションも
柔軟に実装できるようになりたいです。

[参考] 無茶振りデザイナーのアニメーション群

dribbble

16
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?