$30 off During Our Annual Pro Sale. View Details »

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インタフェースをクローンした方法について説明します。

Masamichi Ueta

November 15, 2018
Tweet

More Decks by Masamichi Ueta

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  7. ΠϯλϑΣʔεΛͳΊΒ͔ʹ͢Δʹ͸ʁ
    8IBUNBLFTBOJOUFSGBDFGFFMqVJE
    w "UPPMUIBUGFFMTMJLF
    w BOFYUFOTJPOPGZPVSNJOE
    w BOFYUFOTJPOPGZPVSTFMG
    w BOFYUFOTJPOPGQIZTJDBMCPEZ
    ࣗ෼ͷ৺ମͷΑ͏ʹࣗ༝ʹײ͡Δ͜ͱ͕Ͱ͖Δ

    View Slide

  8. ৺ମΛ֦ு͢ΔΠϯλϑΣʔε
    *OUFSGBDFTUIBUFYUFOEPVSNJOET
    w ͙͢ʹ൓Ԡͯ͠ɺ͍ͭͰ΋໭ͬͨΓதஅͨ͠ΓͰ͖Δ
    *OTUBOUSFTQPOTFBOE
    DPOTUBOUSFEJSFDUJPOBOEJOUFSSVQUJPO

    View Slide

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

    View Slide

  10. ϗʔϜϘλϯͱJ1IPOF9ͷδΣενϟʔ

    View Slide

  11. 'MVJE*OUFSGBDFͷࣄྫ

    View Slide

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

    View Slide

  13. View Slide

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

    View Slide

  15. 4XJQFEVNQJOH
    5BQEVNQJOH

    View Slide

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

    View Slide

  17. 'MVJE1IPUP
    w IUUQTHJUIVCDPNNBTBNJDIJVFUB'MVJE1IPUP

    View Slide

  18. ζʔϜΠϯɾΞ΢τͷΠϯλϥΫγϣϯʹؔ͢ΔΫϥε
    class ZoomAnimator: UIViewControllerAnimatedTransitioning
    class ZoomDismissalInteractionController: UIViewControllerInteractiveTransitioning
    class ZoomTransitionController: UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
    let animator: ZoomAnimator
    let interactionController: ZoomDismissalInteractionController
    var isInteractive: Bool = false

    }

    View Slide

  19. ζʔϜΞχϝʔγϣϯ
    લͷϑϨʔϜ
    ޙͷϑϨʔϜ

    View Slide

  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()

    }
    )

    View Slide

  21. ԼʹҾͬுͬͯ໭Δ
    എܠ͕ಁ͚ͯ͘Δ
    ը૾ͷαΠζ͕খ͘͞ͳΔ
    ্ʹ཭͢ͱݩʹ໭Δ
    ͦͷ··཭͢ͱҰཡʹ໭Δ

    View Slide

  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

    View Slide

  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

    View Slide

  24. View Slide

  25. w 2JJUB
    w J04ͷࣸਅΞϓϦͷΑ͏ͳը໘ભҠͱΠϯλϥΫγϣϯΛ࣮૷͢Δ
    w .FEJVN
    w $SFBUFUSBOTJUJPOBOEJOUFSBDUJPOMJLFJ041IPUPTBQQ
    w (JU)VC
    w 'MVJE1IPUP
    w 88%$
    w %FTJHOJOH'MVJE*OUFSGBDFT

    View Slide

  26. l0VSJOUFSGBDFTOFFEUPCFqVJECFDBVTFXFBSFqVJEz

    View Slide