初めて出したiOSアプリのUI/UXの工夫点とその実装


概要

UXを高めるマイクロインタラクション実装 byゆめみ② Advent Calendar 2018の12/22(土)の記事です!!

業務でiOSを開発して一年以上経過し、この前自分で作ったアプリをリリースできました。(ネイティブ開発はAndroid, Unity, Cordovaなどでかれこれ5年ほどやっています)
そのアプリを開発する際にマイクロインタラクションで工夫した部分なぜそうしようとしたかを紹介いたします。

アプリの概要

ウェナタップ - いつタップしたかわかるアプリ

その名の通り、アイコンを並べてそのアイコンがいつタップされたかがわかります。アイコンのタップ回数などもわかるアプリです。

工夫点の紹介

Collection Viewのアイテムをタップしたときのインタラクション

問題

iOS標準のままのCollectionViewのCellではタップされたのかわからない

工夫点

一般的な解決方法ですが、タップしたcellのimageの部分をアニメーションさせてタップを表現しました。
このアプリはタップした時間を表示するアプリなので、imageの下の「何分前に最後にタップしたかの情報」と「最後にタップした時刻」が変化します。

問題その2

上のタップアニメーションなどだけのインタラクションだとユーザーはこのタップという行為にどういう意味があるのかわからない。

工夫点その2

タップアニメーションだけだとタップしたことしかわかりません。

タップという行為がどのようなことに繋がっているのかということを示したかったので、「今日のタップ回数」と、「今までのタップ回数」をタップした分だけ増やすことで、自分のタップは全て記録され、カウントされているのだということをユーザーに感じてもらえるようにしました。(下のInfo部分)

実装


    /// imageのアニメーション
    func animateImage(completion: (() -> Void)? = nil){
        UIView.animate(withDuration: 0.1, animations: {
            self.imageView.transform = CGAffineTransform.identity.scaledBy(x: 1.3, y: 1.3)
        }) { completed in
            self.imageView.transform = CGAffineTransform.identity
            completion?()
        }
    }

前の画面に戻ったときにTableのどこを選択していたか表現する

問題

遷移先の画面から戻ってきた時、自分がどこを設定したかがわからない。

工夫点

新規のタスクの作成画面です。アイコン選択ですが、戻ってきたときにアイコンを自分が選択したかがわかるようになっています。

実装

UITableViewControllerを利用しているなら何もしなくてもなります。
普通のTableViewの場合は以下です。


    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tableView.indexPathsForSelectedRows?.forEach{
            tableView.deselectRow(at: $0, animated: true)
        }
    }

スクロール可能領域が変化したときにバーとinsetを変化させる

問題

このアプリはCollectionViewと下から出てくるタップ数を記載したView(SubViewとこれから呼びます)の2つの構成です。
SubViewが出ると、CollectionViewのアイテムの下の部分がタップできなくなるといった問題や、表示領域が少なくなってしまうという問題があります。

工夫点

スクロール領域をSubViewに合わせて変化させ、最後のアイテムまでスクロールできるようにしました。

表示領域が狭いという問題に関しては、SubViewをガラス張りのView(iOS標準)にすることで、下にまだアイテムがあるということがわかるようにしました。

最近のiOSではiphoneXの登場もあり、画面いっぱいに要素を表示したいという思想があると思います。
今回のアプリでも、できるだけメインコンテンツのCollectionViewのアイテムをいっぱい見せるため、navigationBar,SubView,bottomBar全てで標準のガラス張りを採用しました。

実装

PropertyAnimator利用しています。こちら参考に実装しています。
Advanced Animations with UIKit


    ///下のViewのアニメーションに合わせてscrollIndecatorInsetsなどを変化させる。
    private func addCollectionViewInsetAnimator(state: State, duration: TimeInterval) {
        let insetAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 1)  {
            switch state {
            case .expanded:
                self.collectionView.scrollIndicatorInsets.bottom = self.bottomMiddleHeight + 5
                self.collectionView.contentInset.bottom = self.bottomMiddleHeight + 5
            case .collapsed:
                self.collectionView.scrollIndicatorInsets.bottom = self.bottomHeaderHeight + 5
                self.collectionView.contentInset.bottom = self.bottomHeaderHeight + 5
            }
        }
        runningAnimators.append(insetAnimator)
    }

スクロールできるViewは見えたときにbarを表示

問題

そもそもスクロールできるかわからない。

工夫点

Viewが表示されたときに、スクロールバーを表示する。

3つ目のセルは横にスクロールしてたくさん色を選択できるようになっています。横スクロールできるという発想はなかなか起こらないと思うので、スクロールバーをflushさせることでスクロールできることをユーザーにアピールしています。

実装

ViewControllerのviewDidAppearで表示する

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        colorCollectionView.flashScrollIndicators()
    }

編集モードを明確に表現する

問題

編集モードになってもCollectionViewの場合はわかりにくい
(EditButtonの「編集」が「完了」に変わるだけ)

工夫点

あまり見ない方法だと思いますが、通常モードでは出していないnavigationBarを表示することで編集モードになったこと、なっていることがわかりやすいようにしました。

また、編集モードで何ができるかをpromptを利用して説明しています。

他には、以下が考えられると思います。
* アイコンの周りにバッジを表示したりして、編集できることを表現する
* barや背景色を変化させる

実装


    override func viewDidLoad() {
        super.viewDidLoad()
        toolbarItems?.insert(editButtonItem, at: 1) // editButton追加
        setEditing(false, animated: true)
    }

    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        navigationItem.prompt = editing ? "編集・削除したいアイテムをタップしてください。" : nil
        title = editing ? "編集モード" : nil
        navigationController?.setNavigationBarHidden(!editing, animated: true)
    }

UITextFieldを含むCellはCellのタップ時にテキスト入力できるようにする

問題

TableviewのCellのなかに配置しているTextFieldをタップしようとして、Cell自体をタップしてしまう。
すると、Cellが選択されるだけで終わってしまう。

工夫点

Cellがタップされた時も、CellのなかのTextFieldにフォーカスするようにする。
もちろんTextFieldがタップされればそのまま入力できます。

実装


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // テキスト入力のセルがタップされた
        if indexPath.row == 1 {
            titleTextField.becomeFirstResponder()
            tableView.deselectRow(at: indexPath, animated: true) //これやらないとずっと選択されたまま
        }
    }

最後に

初のiOSアプリの初のAdvent Calendarでしたがいかがでしたでしょうか。

自分はどのようなインタラクションを行うとユーザーがどう思うかということを考えるのが好きなのですが、マイクロインタラクションの事例をもっと知っていきたいです。

この記事が誰かの役に立てば幸いです。
以上です。ありがとうございました。

作ったアプリ

ウェナタップ - いつタップしたかわかるアプリ
まだタップした時間や回数がわかるだけのアプリですが、もっと生活に役立つアプリに進化させていきたいと思います!!
ご期待ください^^

参考にしたサイト