Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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
800
Better use of SwiftUI
tattn
0
510
Swift Concurrencyによる安全で快適な非同期処理
tattn
2
1.5k
iOSアプリの技術選択2022
tattn
7
4k
Widget Suggestions 対応と ヤフーの新OS対応
tattn
1
1.4k
WidgetKitで良い体験を作るには / Good experience with WidgetKit
tattn
2
2k
既存アプリにSwiftUIをどう組み込んでいくか
tattn
8
2.6k
iOS 14からのアプリ内課金
tattn
5
3.2k
iOS 14の位置情報系アップデート
tattn
0
23k
Other Decks in Technology
See All in Technology
GoCon2026 - Open Source, Open World
sanposhiho
3
3.1k
synctest時代のhttptest Go 1.27で変わるHTTPサーバテストの裏側 / go conference2026 synctest and httptest
budougumi0617
1
2.6k
KPIだけでは評価できないプロダクトが考えるべき Evalsという第二の評価系 / Beyond KPIs: Evals as a Second Evaluation Framework for Products #PdEConf
aki_iinuma
4
3.9k
omasushiというライブラリを作った
polidog
PRO
0
190
Sigmaで作る業務アプリ
kazushiro_honma
0
110
クロスボーダーM&AのValue Upを支えるプロダクト開発。日米チームのハブになったプロダクトエンジニアの実践 / Product Engineering Conference 2026
genda
0
110
AIオーケストレーションを活用した 開発ワークフローの設計と実践
bqnq
0
130
「図書館」という名前のままでいいのか -Code4Lib JAPANカンファレンス2026 アンカンファレンス報告- / Code4Lib JAPAN Conference 2026: Unconference Report
ykiyota
0
160
アプリログインとWeb認証基盤をつなぐ ASWebAuthenticationSession 作法
shimastripe
1
190
作品が生態系になった ─ Mini Tokyo 3D から世界へ
nagix
0
150
2026-09-10 【Snowflake World Tour Tokyo 2026】dbt Core と Snowflake で実現する多層的なデータガバナンス / Multi-Layered Data Governance Powered by dbt Core and Snowflake
civitaspo
0
310
HRC_Frontend_Conference_Fukuoka_2026.pdf
ts020
0
390
Featured
See All Featured
Bash Introduction
62gerente
615
220k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Designing for Timeless Needs
cassininazir
1
470
The agentic SEO stack - context over prompts
schlessera
0
920
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
820
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
520
Are puppies a ranking factor?
jonoalderson
2
3.9k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
820
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
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Λࢦͦ͏ʗ ʘʘ\\٩( 'ω' )و //ʗʗ ఏڙ͞Ε͍ͯΔΈΛར༻͢Δ͜ͱͰ ҙ֎ͱ؆୯ʹ࣮͢Δ͜ͱ͕ग़དྷ·ͨ͠