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
iOS17のScrollViewはちょっとできる子
Search
toya108
September 06, 2024
22
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
iOS17のScrollViewはちょっとできる子
toya108
September 06, 2024
More Decks by toya108
See All by toya108
MaintainabilityIndexを 計測しながらコードの保守性を 改善している話
toya108
1
860
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
410
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
430
Visualization
eitanlees
152
17k
Abbi's Birthday
coloredviolet
2
8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
We Are The Robots
honzajavorek
0
240
Git: the NoSQL Database
bkeepers
PRO
432
67k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
Statistics for Hackers
jakevdp
799
230k
Six Lessons from altMBA
skipperchong
29
4.3k
Building Adaptive Systems
keathley
44
3k
Transcript
iOS17のScrollViewは ちょっとできる子 toya108 / Toya Niibori iOSDC Japan 2024 2024/08/23
TrackB
こんにちは 👋 • クックパッド 所属の • ボルダリング が好きな • 1児の父(もうすぐ
2児) として覚えてもらえると嬉しいです toya108 / Toya Niibori
リール風UI めっちゃ流行ってませんか?
リール風UIって何? 要するにTikTok なんらかのアルゴリズムで推薦される動画、 あるいは画像のコンテンツ上下にスワイプして閲覧 できるUI 気づいたらすぐに時間が溶けるやつ
流行りのこの UI 作ってみたくないですか?
iOS17のScrollViewなら 簡単にできます!
要件から考えてみる • 画面幅いっぱいにコンテンツを表示したい • スワイプでコンテンツを切り替えたい(snap scrollの 挙動にしたい) • どのページにスワイプしたか知りたい
iOS16以前 TabViewを90度、子View側を-90度回転させると実装できる これでもできなくはないが、縦にページングしたいだけなのにやってることが 難しすぎる。 TabView { ForEach(items) { item in
ItemView(item: item) } } .tabViewStyle(PageTabViewStyle()) .rotationEffect(.degrees(90))
https://developer.apple.com/videos/play/wwdc2023/10159
どうBeyondしたか 特に重要なのはTargets and positionsで追加された以下のmodifier達 • containerRelativeFrame(_:alignment:) • scrollTargetBehavior(_:) • scrollTargetLayout(isEnabled:)
• scrollPosition(id:anchor:) これらを使用することでリール風UIが楽に作成できる
ScrollView { LazyVStack { ForEach(items) { item in ItemView(item: item)
} } } .ignoresSafeArea() 子Viewのサイズを ScrollViewのコンテナサイズにしたい iOS16まではGeometryReaderなしで子Viewに対し 親Viewのサイズに依存したサイズを指定する術がなかった
ScrollView { LazyVStack(spacing: 0) { ForEach(items) { item in ItemView(item:
item) .containerRelativeFrame([.horizontal, .vertical]) } } } containerRelativeFrame(_:alignment:) GeometryReaderなしでコンテナのサイズを指定可能に👍 ※GeometryReaderの使用を否定したいわけではない。今回の要件ではより 簡単に使用できるcontainerRelativeFrame(_:alignment:)に軍杯が上がると思う。
Snap scrollの挙動にしたい iOS16までのScrollViewは連続的なスクロールしか できない。 pagingはTabViewの領分だった。
scrollTargetBehavior(_:) ScrollView { ... } .scrollTargetBehavior(.paging) pagingやviewAlignedなど、Viewのサイズや位置を 考慮したoffsetの計算が可能に👍
scrollTargetBehavior(_:) pagingはScrollView自体のサイズを 1ページとして計算する。 ScrollView自体のサイズとコンテンツ 1ページのサイズが等しくない場合は viewAlignedが適している。 ViewAligned Paging ScrollView {
... } .scrollTargetBehavior(.viewAligned(limitBehavior: .always))
scrollTargetLayout(isEnabled:) ScrollView { LazyVStack { ... } .scrollTargetLayout() } .scrollTargetBehavior(.viewAligned(limitBehavior:
.always)) viewAlignedを使う場合は基準となるViewを指定する必要がある。 .scrollTargetLayout(isEnabled:)で指定することができる。
ここまで紹介した 機能を使うとこうなる
どのページにスワイプしたか知りたい ページ番号の表示、ログ送信などの目的で どのページへ移動したか知りたくなる。 .onAppear()で最後に表示されたViewからページを計 算することもできるが、頑張りが必要。 1 2 3 4
@State var scrollPosition: Int? = 0 var body: some View
{ ScrollView { ... } .scrollPosition(id: $scrollPosition) } scrollPosition(id:anchor:) スクロールによって表示されるViewのIDをbindできる。
scrollPosition(id:anchor:) 逆にscrollPositionを上書きすることで指定したidのViewに 移動することも可能 💪 ForEach(Array(items.enumerated()), id: \.element.id) { index, item
in Button("\(index)") { withAnimation { scrollPosition = item.id } } }
できました 🎉🎉
まとめ iOS17のScrollViewなら • 子Viewでコンテナサイズを考慮したサイズを簡単に指定できる • paging、viewAlignedなスクロールが可能 • スクロールして表示されたViewのIDが分かる さらにID指定で特定のViewまでスクロールすることができる これらの機能を使用すればリール風UIも楽に作成可能
※注意: 先にiOS16のサポートを切らないといけない リールはUIを実装するより推薦するアルゴリズムを考える方がむずい
おまけ iOS18でもScrollViewは大幅にアップデートされてる。 来年iOSDCではこのトピックで CFP書きます!!