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
CollectionViewの 新しいレイアウトの作り方
Search
ry-itto
November 02, 2019
Programming
79
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
CollectionViewの 新しいレイアウトの作り方
ry-itto
November 02, 2019
More Decks by ry-itto
See All by ry-itto
決定版!?OSSアプリプロジェクトでのBeta版アプリ配布の方法「Xcode Cloud + TestFlight」
ryitto
0
410
CA.swift#14
ryitto
3
5.9k
swift-argument-parserで 簡単 CLI ツール作り
ryitto
1
170
Data Essentials in SwiftUI
ryitto
1
540
Composable Architecture
ryitto
0
810
Swift5.1 SwiftUI
ryitto
0
140
Other Decks in Programming
See All in Programming
関数型プログラミングのメリットって何だろう?
wanko_it
0
170
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
170
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
170
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
510
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
210
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
170
Creating Composable Callables in Contemporary C++
rollbear
0
200
【やさしく解説 設計編・中級 #6】良いアーキテクチャとは ~ 一本の登り道の、行き先 ~
panda728
PRO
0
150
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
5.8k
なぜ関数型プログラミングで「型」と「証明」が語られるのか #fp_matsuri
kajitack
3
800
Prismを使った型安全な暗号化_関数型まつり2026
_fhhmm
0
120
AIエージェントで 変わるAndroid開発環境
takahirom
2
570
Featured
See All Featured
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
180
Measuring & Analyzing Core Web Vitals
bluesmoon
9
880
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.5k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
How to train your dragon (web standard)
notwaldorf
97
6.7k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
We Have a Design System, Now What?
morganepeng
55
8.2k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
WENDY [Excerpt]
tessaabrams
11
38k
Transcript
CollectionViewͷ ৽͍͠ϨΠΞτͷ࡞Γํ ձେֶֶ෦3ɹҏ౻྇
ࣗݾհ • ҏ౻྇ • ΧϐόϥѪ • iOSΤϯδχΞ • ͚ͭ໙େ͖
CollectionViewͱʁ “UICollectionView is a flexible, powerful tool to help you
achieve great user experiences in your applications.” –WWDC2018 A Tour of UICollectionView https://developer.apple.com/videos/play/wwdc2018/225/
͜Μͳը໘Λදݱ͢ΔͨΊʹ͏
iOS13Ͱ৽͘͠Ճ͞Εͨ CollectionViewपΓͷAPI • Compositional Layouts • DiffableDataSource
iOS13Ͱ৽͘͠Ճ͞Εͨ CollectionViewपΓͷAPI • Compositional Layouts • DiffableDataSource
Compositional Layouts • Item • Group • Section • Layout
ͷ4߲ͰCollectionViewͷϨΠΞτΛߏ͢Δ 88%$"EWBODFTJO$PMMFDUJPO7JFX-BZPVU TMJEF ˞ ˞ IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED
Compositional Layoutsͷ ੜ·Εͨཧ༝ʢલஔ͖ʣ • ࡢࠓͷΞϓϦͷUIෳࡶʹͳ͖͍ͬͯͯΔ • ैདྷͷFlowLayoutΛͬͨϨΠΞτߏͩͱ ͔ͳΓෳࡶͳίʔυʹͳͬͯ͠·͏ • ύϑΥʔϚϯε໘Λߟ͑ͳ͕ΒUIΛߏ͢Δඞཁ
͕͋ͬͨ
Compositional Layoutsͷ ࡾຊͷப • ComposableʢߏՄೳʣ γϯϓϧͳίʔυͰෳࡶͳUI͕࡞ΕΔ • Flexibleʢॊೈʣ ෳࡶͳUI͕࡞ΕΔ •
Fastʢૣ͍ʣ ύϑΥʔϚϯεʹྀ͠ͳͯ͘ྑ͍
σϞ, ίʔυ
αϯϓϧΞϓϦ ηΫγϣϯ͕ෳ͋ͬ ͯͦΕͧΕͷηΫγϣ ϯ͕10ݸ΄ͲͷཁૉΛ ͍࣋ͬͯΔ εΫϩʔϧ͢Δ
ैདྷͷFlowLayout Λ༻ͨ͠߹
࣮ํ େݩͷ $PMMFDUJPO7JFX ʢ5BCMF7JFXͰՄʣ େݩͷ $PMMFDUJPO7JFXͷηϧ ࢠͷ$PMMFDUJPO7JFX ࢠͷ$PMMFDUJPO7JFXͷηϧ
େݩͷCollectionView class LegacyViewController: UIViewController { func configureHierarchy() { collectionView.register(CollectionCell.self, forCellWithReuseIdentifier:
CollectionCell.reuseIdentifier) ɹɹɹ collectionView.collectionViewLayout = createLayout() } func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: view.bounds.width, height: view.bounds.height * 0.3) return layout } } extension LegacyViewController: UICollectionViewDataSource { } ηϧΛొɾϨΠΞτΛηοτ
ࢠͷCollectionView class SectionCollectionView: UICollectionView { override init(frame: CGRect, collectionViewLayout layout:
UICollectionViewLayout) { super.init(frame: frame, collectionViewLayout: layout) self.collectionViewLayout = createLayout() self.register(TextCell.self, forCellWithReuseIdentifier: TextCell.reuseIdentifier) self.contentInset = .init(top: 20, left: 20, bottom: 20, right: 20) } func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontalɹ/// εΫϩʔϧͷ͖Λԣ͖ʹ͢Δ layout.itemSize = CGSize(width: self.frame.width / 2, height: self.bounds.height - 40) return layout } } extension SectionCollectionView: UICollectionViewDataSource { }
େݩͷCollectionViewͷηϧ class CollectionCell: UICollectionViewCell { static let reuseIdentifier = "collectionCell"
var collectionView: SectionCollectionView! override init(frame: CGRect) { super.init(frame: frame) configure() } func configure() { self.collectionView = SectionCollectionView(frame: self.bounds, collectionViewLayout: .init()) contentView.addSubview(collectionView) collectionView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ collectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), collectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), collectionView.topAnchor.constraint(equalTo: contentView.topAnchor), collectionView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) ]) self.collectionView.backgroundColor = .white } } ηϧʹ$PMMFDUJPO7JFXΛηοτ
ࢠͷCollectionViewͷηϧ class TextCell: UICollectionViewCell { let label = UILabel() override
init(frame: CGRect) { super.init(frame: frame) configure() } } extension TextCell { func configure() { label.translatesAutoresizingMaskIntoConstraints = false label.adjustsFontForContentSizeCategory = true contentView.addSubview(label) label.font = UIFont.preferredFont(forTextStyle: .caption1) ... } }
ैདྷͷํ๏ͰαϯϓϧΞϓϦͷ UIΛ࡞͢ΔͨΊʹ ωετͨ͠CollectionView͕ඞཁ ίʔυ͕ଟ͘ͳΓɺ͔ͭߏ͕௫Έʹ͍͘
Compositional LayoutsΛ ༻ͨ͠߹
࣮ํ $PMMFDUJPO7JFX $PMMFDUJPO7JFXͷηϧ
CollectionView class ViewController: UIViewController { var collectionView: UICollectionView! override func
viewDidLoad() { super.viewDidLoad() configureHierarchy() } func configureHierarchy() { collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout()) collectionView.register(TextCell.self, forCellWithReuseIdentifier: TextCell.reuseIdentifier) collectionView.dataSource = self view.addSubview(collectionView) } func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(0.3)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) section.orthogonalScrollingBehavior = .continuous let layout = UICollectionViewCompositionalLayout(section: section) return layout } }
CollectionViewͷηϧ class TextCell: UICollectionViewCell { let label = UILabel() override
init(frame: CGRect) { super.init(frame: frame) configure() } } extension TextCell { func configure() { label.translatesAutoresizingMaskIntoConstraints = false label.adjustsFontForContentSizeCategory = true contentView.addSubview(label) label.font = UIFont.preferredFont(forTextStyle: .caption1) ... } }
Compositional Layouts Λ ༻͢Δ͜ͱͰ̍ͭͷCollectionView Ͱදݱ͢Δ͜ͱ͕Մೳʹͳͬͨ
·ͱΊ • Compositional LayoutsΛ͏͜ͱͰࠓ·Ͱ͔ͬͨ͠ UIͷදݱ͕؆୯ʹͰ͖Δ • ࠷ۙॳΊͯiOSΞϓϦ։ൃΛ࢝ΊͨͬͯਓʹΦεεϝ ※ iOS13Ҏ߱Ͱ͔͑͠ͳ͍ͷʹҙ
ࢀߟͳͲ • ࠓճͷαϯϓϧΞϓϦͷϦϙδτϦ https://github.com/ry-itto/CompositionalLayoutsSample • Advances in Collection View Layout(ηογϣϯ)
https://developer.apple.com/videos/play/wwdc2019/215/ • ࣌ͷมԽʹԠͯ͡ਐԽ͢ΔCollectionView ~Compositional LayoutsͱDiffable Data Sources~ https://qiita.com/shiz/items/a6032543a237bf2e1d19
͋Γ͕ͱ͏͍͟͝·ͨ͠