Slide 1

Slide 1 text

΋ͬͱFluidͰ RedirectableͳϞʔμϧ දࣔΞχϝʔγϣϯ @hirobe 2018.9.13

Slide 2

Slide 2 text

ࣗݾ঺հ ޿෦Ұ໻ ( twitter : @hirobe ) גࣜձࣾBunguu iOSΞϓϦɺMacOSΞϓϦͷ։ൃΛ΍ͬͯ·͢ ࠓճͷιʔείʔυ: https://github.com/hirobe/DismissFluidlySample

Slide 3

Slide 3 text

Designing Fluid Interfaces
 (WWDC 2018) • Fluid : ྲྀମͷɺͳΊΒ͔ͳ • ӳޠ೉͔͚ͬͨ͠Ͳɺࠓ͸ࣈນ͋Δ https://developer.apple.com/videos/play/wwdc2018/803/

Slide 4

Slide 4 text

What makes an interface feed fluid? • ͳΊΒ͔ͳΠϯλϑΣʔεͬͯͲΜͳͩΖ͏ʁ • ৮ͬͯͬ͘͠Γ͘Δ΋ͷ

Slide 5

Slide 5 text

A tool feels like an extension of your mind • ৺ ମͷԆ௕ͷΑ͏ʹײ͡ΒΕΔಓ۩ • iPhone͸௚઀खͰૢ࡞͢Δ΋ͷ • ͏·͘ಈ͚͹ਓؒͷExtensionͱͳΕΔ • ৮Δͷָ͕͘͠ͳΔ

Slide 6

Slide 6 text

಄ͷಇ͖ํʹΞϓϦͷ൓ԠΛ߹ΘͤΔ • ൓Ԡ଎౓͕େࣄ • ࢥߟͷํ޲స׵΍ׂΓࠐΈʹରԠ͠·͠ΐ͏ • 
ۭؒతҰ؏ੑΛอͬͨ഑ஔΛ͠Α͏ • Ϣʔβͷ༧ଌʹԊͬͨදݱΛ͠Α͏ • খ͞ͳλονૢ࡞Ͱେ͖ͳग़ྗΛ͠Α͏ • εΫϩʔϧͷڥքʹό΢ϯυΛ͚ͭΑ͏ • ΞχϝʔγϣϯͷνϥπΩΛ๷ࢭ͠Α͏

Slide 7

Slide 7 text

Redirectable • ࢥߟͷํ޲స׵΍ׂΓࠐΈʹଈԠ͠·͠ΐ͏
 ਓؒ͸ߟ͑ͳ͕Βը໘ૢ࡞͢Δ • δΣενϟதͷδΣενϟΛՄೳʹ͠Α͏

Slide 8

Slide 8 text

δΣενϟதͷδΣενϟ iPhoneX • ϗʔϜʹ໭Γͳ͕Β
 ϗʔϜը໘ΛԣεϫΠϓ

Slide 9

Slide 9 text

δΣενϟதͷδΣενϟ iPhoneX • ΞϓϦΛλοϓͯ͠
 ֦େதʹϗʔϜը໘ʹ໭Δ

Slide 10

Slide 10 text

δΣενϟதͷδΣενϟ iPhoneX • ΞϓϦΛىಈͯ͠
 ֦େதʹΞϓϦΛૢ࡞

Slide 11

Slide 11 text

ΞϓϦͰ࣮૷͍ͨ͠ʂ • Ͳ͜Ͱ࢖͑ΔͩΖ͏͔ʁ • ͦ͏͍͑͹ࢥ͍౰ͨΔ͜ͱ͕

Slide 12

Slide 12 text

ࣸਅΛλοϓ͢Δͱ֦େදࣔ͢ΔΞϓϦ

Slide 13

Slide 13 text

λον͕ແࢹ͞ΕΔ͜ͱ͕͋Δ • ࢠը໘Λดͨ͡ޙʹɺ ผͷը૾Λ։͖͍ͨ • ը૾ͷॖখΞχϝʔγϣ ϯ͕ऴΘΔલʹλοϓ͠ ͪΌͬͯΔʁʁ /P 3FTQPOTF

Slide 14

Slide 14 text

iPhoneXͷϗʔϜͷ৔߹

Slide 15

Slide 15 text

iPhoneXͷϗʔϜͷ৔߹ • ΞϓϦΛด͍ͯΔؒ΋ɺ
 λονΛͪΌΜͱड͚෇͚ͯ ͘ΕΔ -> Fluid!

Slide 16

Slide 16 text

ը໘Λด͡ΔભҠதʹ ผૢ࡞Λ ड͚෇͚ΔͷΛ ΞϓϦͰ࣮ݱ͢Δͧ

Slide 17

Slide 17 text

UIViewControllerAnimatedTransitioning • containerViewʹద౰ʹviewΛషΓ෇͚ͯ
 ը໘ભҠΞχϝʔγϣϯΛॻ͍͓ͯ͘ Ξχϝʔγϣϯ༻ͷ View containerView ਌ը໘

Slide 18

Slide 18 text

UIViewControllerAnimatedTransitioning • ç func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { if isForPresented { // present presentAnimation(transitionContext) } else { // dissmis dissmisAnimation(transitionContext) } } func dissmisAnimation(_ transitionContext: UIViewControllerContextTransitioning) { let containerView = transitionContext.containerView guard let nav = transitionContext.viewController(forKey: .from) as? UINavigationController, let detailVC:DetailViewController = nav.visibleViewController as? DetailViewController else { fatalError() }

Slide 19

Slide 19 text

UIViewControllerAnimatedTransitioning • ç let fromImageRect = detailVC.detailImageRect(containerView: containerView, safeAreaInsets: from?.view?.safeAreaInsets ?? .zero) let toImageRect = detailVC.parentImageViewRect // imageΛҠಈ͢ΔͨΊͷviewΛ࡞੒ let imageView:UIImageView = UIImageView(frame: fromImageRect) imageView.contentMode = .scaleAspectFill imageView.clipsToBounds = true imageView.image = detailVC.parentImage containerView.addSubview(imageView) // ॖখΞχϝʔγϣϯ nav.view.isHidden = true UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: [.curveEaseInOut], animations: { () -> Void in imageView.frame = toImageRect }) { (finished) -> Void in nav.view.removeFromSuperview() transitionContext.completeTransition(true) } }

Slide 20

Slide 20 text

ࢦΛ཭ͨ͠ޙͷΞχϝʔγϣϯ • UIViewControllerTransitionDelegate,
 UIViewControllerAnimatedTransitioningΛ࣮૷ • ։࣌͘ʹtransitionDelegateʹηοτ override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { : let storyboard = UIStoryboard(name: "Main", bundle: nil) guard let vc = storyboard.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController else { return } let nav = UINavigationController(rootViewController: vc) nav.isNavigationBarHidden = true nav.modalPresentationStyle = .custom nav.transitioningDelegate = vc.modalTransition self.present(nav, animated: true) }

Slide 21

Slide 21 text

• dismiss(animated: true)ͰΞχϝʔγϣϯΛ։࢝ • λον΍δΣενϟ͕ແࢹ͞ΕΔ εϫΠϓɺϘλϯૢ࡞ ࢦΛ཭ͨ͠:dismiss(animated: true) ด͡ΔΞχϝʔγϣϯ UIViewController AnimatedTransitioning UIViewControllerAnimatedTransitioning

Slide 22

Slide 22 text

UIAnimatedTransitioningΛ࢖Θͳ͍ ->ࢦΛ཭ͨ͠ޙ͸ɺભҠઌ͕Ξχϝʔγϣϯ εϫΠϓɺϘλϯૢ࡞ ࢦΛ཭ͨ͠: dismiss(animated: false) ࢠViewCotroller ด͡ΔΞχϝʔγϣϯ ʢ৮ΕΔʣ ਌ViewCotroller

Slide 23

Slide 23 text

λοϓ͕ແࢹ͞Εͳ͘ͳͬͨ • Ͱ͖ͨʂ

Slide 24

Slide 24 text

͚ͩͲɺɺ

Slide 25

Slide 25 text

FatͳViewControllerʹͳΔ ΑͶ →ͳΜͱ͔͍ͨ͠ ͚ͩͲɺɺ

Slide 26

Slide 26 text

UIViewControllerAnimatedTransitioningΛ ྲྀ༻͠Α͏ class DetailModalTransition : NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { if isForPresented { // present // : } else { // dissmis self.dissmisAnimation( containerView: transitionContext.containerView, from: transitionContext.viewController(forKey: .from), to: transitionContext.viewController(forKey: .to), duration: self.transitionDuration(using: transitionContext), completeTransition: transitionContext.completeTransition) } } func dissmisAnimation(containerView: UIView, from: UIViewController?, to: UIViewController?, duration: TimeInterval, completeTransition: @escaping (_ didComplete: Bool) -> Void) { // ΞχϝʔγϣϯΛॻ͘ } }

Slide 27

Slide 27 text

extension DetailModalTransition { func dissmisFluidly(viewController:UIViewController?) { guard let parent = viewController?.presentingViewController, let child = parent.presentedViewController, let window = parent.view?.window else { return } viewController?.dismiss(animated: false) { // viewDidDisappearͷޙʹݺ͹ΕΔͷͰ஫ҙ let containerView = UIView(frame: window.bounds) containerView.isUserInteractionEnabled = false window.addSubview(containerView) self.dissmisAnimation(containerView: containerView, from: child, to: parent, duration: 0.6, completeTransition: { didComplete in containerView.removeFromSuperview() }) } } } UIViewControllerAnimatedTransitioningΛ ྲྀ༻͠Α͏

Slide 28

Slide 28 text

·ͱΊ • ը໘ભҠΞχϝʔγϣϯதʹλονΛ༗ޮʹͨ͠ • ࢦΛ཭ͨ͠ޙ͸ɺભҠઌͷViewControllerͰॲཧ͢Δ • λον͕ແࢹ͞Εͳ͘ͳͬͨ • Fluidʹͳͬͨʂʂ • ΋͏ͪΐͬͱεϚʔτͳ΍Γํ͸ͳ͍΋ͷ͔ Github : https://github.com/hirobe/DismissFluidlySample