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
それっぽいカルーセルをつくる
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yoshihiro WADA
December 13, 2018
Programming
780
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
それっぽいカルーセルをつくる
2018/12/13に開催された Shibuya.apk #30 にて発表した資料です
Yoshihiro WADA
December 13, 2018
More Decks by Yoshihiro WADA
See All by Yoshihiro WADA
AndroidデバイスにFTPサーバを建立する
e10dokup
0
1.7k
Gradleの実行環境設定を見直す
e10dokup
0
1.4k
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
1
760
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.4k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
820
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
4.1k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
6k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3.7k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
330
Other Decks in Programming
See All in Programming
クラウドゲーミングのパフォーマンス最適化に挑む / Cloud Gaming Performance Tuning
vivion
0
320
AI駆動開発4年目の現在地(『あなたはFDEになるべきか?』イベント資料)
kumaiu
0
110
Railsバージョンを4倍にした話
optim
0
900
8年前のNode.jsを動かして分かった、npm installの裏側
keisukeikeda
0
120
baseline으로 마이그레이션, 리팩토링 안전하게 맡기기
fornewid
1
800
AI時代のTerminal環境を UNIX哲学で設計・運用する
yasunori0418
1
330
そのデザイントークン、Flutterでも同じ見た目になりますか?
nakamizu
0
230
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
500
Apple Intelligenceとオンデバイス時代の到来
yahir0
0
190
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.2k
Modernizing iOS Apps
seyfoyun
0
150
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
7.1k
Featured
See All Featured
Technical Leadership for Architectural Decision Making
baasie
3
620
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.6k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8.2k
Paper Plane (Part 1)
katiecoart
PRO
2
12k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Chasing Engaging Ingredients in Design
codingconduct
0
380
Designing for humans not robots
tammielis
254
26k
Everyday Curiosity
cassininazir
0
390
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
390
Paper Plane
katiecoart
PRO
5
54k
From π to Pie charts
rasagy
1
430
Transcript
それっぽいカルーセルを作る Cyber Agent Inc. Yoshihiro Wada a.k.a. @e10dokup 2018/12/13 Shibuya.apk
自己紹介 • Yoshihiro Wada a.k.a. @e10dokup • 大体右のアイコンで息をしています • CyberAgant
Inc. / Ameba • Amebaブログやってます • We’re Hiring • カメラ沼 • 財布の透過率が高いのが最近の悩み
今日のコンテンツ • カルーセルを作る • ループするしないとかするとかいろいろあるが… • 今回は画面横方向に面が並んだものと定義します • 正直EpoxyにCarouselItemってあるやん…? 2
1 3 4
特に… • 画面横幅いっぱいにコンテンツアイテムとかを出すスナップで行き来できるカルーセル • マージンがついたり • 触っていないときは隣の面が見えるように…とかだったり • 今回はRecyclerViewで実装していきます(ViewPager) •
本音:Groupieで雑にAdapterを作って管理したかった 2 1 3
やっていきましょう
レベル1 単純に画面いっぱいのカルーセル
どうということはない • RecyclerViewに対してlayout_widthがmatch_parentなItemのLayoutを用意する • Adapterにはそのレイアウトを渡してInflateさせる • SnapHelperにRecyclerViewを渡してスナップによるスクロールをさせるようにする
SnapHelper • RecyclerView.onFlingListenerを継承したAbstract class • フリングしたときに子Viewにスナップさせる • 継承クラスは2つ • LinearSnapHelper
• snap対象のViewがRecyclerViewの中心に来るようにスナップ • PagerSnapHelper • ViewPagerっぽい挙動のスナップ • SnapHelper#attachToRecyclerView(recyclerView)でアタッチ • nullを入れるとdetach。多重attachしないように気をつける
レイアウトを用意して <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="150dp" android:background="#EEEEEE"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" ɾɾɾ/>
</android.support.constraint.ConstraintLayout>
RecyclerViewにAdapterをセットする // container͕RecyclerViewͰ͢ adapter = RecyclerAdapter(list) // onDestroyͳΓͰdetach͢Δ snapHelper.attachToRecyclerView(container) container.setHasFixedSize(true)
container.layoutManager = LinearLayoutManager( this, LinearLayoutManager.HORIZONTAL, // ਫฏํͳͷͰ… false) container.adapter = adapter
レベル2 アイテム間にスペースを つけるカルーセル
Spaceを入れるItemDecorationをつけよう • getItemOffsetsをoverrideしたItemDecorationを用意する • 引数のoutRectのleft/rightを必要なspace分ずらす • 実装したItemDecorationをRecyclerViewにaddするだけ container.addItemDecoration(SpaceItemDecoration(SPACE_SIZE))
ItemDecorationの中はこんな感じ override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView,
state: RecyclerView.State) { outRect.set(0, 0, space, 0) // ඞཁͳϚʔδϯΛηοτ // outRect.right = space ͱ͔ͰOKɻͨͩ͠pxͳͷͰdp -> px͢Δ }
なんか左寄りなので真ん中にしたい override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView,
state: RecyclerView.State) { // ࠨӈۉʹϚʔδϯ͕ͨΔΑ͏ʹ͢Δ outRect.set(space / 2, 0, space / 2, 0) }
良さそう ちゃんと真ん中に寄ってる
レベル3 隣のアイテムが見えるカルーセル
やりたいことは… • 触っていないときは隣のアイテムが見えている状態にしたい • 画面幅に対して左右60dpずつマージンをとる • itemが並ぶ間隔はマージンの半分である30dpにする 2 3 1
60dp 30dp
変えないといけないこと • 元々がwidthがmatch_parentなので、このままではいくらItemDecorationでOffsetをつけて も隣のViewは同じようには見えない • OffsetでItemのサイズが変わるので無理やり一つ見えてもほかのサイズが変わったり… • アイテム自体を固定値に…できたら良かった • 世の中の端末すべてが横幅360dpではない
• 隣のアイテムが見える + アイテムが中央に来るは達成できるが… • 端末によっては中央にアイテムが来るように調整した結果 余白が大きくスカスカに見える • Eg. Nexus 5X -> 411dp、Essential PH-1 -> 431dp…
つまり… • match_parent時にしたときのitemのサイズを制限できればいい • ということは親が小さくなればいい • 親になるRecyclerView自体にPaddingを設定する
少し算数する • アイテム間のスペースが30dpの時、RecyclerViewのPaddingを60dpにして、かつ中央にア イテムが来るような値のとり方を考える • 前述の通り、アイテムの中央寄せの為に左右に同じスペースをとる • つまりアイテムの左右には15dpを与える • 最初のアイテムも左側には15dp持つことになるので、Paddingを安直に60dpにすると75dp
になる。ここは60dpで抑えたい • よってRecyclerView取るべきPaddingは60-15=45dp 2 3 1 60dp 30dp
少し算数する(一般化) • アイテム間のスペースがx[dp]の時、RecyclerViewのPaddingを2x[dp]にして、かつ中央に アイテムが来るような値のとり方を考える • 前述の通り、アイテムの中央寄せの為に左右に同じスペースをとる • つまりアイテムの左右には0.5x[dp]を与える • 最初のアイテムも左側には0.5x[dp]持つことになるので、Paddingを安直に2x[dp]にすると
2.5x[dp]になる。ここは2x[dp]で抑えたい • よってRecyclerViewが取るべきPaddingは2x-0.5x=1.5x[dp] • XML上に書いてもItemDecorationには反映されないのでこれをコードで定義する • SpaceItemDecorationを作る際に一緒にRecyclerViewを引数に渡してみる
いい感じにマージンを設定する fun from( recyclerView: RecyclerView, itemSpaceDp: Int ): SpaceItemDecoration {
val paddingPx = itemSpaceDp.toPx() // ͍͍ײ͡ʹdp -> pxม // RecyclerViewʹ༩͑Δpaddingʢ1.5x[dp]Λ༻ҙ͢Δʣ val edgePaddingPx = (paddingPx * 3 / 2).toInt() recyclerView.setPadding(edgePaddingPx, 0, edgePaddingPx, 0) return SpaceItemDecoration(paddingPx.toInt()) }
やったか…? 隣が見えていない (´・ω・`)
つまり… • match_parent時にしたときのitemのサイズを制限できればいい • ということは親が小さくなればいい • 親になるRecyclerView自体にPaddingを設定する • RecyclerView自体にPaddingをつけても隣は結局見えない
つまり… • match_parent時にしたときのitemのサイズを制限できればいい • ということは親が小さくなればいい • 親になるRecyclerView自体にPaddingを設定する • RecyclerView自体にPaddingをつけても隣は結局見えない •
clipToPaddingをfalseにすることで見えるようになる • デフォルトではPaddingによる余白の描画は切り取るようになっているがそれを表示する • paddingされたコンテンツの外側にあるものが見えるようになる
いい感じにマージンを設定する fun from( recyclerView: RecyclerView, itemSpaceDp: Int ): SpaceItemDecoration {
val paddingPx = itemSpaceDp.toPx() // ͍͍ײ͡ʹdp -> pxม // RecyclerViewʹ༩͑Δpaddingʢ1.5x[dp]Λ༻ҙ͢Δʣ val edgePaddingPx = (paddingPx * 3 / 2).toInt() recyclerView.setPadding(edgePaddingPx, 0, edgePaddingPx, 0) recyclerView.clipToPadding = false // ͜ΕͰྡ͕ݟ͑Δ return SpaceItemDecoration(paddingPx.toInt()) }
良さそう ちゃんと隣も見えていて 中央に寄ってる
まとめ • RecyclerViewでいろんなカルーセルを作る話でした • 結局作りたかったのは「隣のitemがちらっと見えるカルーセル」 • 今回は「画面幅に対するPaddingの半分の間隔でitemが並んでいる時」の話なので デザインで異なる場合はそれにあった算数が必要 • EpoxyのCarouselItemを使うと
setItemSpacingPx でアイテム間のスペースを 設定できるのでItemDecorationを書かなくてもなんとかなるのかな • 未検証です
ありがとうございました