Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

カスタムトランジションやジェスチャーを生かしたUIの実装ポイント

1,038 views

Published on

iOS Creators' Meetup vol.3でのでのLT登壇資料になります。

GestureRecognizer(UILongPressGestureRecognizer & UIScreenEdgePanGestureRecognizer)やCustomTransitionを活用したサンプル作成を行った際に実装のポイントや活用した部分についての事項に関してまとめたものになります。

Published in: Technology
  • Be the first to comment

カスタムトランジションやジェスチャーを生かしたUIの実装ポイント

  1. 1. カスタムトランジションやジェスチャーを 生かしたUIの実装ポイント iOS Creators Meetup #3 2017/01/24 Fumiya Sakai
  2. 2. 自己紹介と簡単な経歴など ✦ 今までの仕事履歴(本業) 石川県金沢市生まれ 本業はサーバーサイドのプログラマ ※Rails&PHP使い 26歳〜32歳: Webプログラマ(PHP & Rubyがキャリア長い) 23歳〜25歳: Webデザイナー兼ディレクター チャンスがあればiOSアプリ開発も絶賛やってみたい! 趣味:シルバーアクセサリー集め・スイーツ作り・アプリ開発 女子向け・グルメ・エンタメ関連のお仕事が多い Qiita : http://qiita.com/fumiyasac@github Github : https://github.com/fumiyasac ✦ 酒井文也(さかい ふみや) 東京(大塚)住まいの32歳 こんな格好を普段からしているので 遊び人に見られますがエンジニアです。 文系卒に思われますが 実は数学科で理系卒です。 めっちゃお酒好きそうに見えますが ビール苦手でお酒も超弱いです。 今でもたまにUIまわりとか触りたく なることがあったりなかったり 今年の4月からフリーランスです。 (割とお堅い感じの会社にいます) 最近のはまっている食べ物は カボチャと担々麺と甘栗です。 最近はSwift以外ではRailsやLaravel・CakePHP・Node.jsなんかも
  3. 3. これまでに作ったもの(ネイティブアプリ) ① 簡易家計簿アプリ「Coffre」 ② ゲームアプリ「10秒虫食い算」 ・カレンダーを自作しています ・シンプルなお小遣い帳感覚で支出管理できます ・全問正解者ほとんどいません… ・不定期ですがコラムも書いています ・サーバーサイドはRuby on Railsを使用 http://www.coffre.me/ ・デザインにもこだわってみました(特にグラフ) ・実はちょっとバグがあります。 ・問題は今後追加予定(現在110問収録) 個人的にはなりますが、他にもアプリ・Webサービスなど開発中です(2016年も宜しくお願いします) ・サイト等は次回のアップデートで公開予定 http://blog.just1factory.net/services/284 ・若干の中毒性を含みます
  4. 4. カレンダーが好きでライブラリを作りました 日本の祝祭日を計算で出してくれる ・カレンダーアプリ等での活用を想定 ・シルバーウィーク・ゴールデンウィークも対応 ・ハッピーマンデー法の施行も対応 ・春分の日・秋分の日にも対応 ・過去の祝祭日もおおむね考慮はしている 構想や基本実装は僕ですが、他に4名のContributorのお力添えがあり実運用できるレベルになりました! 職人の手作業で計算しております! ・HTTP(HTTPS)通信は不要 ★CalculateCalendarLogic ver0.1.3 【最新情報】最近はmacOSのサポートがされました! ※CocoaPods / Carthage経由で導入できます。 ・Github: https://github.com/fumiyasac/handMadeCalendarAdvance ・実装解説: http://qiita.com/fumiyasac@github/items/33bfc07ad36dfffcdf8f 【2017年】Swift3系への正式対応をしていますので是非README等を参考に導入してみてください!
  5. 5. ✦ 今回紹介するGestureRecognizerは下記の2つ UI実装時に発見したGestureRecognizer 長押しを検知してイベントを発生させる UIサンプルを作成する過程の中で「このタイミングで使用した」という機会があったので今回共有します。 ライブラリを使わずにUI部分を強引にDIYしてみたり、サンプル製作の過程の中で僕自身も知りました… ★UILongPressGestureRecognizer ・minimumPressDuration: イベント発生までの時間 ・allowableMovement:指のズレの許容範囲 ★UIScreenEdgePanGestureRecognizer 【実際になかなか使う機会がなさそう?と自分自身も勝手ながら感じていた】 ・numberOfTapsRequired:タップする回数 1本以上の指で触れ、 接触したままを保持する 主なプロパティ紹介: ・numberOfTouchesRequired:タップする指の数 画面端のPanを検知してイベントを発生させる 画面の縁に触れ、 接触したまま移動する ・edges: 端の位置を取得(上下左右) ※ UIRectEdgeはenumで指定(例. 左の場合は .left) 主なプロパティ紹介:
  6. 6. ✦ メインの表示状態からPanを検知して下に隠れた部分を表示 UIScreenEdgePanGestureRecognizerを活用 隠れているサイドメニューを表示させるためのトリガーとして使用するケース等では活用ができそうかも。 ★ハンバーガーメニューと併せる きっかけ: その1) ハンバーガーメニューがあるUIの場合、 端からドラッグするメニューが現れること が多かった。 このサンプルではコンテンツが表示された状態から下に隠れているメニュー画面を、左端のPanを トリガーとして開くような形にしている。 ポイント: その2) 別途に配置したUI部品に付与したGesture とバッティングしてデバッグが難しい場合 があった。 → 1つのViewControllerに2つのContainerView(表示用とサイドメニュー用)が配置されている。
  7. 7. ✦ 先ほどの見た目を図解するとViewControllerはこのような形 UIScreenEdgePanGestureRecognizerの実装 self.viewに付与すると、開く動作中に別の指でself.viewの左端を触ると固まるのでこの実装にしました。 ★ぴったりと重なったコンテンツ用のContainerViewを開くトリガーとして活用 ・UIScreenEdgePanGestureRecognizer  (コンテンツのContainerViewに付与する) ・おおもとのView (self.view) ・コンテンツ用のContainerView (mainContentsContainer) ・サイドメニュー用のContainerView (sideMenuContainer) コンテンツ表示用のContainerViewの大きさはおおもとのviewと同じ大きさ //左隅部分のGestureRecognizerを作成する(デリゲートの設定と検知位置を決める) let edgeGesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(ViewController.edgeTapGesture(sender:))) edgeGesture.delegate = self edgeGesture.edges = .left //初期状態では左隅部分のGestureRecognizerを有効にしておく mainContentsContainer.addGestureRecognizer(edgeGesture)
  8. 8. ✦ セルの長押しをして画像のドラッグ&ドロップでデータを選択 UILongPressGestureRecognizerを活用 ドラッグ&ドロップ処理表現のトリガーの際にTapやPanでは検知までの間隔が短すぎたので誤作動対策に。 ★データ選択時のトリガーに活用 きっかけ: その1) ただのタップでの選択ではなくゲームのよ うな感覚で写真から直感的に選択するよう な形を表現してみたかった。 UICollectionViewのセルに対してUILongPressGestureRecognizerを付与する ポイント: その2) TapGestureやPanGestureでは検知まで時間 が短すぎるのでドラッグまでのつなぎをな るべく自然な形に&誤作動を減らすため。 → 画像が抜き出てドラッグしているように見せるために選択した画像を非表示にする。 → UILongPressGestureRecognizer検知時に発動するメソッドにtag値から識別できるようにする。
  9. 9. ✦ UICollectionViewのセルに付与しその後の処理でドラッグ&ドロップ UILongPressGestureRecognizerの実装 イベント発生までのタップ時間の設定や指のズレの許容範囲を設定できるのでより細かい設定が可能です。 ★画像のドラッグ&ドロップに関する処理を行う直前のトリガーとして活用 //セルに表示する値を設定する internal func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { //セルの定義を行う let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecipeCell", for: indexPath) as! RecipeCell //(省略)セルへ受け渡された値を設定する //cellのタグを決定する(LongPressGestureRecognizerからの逆引き用に設定) cell.tag = indexPath.row //LongPressGestureRecognizerの定義を行う let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(MakeRecipeController.longPressCell(sender:))) //イベント発生までのタップ時間:0.24秒 longPressGesture.minimumPressDuration = 0.24 //指のズレを許容する範囲:10px longPressGesture.allowableMovement = 10.0 //セルに対してLongTapGestureRecognizerを付与する cell.addGestureRecognizer(longPressGesture) return cell } longPressCellメソッド内で選択したセルの識別と ドラッグ&ドロップの実処理部分を行う。
  10. 10. ✦ NSObjectを継承 & UIViewControllerAnimatedTransitioningを適用 アニメーションを行う実体となるContainerViewの中に遷移元・遷移先の情報とロジックを記載する形に。 ★設定するのは動きの秒数と画面遷移時のアニメーション実体となるContainerView CustomTransitionの基本形(遷移用Class) //アニメーションの時間を定義する internal func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return (アニメーションの動作時間) } //アニメーションの実装を定義する internal func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { �//(流れ1) コンテキストを元にViewないしはViewControllerのインスタンスを取得する(存在しない場合は処理を終了) �//(流れ2) アニメーションの実態となるコンテナビューを作成 �//(流れ3) 拡大・縮小等の処理を記載しアニメーションの実体となるContainerViewに必要なものを追加する ����UIView.animate(withDuration: (アニメーションの動作時間), delay: 0.0, options: .curveEaseOut, animations: { �����//アニメーション処理の中身 �}, completion:{ finished in ����transitionContext.completeTransition(true) �}) } transitionContext = 遷移元や遷移先のViewControllerやそのほか関連する情報が格納されているもの
  11. 11. ✦ 遷移時のアクションのpresented側にtransitionDelegateを適用 遷移用クラスのインスタンスをViewController側で作りUIViewControllerTransitioningDelegateを適用する ★適用させるプロトコル:UIViewControllerTransitioningDelegate CustomTransitionの基本例(ViewController) //進む場合のアニメーションの設定を行う internal func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return (UIViewControllerAnimatedTansitioningのインスタンス) } //戻る場合のアニメーションの設定を行う internal func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return (UIViewControllerAnimatedTansitioningのインスタンス) } このケースはModalでの遷移をCustomTransitionを活用してカスタマイズすることを想定しています。 遷移用のClass内でPresented / Dismissの場合分けが行えるような形で実装をしておく。 ポイント: ※UINavigationControllerと併用してPush / Popの遷移アニメーションのカスタマイズも可能 該当のViewControllerで遷移用Classのインスタンスを作成しPresented / Dismissの設定を行う。
  12. 12. ✦ 実際に試してみた事例がありますので併せてお時間がある際にどうぞ Demo実装サンプルの紹介 ジェスチャーやカスタムトランジションをうまく活用してUIをより綺麗に彩る実装ができそうな感じです。 ★LongPressGestureRecognizer & CustomTransition (Qiita) ジェスチャーやカスタムトランジションを利用して入力時やコンテンツ表示時に一工夫を加えたUIの 実装ポイントまとめ http://qiita.com/fumiyasac@github/items/6c4c2b909a821932be04 (Github)DraggableImageForm https://github.com/fumiyasac/DraggableImageForm 【記事のボリューム自体があまりにゴツすぎてすみません…どこぞの機会で発表 or 補足解説できれば!】 (Qiita) SwiftでStoryboardとContainerViewを活用して、動きに合わせた細部のアレンジを加えたサンプル例 (iOSで良くあるライブラリを参考にDIYしました) http://qiita.com/fumiyasac@github/items/eb5b17ab90f5aa27b793 (Github)SimplySideMenuSample https://github.com/fumiyasac/SimplySideMenuSample ★ScreenEdgePanGestureRecognizer
  13. 13. ✦ 研究のしがいがあるCustomTransitionやGestureRecognizer 今回のまとめ ご清聴ありがとうございました!またこのような機会があった際には是非ともよろしくお願い致します! ★ユーザーの指の動きを想定したUIを組み立てる際の表現はとても面白い 選択時のドラッグ&ドロップの手前での要素検知やメニュー開閉のトリガーにも応用可能 ★気持ちの良いアニメーションを伴うCustomTransitionの表現もとても面白い ModalやNavigationControllerでの画面遷移にも工夫を加えることでより表現がリッチにできる ★デバッグ時にはGestureRecognizerの混在やCustomTransitionの内部処理には注意 細かな部分の配慮や考慮すべき点がこだわればこだわるとたくさん出るのでデバッグが少し大変かも ★自分ルール 【良いアウトプットのために】 発表・登壇時はこの中のいずれか2つを 絶対に準備するルールを設けています!

×