Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Swipe Transition
Search
Tatsuya Tanaka
January 24, 2018
Technology
1.9k
12
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Swipe Transition
#potatotips 47
https://github.com/tattn/SwipeTransition
Tatsuya Tanaka
January 24, 2018
More Decks by Tatsuya Tanaka
See All by Tatsuya Tanaka
iPhoneのセンサー情報をmacOSアプリでリアルタイム活用するための技術
tattn
1
780
Better use of SwiftUI
tattn
0
500
Swift Concurrencyによる安全で快適な非同期処理
tattn
2
1.4k
iOSアプリの技術選択2022
tattn
7
4k
Widget Suggestions 対応と ヤフーの新OS対応
tattn
1
1.4k
WidgetKitで良い体験を作るには / Good experience with WidgetKit
tattn
2
1.9k
既存アプリにSwiftUIをどう組み込んでいくか
tattn
8
2.6k
iOS 14からのアプリ内課金
tattn
5
3.1k
iOS 14の位置情報系アップデート
tattn
0
22k
Other Decks in Technology
See All in Technology
論語・武士道・産業革命から見る かわるもの、かわらないもの
ichimichi
8
2.1k
システム監視入門
grimoh
5
800
もう一度考える SRE チームの作り方・育て方 / Rethinking SRE #1: Building and Growing SRE Teams
rrreeeyyy
5
850
【Google Cloud Next Tokyo'26】Gemini Enterprise と Oracle AI Database で実現する、業務データ活用を実現する AI エージェント実装
shisyu_gaku
0
170
NetBoxを利用した作業効率化の試み_NetDevNight4
tnoha
0
430
LangfuseによるLLMOps基盤の構築と活用事例
zozotech
PRO
1
250
脱Jenkins、インターン生が挑んだCIツールGitHubActions移行
mixi_engineers
PRO
1
310
VPCセキュリティ対応の最新事情
nagisa53
2
360
AIQAのナレッジ構築について
qatonchan
1
140
20260722_品質と開発生産性の相互作用
magicpod
0
110
AIがAPIを書く時代に、私たちは何を設計すべきか
nagix
0
200
変化の早いClaude Codeを 書籍に落とし込む
oikon48
4
510
Featured
See All Featured
Designing for humans not robots
tammielis
254
26k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
370
Bash Introduction
62gerente
615
220k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
280
How to Think Like a Performance Engineer
csswizardry
28
2.7k
A Soul's Torment
seathinner
6
3.1k
Into the Great Unknown - MozCon
thekraken
41
2.6k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.2k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
240
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
620
HDC tutorial
michielstock
2
770
Transcript
Swipe Transition #potatotips 47 ాத ୡ (@tattn)
• Yahoo!Ҋ • iOSΞϓϦΤϯδχΞ • GitHub: @tattn • Qiita: @tattn
• Twitter: @tanakasan2525 ాத ୡ (@tattn)
Α͋͘Δ ศརͳεϫΠϓδΣενϟʔ Λ࣮ͯ͠Έ·ͨ͠
ͲͷҐஔͰ εϫΠϓόοΫͰ͖Δ
ը໘ͷͲ͜ͰࠨʹεϫΠϓͰ͖Δ ը໘(Τοδ)Ͱͳͯ͘OK
Sloppy Swiping ͱݺΕ͍ͯ·͢ɻ ͜ͷεϥΠυͰγϯϓϧʹ SwipeBackͱදه͠·͢ɻ
ԼεϫΠϓͰϞʔμϧΛด͡Δ
ԼʹεϫΠϓ͢ΔͱϞʔμϧͷը໘͕εϫΠϓͱͱʹҠಈ͠ɺ ͋ΔఔεΫϩʔϧ͢Δͱด͡Δ
͜ͷεϥΠυͰ SwipeToDismissͱදه͠·͢ɻ
࣮ͯ͠Έ·ͨ͠ͷͰɺ ͦͷ࣮ํ๏Λ͝հ͠·͢
࣮ํ๏
ࠓճͷओͳొਓ • UIPanGestureRecognizer • UIViewControllerAnimatedTransitioning • UIViewControllerTransitioningDelegate • UINavigationControllerDelegate
• UIPercentDrivenInteractiveTransition
UIPanGestureRecognizer ࢦͷҠಈྔͳͲΛऔಘͰ͖ΔΫϥεɻ ࠓճ͜ΕͰεϫΠϓΛݕग़͠·͢ɻ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUVJQBOHFTUVSFSFDPHOJ[FS
UIViewControllerAnimatedTransitioning ࣗ࡞ͷը໘ભҠΛ࣮Ͱ͖Δϓϩτίϧɻ SwipeBackͰViewΛӈʹҠಈɺ SwipeToDismissͰViewΛԼʹҠಈ ͢ΔͨΊʹ༻͠·͢ɻ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUVJWJFXDPOUSPMMFSBOJNBUFEUSBOTJUJPOJOH
UIViewControllerTransitioningDelegate present/dismiss࣌ʹ Ͳͷτϥϯδγϣϯ(UIViewControllerAnimatedTransitioning)Λ ར༻͢Δͷ͔Λࢦఆ͢Δϓϩτίϧɻ SwipeToDismissͰࣗ࡞ͷը໘ભҠΛར༻͢ΔͨΊʹ ༻͠·͢ɻ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUVJWJFXDPOUSPMMFSUSBOTJUJPOJOHEFMFHBUF
UINavigationControllerDelegate UINavigationControllerͰൃੜ͢ΔΠϕϯτͷัଊ Ͳͷτϥϯδγϣϯ(UIViewControllerAnimatedTransitioning)Λ ར༻͢Δͷ͔Λࢦఆ͢Δϓϩτίϧɻ SwipeBackͰࣗ࡞ͷը໘ભҠΛར༻͢ΔͨΊʹ ༻͠·͢ɻ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUVJOBWJHBUJPODPOUSPMMFSEFMFHBUF
UIPercentDrivenInteractiveTransition ը໘ભҠͷิؒํ๏ͷࢦఆ ը໘ભҠ͕Կ%͍ྃͯ͠Δͷ͔ͳͲΛ ઃఆ͢ΔΫϥεɻ SwipeBackͱSwipeToDismissͰ Ͳ͜·ͰεϫΠϓͨ͠ͷ͔Λදݱ͢ΔͨΊʹ༻͠·͢ɻ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUVJQFSDFOUESJWFOJOUFSBDUJWFUSBOTJUJPO
(ൃද࣌ؒͷؔͰ) SwipeBackͷํΛհ͠·͢ɻ (SwipeToDismiss΄΅ಉ࣮͡Ͱग़དྷ·͢ɻ)
SwipeBackAnimator class SwipeBackAnimator: NSObject, UIViewControllerAnimatedTransitioning { func animateTransition(using transitionContext:
UIViewControllerContextTransitioning) { guard let to = transitionContext.viewController(forKey: .to), let from = transitionContext.viewController(forKey: .from) else { return } let containerView = transitionContext.containerView containerView.insertSubview(to.view, belowSubview: from.view) to.view.frame = containerView.frame ભҠݩͷviewͷԼʹભҠޙͷviewΛinsert͍ͯ͠·͢ɻ SwipeBack࣌ʹԼͷViewΛදࣔ͢ΔͨΊͰ͢ɻ
͜ͷ෦
SwipeBackAnimator // ύϥϥοΫεޮՌ to.view.transform.tx = -containerView.bounds.width * 0.3 UIView.animate(
withDuration: transitionDuration(using: transitionContext), delay: 0, options: .curveLinear, animations: { to.view.transform = .identity from.view.transform = CGAffineTransform(translationX: to.view.frame.width, y: 0) }, completion: { _ in from.view.transform = .identity transitionContext.completeTransition( !transitionContext.transitionWasCancelled ) }) ભҠޙͷviewʹύϥϥοΫεޮՌΛ͚ͭͭɺ ભҠલͷviewΛӈҠಈ
SwipeBackNavigationController class SwipeBackNavigationController: UINavigationController { private let animator =
SwipeBackAnimator() private var interactiveTransition: UIPercentDrivenInteractiveTransition! override func viewDidLoad() { super.viewDidLoad() delegate = self let panGesture = UIPanGestureRecognizer() panGesture.addTarget(self, action: #selector(handlePanGesture(_:))) panGesture.maximumNumberOfTouches = 1 view.addGestureRecognizer(panGesture) } viewʹUIPanGestureRecognizerͱ UINavigationControllerDelegateΛηοτ
SwipeBackNavigationController extension SwipeBackNavigationController: UINavigationControllerDelegate { public func navigationController(_ navigationController:
UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { return operation == .pop ? animator : nil } public func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return interactiveTransition } } ར༻͢Δࣗ࡞ͷτϥϯδγϣϯΛฦ͢ɻ (εϥΠυʹࡌͤΔͱਏ͍ݟͨͰ͕͢ɺ࣮͍ͯ͠Δͷ2ߦͰ͢)
SwipeBackNavigationController @objc private func handlePanGesture(_ recognizer: UIPanGestureRecognizer) { switch
recognizer.state { case .began: interactiveTransition = UIPercentDrivenInteractiveTransition() interactiveTransition.completionCurve = .linear popViewController(animated: true) case .changed: let translation = recognizer.translation(in: view) interactiveTransition.update(translation.x / view.bounds.width) case .ended: if recognizer.velocity(in: view).x > 0 { interactiveTransition.finish() interactiveTransition = nil } else { fallthrough } case .cancelled: interactiveTransition.cancel() interactiveTransition = nil default: break } } δΣενϟʔʹ߹Θͤͯঢ়ଶΛߋ৽
100ߦຬͨͳ͍ίʔυͰ γϯϓϧͳSwipeBackΛ࣮Ͱ͖·ͨ͠ɻ ࠓճͷ࣮ˣʹஔ͍ͯ͋Γ·͢ɻ https://github.com/tattn/SwipeTransitionExample
ϥΠϒϥϦԽ
͔ͤͬ͘ͳͷͰϥΠϒϥϦԽ͠·ͨ͠ https://github.com/tattn/SwipeTransition ScrollView͕͋ͬͯಈ࡞͢ΔΑ͏ʹͨ͠Γɺ Method SwizzlingͰશը໘ʹద༻͢Δػೳ͋Γ·͢ɻ SwipeTransition ͥͻɺ͓ࢼ͍ͩ͘͠͞ʂ
·ͱΊ
·ͱΊ ʘδΣενϟʔͰૉఢUXΛࢦͦ͏ʗ ʘʘ\\٩( 'ω' )و //ʗʗ ఏڙ͞Ε͍ͯΔΈΛར༻͢Δ͜ͱͰ ҙ֎ͱ؆୯ʹ࣮͢Δ͜ͱ͕ग़དྷ·ͨ͠