Save 37% off PRO during our Black Friday Sale! »

Cloning photos app fluid interface

Cloning photos app fluid interface

In WWDC 2018, apple human interface design team did a presentation about designing fluid interfaces.
This slide summarizes the important points in the session, and explains how to clone a fluid interface of iOS photos app.

WWDC2018でAppleのヒューマンインタフェースデザインチームが、fluidインタフェースのデザインについてプレゼンを行いました。
このスライドではそのセッションで述べられた重要なポイントをまとめ、iOSの写真アプリのfluidインタフェースをクローンした方法について説明します。

E2677c8861e7d02039ebb14e48dbd7be?s=128

Masamichi Ueta

November 15, 2018
Tweet

Transcript

  1. $MPOJOHQIPUPTBQQqVJEJOUFSGBDF .BTBNJDIJ6FUB 4PGUXBSF&OHJOFFSJ04BUNFSQBZ (JU)VC5XJUUFS!NBTBNJDIJVFUB .FSQBZ5FDI5BMLGPSJ04&OHJOFFS

  2. w 'MVJEJOUFSGBDFʹ͍ͭͯ w %FTJHOJOH'MVJE*OUFSGBDFT88%$ w 'MVJE*OUFSGBDFͷྫ w ࣸਅΞϓϦͷ'MVJE*OUFSGBDFΛΫϩʔϯͯ͠Έͨ

  3. ৴༻Λ૑଄ͯ͠ɺͳΊΒ͔ͳࣾձΛ૑Δɻ #VJMEJOHUSVTUGPSBTFBNMFTTTPDJFUZ

  4. J04͸ͲΜͲΜͳΊΒ͔ʹͳ͍ͬͯΔ w 'BDF*% w "QQMF1BZ w ύεϫʔυɺηΩϡϦςΟίʔυͷࣗಈೖྗ w J1IPOF9ͷδΣενϟʔ6*ʢϗʔϜʹ໭ΔɺΞϓϦ੾Γସ͑ʣ w

    FUD
  5. 7JEFP88%$%FTJHOJOH'MVJE*OUFSGBDFT

  6. %FTJHOJOH'MVJE*OUFSGBDFT88%$ w "QQMF)VNBO*OUFSGBDF%FTJHO5FBNͷϝϯόʔʹΑΔൃද w J1IPOF9ͷ'MVJE(FTUVSF*OUFSGBDFΛ࡞ͬͨࡍͷ஌ݟΛݴޠԽͯ͠ڞ༗

  7. ΠϯλϑΣʔεΛͳΊΒ͔ʹ͢Δʹ͸ʁ 8IBUNBLFTBOJOUFSGBDFGFFMqVJE w "UPPMUIBUGFFMTMJLF w BOFYUFOTJPOPGZPVSNJOE w BOFYUFOTJPOPGZPVSTFMG w BOFYUFOTJPOPGQIZTJDBMCPEZ

    ࣗ෼ͷ৺ମͷΑ͏ʹࣗ༝ʹײ͡Δ͜ͱ͕Ͱ͖Δ
  8. ৺ମΛ֦ு͢ΔΠϯλϑΣʔε *OUFSGBDFTUIBUFYUFOEPVSNJOET w ͙͢ʹ൓Ԡͯ͠ɺ͍ͭͰ΋໭ͬͨΓதஅͨ͠ΓͰ͖Δ *OTUBOUSFTQPOTFBOE DPOTUBOUSFEJSFDUJPOBOEJOUFSSVQUJPO

  9. -JOFBS*OUFSGBDFTͱ1BSBMMFM*OUFSGBDFT 5IPVHIU ߟ͑Δ %FDJTJPO ܾΊΔ (FTUVSF δΣενϟʔ 3FMFBTF ऴΘΔ 5IPVHIU

    ߟ͑Δ %FDJTJPO ܾΊΔ (FTUVSF δΣενϟʔ 3FMFBTF ऴΘΔ -JOFBS*OUFSGBDFT໭ͬͨΓதஅͨ͠ΓͰ͖ͳ͍ɺҙࢥܾఆͷޙʹδΣενϟʔ͕ى͜Δ 1BSBMMFM*OUFSGBDFT໭ͬͨΓதஅͨ͠ΓͰ͖Δɺҙࢥܾఆͱฒߦͯ͠δΣενϟʔ͕ى͜Δ
  10. ϗʔϜϘλϯͱJ1IPOF9ͷδΣενϟʔ

  11. 'MVJE*OUFSGBDFͷࣄྫ

  12. ϋʔϑϞʔμϧ .FTTBHF 5XJUUFS 'BDFCPPL 4MBDL

  13. None
  14. ϋʔϑϞʔμϧ w ϋʔϑϞʔμϧࣗମ͸'MVJE*OUFSGBDFͱ͍͏ΑΓ΋େܕԽʹ൐͏6*ͷมԽ ͩͱࢥ͍ͬͯΔ w SFTQPOTJWFͰSFEJSFDUBCMFͰJSSVQUBCMFͳδΣενϟʔͰૢ࡞Մೳ w εϫΠϓɾύϯɾλοϓ͝ͱͷ஄Έ NPNFOUVN Λ࢖ͬͨભҠ

  15. 4XJQFEVNQJOH 5BQEVNQJOH

  16. ࣸਅΞϓϦ w ζʔϜભҠ w ύϥϥοΫε w ԼʹҾͬுͬͯ໭Δ w ্ʹҾͬுͬͯৄࡉ w

    εϥΠμʔ
  17. 'MVJE1IPUP w IUUQTHJUIVCDPNNBTBNJDIJVFUB'MVJE1IPUP

  18. ζʔϜΠϯɾΞ΢τͷΠϯλϥΫγϣϯʹؔ͢ΔΫϥε class ZoomAnimator: UIViewControllerAnimatedTransitioning class ZoomDismissalInteractionController: UIViewControllerInteractiveTransitioning class ZoomTransitionController: UIViewControllerTransitioningDelegate,

    UINavigationControllerDelegate { let animator: ZoomAnimator let interactionController: ZoomDismissalInteractionController var isInteractive: Bool = false … }
  19. ζʔϜΞχϝʔγϣϯ લͷϑϨʔϜ ޙͷϑϨʔϜ

  20. ζʔϜΞχϝʔγϣϯ transitionImageView = UIImageView(image: referenceImage) transitionImageView.contentMode = .scaleAspectFill transitionImageView.clipsToBounds =

    true transitionImageView.frame = fromReferenceImageViewFrame containerView.addSubview(transitionImageView) … UIView.animate( withDuration: transitionDuration(using: transitionContext), delay: 0, options: [], animations: { … self.transitionImageView?.frame = finalSize … }, completion: { completed in … self.transitionImageView?.removeFromSuperview() … } )
  21. ԼʹҾͬுͬͯ໭Δ എܠ͕ಁ͚ͯ͘Δ ը૾ͷαΠζ͕খ͘͞ͳΔ ্ʹ཭͢ͱݩʹ໭Δ ͦͷ··཭͢ͱҰཡʹ໭Δ

  22. ԼʹҾͬுͬͯ໭Δ @objc func didPanWith(gestureRecognizer: UIPanGestureRecognizer) { switch gestureRecognizer.state { case

    .began: transitionController.isInteractive = true let _ = navigationController?.popViewController(animated: true) case .ended: if transitionController.isInteractive { transitionController.isInteractive = false transitionController.didPanWith(gestureRecognizer: gestureRecognizer) } default: if transitionController.isInteractive { transitionController.didPanWith(gestureRecognizer: gestureRecognizer) } } } 7JFX$POUSPMMFS
  23. func didPanWith(gestureRecognizer: UIPanGestureRecognizer) { … let verticalDelta = translatedPoint.y <

    0 ? 0 : translatedPoint.y let backgroundAlpha = backgroundAlphaFor(view: fromVC.view, withPanningVerticalDelta: verticalDelta) let scale = scaleFor(view: fromVC.view, withPanningVerticalDelta: verticalDelta) // update background alpha, scale, center … transitionContext.updateInteractiveTransition(1 - scale) if gestureRecognizer.state == .ended { let velocity = gestureRecognizer.velocity(in: fromVC.view) if velocity.y < 0 || center.y < anchorPoint.y { // cancel interactive transition … return } // start zoom out animation … } } ;PPN%JTNJTTBM*OUFSBDUJPO$POUSPMMFS
  24. None
  25. w 2JJUB w J04ͷࣸਅΞϓϦͷΑ͏ͳը໘ભҠͱΠϯλϥΫγϣϯΛ࣮૷͢Δ w .FEJVN w $SFBUFUSBOTJUJPOBOEJOUFSBDUJPOMJLFJ041IPUPTBQQ w (JU)VC

    w 'MVJE1IPUP w 88%$ w %FTJHOJOH'MVJE*OUFSGBDFT
  26. l0VSJOUFSGBDFTOFFEUPCFqVJECFDBVTFXFBSFqVJEz