Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to micro interactions for iOS apps

kiwi
September 02, 2018

Introduction to micro interactions for iOS apps

iOSDC 2018 (day3)
「iOSマイクロインタラクション入門」登壇資料
https://fortee.jp/iosdc-japan-2018/proposal/f21bf617-3e9c-4ec0-833c-bc8dbb6965e5

(プロポーザルより)
マイクロインタラクションとは、ユーザーが操作した際に表示される、ちょっとしたアニメーションやフィードバックなどのアクションのことです。
Facebookなどのアプリで積極的に採用されており、自分のアプリにも入れてみたい、という方に向けて、マイクロインタラクションの使いどころや実装例を紹介します。

kiwi

September 02, 2018
Tweet

More Decks by kiwi

Other Decks in Technology

Transcript

  1. Ϧονͳදݱ͕Ͱ͖Δ ૂ͑ΔޮՌ • ϫΫϫΫײ • ੈք؍ͷදݱ ࢖͍Ͳ͜Ζ • ήʔϜͳͲੈք؍͕ڧ͍ΞϓϦ •

    ΢ΥʔΫεϧʔը໘ 5PLZP %JTOFZ3FTPSU"QQ ΢ΥʔΫεϧʔը໘ ىಈ࣌ͷζʔϜͷಈ͖
  2. ΞχϝʔγϣϯΛ࡞ͬͯΈΔr ΆΑΜͱ͢ΔϘλϯ • ඵ਺ͱΞχϝʔγϣϯऴྃޙͷঢ়ଶʢΫϩʔδϟʣΛࢦఆ͢Δͱɺ ͦͷؒΛࣗಈͰิؒͯ͠Ξχϝʔγϣϯͯ͘͠ΕΔ • ࢦఆͰ͖Δ಺༰͸6*7JFXͷϓϩύςΟ • GSBNF΍CPVOETɺഎܠ৭ɺಁ໌౓ •

    USBOTGPSN ճస ֦େॖখ  %BZ-5!5SBDL# • ஗Εඵ਺΍ΠʔζΠϯΞ΢τɺऴྃޙͷॲཧͷࢦఆ͕Մೳͳ೿ੜܕ΋ • ऴྃॲཧͰผͷΞχϝʔγϣϯΛೖΕΔ͜ͱͰɺ࿈ଓͨ͠Ξχϝʔ γϣϯ͕Մೳ UIView.animate(withDuration:animations:)
  3. ΞχϝʔγϣϯΛ࡞ͬͯΈΔr ΆΑΜͱ͢ΔϘλϯ UIView.animate(withDuration:animations:) imageView.bounds.size = CGSize(width: 36, height: 36) UIView.animate(

    withDuration: 0.3, // 秒数 delay: 0, // 0秒後に開始 options: .curveEaseIn, // オプション(カーブ, リピート等) animations: { self.imageView.bounds.size = CGSize(width: 44, height: 44) }, completion: nil)
  4. ΞχϝʔγϣϯΛ࡞ͬͯΈΔr ΆΑΜͱ͢ΔϘλϯ imageView.bounds.size = CGSize(width: 36*0.7, height: 36*0.7) UIView.animate( withDuration:

    0.4, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: .curveEaseInOut, animations: { self.imageView.bounds.size = CGSize(width: 36, height: 36) }, completion: nil)
  5. ΞχϝʔγϣϯΛ࡞ͬͯΈΔr ΆΑΜͱ͢ΔϘλϯ imageView.bounds.size = CGSize(width: 36*0.7, height: 36*0.7) UIView.animate( withDuration:

    0.4, delay: 0.0, usingSpringWithDamping: 0.5, // バネの振幅 initialSpringVelocity: 0.0, // バネの初速 options: .curveEaseInOut, animations: { self.imageView.bounds.size = CGSize(width: 36, height: 36) }, completion: nil)
  6. ΞχϝʔγϣϯΛ࡞ͬͯΈΔ ը໘ભҠ • ը໘ؒͰͲΜͳભҠΛ͢Δ͔Λදͨ͢Ίͷϓϩτίϧ • VTJOHͰ౉͞ΕΔ 6*7JFX$POUSPMMFS$POUFYU5SBOTJUJPOJOHܕͷҾ਺ ͔Βɺલޙͷ7JFX$POUSPMMFS΍7JFX͕औಘՄೳ UIViewControllerAnimatedTransitioning プロトコル

    animateTransition(using:) メソッド func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let containerView = transitionContext.containerView // アニメーション中のcontainer let fromView = transitionContext.view(forKey: .from)! // 今まで表示していたview let toView = transitionContext.view(forKey: .to)! // これから表示するview ...
  7. ΞχϝʔγϣϯΛ࡞ͬͯΈΔ ը໘ભҠ • USBOTJUJPO$POUFYUDPOUBJOFS7JFX͕Ξχϝʔγϣϯͷؒදࣔ͞ΕΔ • ભҠޙͷ7JFX΍Ξχϝʔγϣϯதʹදࣔ͢Δ7JFXΛDPOUBJOFS7JFXʹ BEE4VCWJFX͠ɺΞχϝʔγϣϯͤ͞Δ • ࠓճ͸ɺભҠઐ༻ͷ*NBHF7JFXΛDPOUBJOFSʹ௥Ճ͠ɺ ϦετͷҐஔ͔Βৄࡉը໘ͰͷҐஔ·Ͱಈ͔͢ͱ͍͏ํ਑

    • ৄࡉΛεέϧτϯදࣔ͠ɺͦͷதͰॳظҐஔ͔Βಈ͔͢ํ๏΋͋Δ • Ξχϝʔγϣϯ͕ऴΘͬͨΒ DPOUFYUDPNQMFUF5SBOTJUJPO USVF UIViewControllerAnimatedTransitioning プロトコル animateTransition(using:) メソッド
  8. ࣮૷ྫ   func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { presenting =

    operation == UINavigationControllerOperation.push // containerView, fromView, toView を取得 let containerView = transitionContext.containerView let fromView = transitionContext.view(forKey: .from)! let toView = transitionContext.view(forKey: .to)! // 詳細画面側のViewを取得し、アニメーション中は非表示にする let detailView = presenting ? toView : fromView toView.alpha = 0 // 詳細画面のImageViewの位置, 遷移用ImageViewの初期位置と最終位置 let detailFrame = CGRect(x: 0, y: 64, width: detailView.frame.width, height: detailView.frame.width)
  9. ࣮૷ྫ   // 詳細画面のImageViewの位置, 遷移用ImageViewの初期位置と最終位置 let detailFrame = CGRect(x:

    0, y: 64, width: detailView.frame.width, height: detailView.frame.width) let initialFrame = presenting ? originFrame : detailFrame let finalFrame = presenting ? detailFrame : originFrame // 遷移中のみ表示させるImageView let transitionImageView = UIImageView(frame: initialFrame) transitionImageView.image = listImageView.image transitionImageView.contentMode = .scaleAspectFill transitionImageView.clipsToBounds = true containerView.addSubview(toView) containerView.addSubview(transitionImageView) containerView.bringSubview(toFront: transitionImageView)
  10. ࣮૷ྫ   // 最初の0.2秒で遷移元の画面を非表示にする // containerViewに追加しているImageViewだけが表示される UIView.animate(withDuration: duration/5, animations:

    { fromView.alpha = 0 }) // 0.2秒後からEaseInOutでImageViewの位置を移動 // 合わせて、一覧に戻る遷移の場合は一覧画面を徐々に表示 UIView.animate(withDuration: duration*4/5, delay: duration/5, options: [.curveEaseInOut], animations: { transitionImageView.frame = finalFrame if !self.presenting { toView.alpha = 1 } }, completion: { _ in // 非表示にした詳細画面を表示
  11. ࣮૷ྫ   if !self.presenting { toView.alpha = 1 }

    }, completion: { _ in // 非表示にした詳細画面を表示 // 遷移中に表示していたimageViewを削除 if self.presenting { detailView.alpha = 1 } else { self.dismissCompletion?() } transitionImageView.removeFromSuperview() transitionContext.completeTransition(true) }) }
  12. ͓·͚6*7JFX1SPQFSUZ"OJNBUPS ʹ͍ͭͯ $PSF"OJNBUJPO $"-BZFSͰͷΞχϝʔγϣϯ 6*7JFX $"-BZFSΛ಺෦ʹ͍࣋ͬͯΔ 6*7JFX1SPQFSUZ"OJNBUPS J04ʙ ͍Ζ͍ΖઃఆͰ͖Δ΍ͭ ಺෦ͰݺΜͰΔ

    ಺෦ͰݺΜͰΔʜʜͱࢥ͏ • ΞχϝʔγϣϯͷҰ࣌ఀࢭ΍ٯ࠶ੜ • ΠʔδϯάͷΧʔϒΛࣗ෼Ͱઃఆ • ಈతʹΞχϝʔγϣϯΛ௥Ճ %BZ !%
  13. ͍͞͝ʹ • ϚΠΫϩΠϯλϥΫγϣϯΛద੾ʹऔΓೖΕΔ͜ͱͰɺ ΞϓϦͷ࢖͍৺஍͕Α͘ͳΓɺϢʔβʔମݧ͕޲্͢Δ • ؤுͬͯεςοϓΞοϓ͍͖ͯ͠·͠ΐ͏ʂ ՝୊Λ ղܾͰ͖Δ εϜʔζʹ ՝୊ղܾ

    ࢖͍উख ՝୊ղܾ͕ շײʹͳΔ ࢖͍৺஍ ҆ఆͨ͠ಈ࡞ ը໘ͷߏ੒ཁૉ΍ ભҠͷ߹ཧԽ ಈ࡞ͷΧΫ͖ͭ ϚΠΫϩΠϯλϥΫγϣϯ
  14. ࢀߟࢿྉ • 6*7JFX "OJNBUJPO$PSF"OJNBUJPO • IUUQTEFWFMPQFSBQQMFDPNKQEPDVNFOUBUJPO7JFX1(@J1IPOF04QEG • IUUQTEFWFMPQFSBQQMFDPNKQEPDVNFOUBUJPO$PSF"OJNBUJPO@HVJEFQEG • IUUQTTUPSFSBZXFOEFSMJDIDPNQSPEVDUTJPTBOJNBUJPOTCZUVUPSJBMT

    • IUUQTRJJUBDPNIBDIJOPCVJUFNTEDDCB • 6*7JFX1SPQFSUZ"OJNBUPS • IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUBOJNBUJPO@BOE@IBQUJDT QSPQFSUZ@CBTFE@BOJNBUJPOT • IUUQTTQFBLFSEFDLDPNIFEKJSPHJOUSPEVDUJPOUP VJWJFXQSPQFSUZBOJNBUPS • IUUQTTQFBLFSEFDLDPNIFEKJSPHVJWJFXQSPQFSUZBOJNBUPSEFTIJYJBO TVSVSJUVUJOBBOJNFTJZPOCJBPYJBO