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
LayoutManagerをつくろう
Search
consomme
March 10, 2017
Programming
2
2.9k
LayoutManagerをつくろう
DroidKaigi 2017 にて発表した資料です。
consomme
March 10, 2017
Tweet
Share
More Decks by consomme
See All by consomme
Firebaseでゼロからアプリを作る / Make app from scratch with Firebase
consomme
3
2k
Other Decks in Programming
See All in Programming
受け取る人から提供する人になるということ
little_rubyist
0
230
Streams APIとTCPフロー制御 / Web Streams API and TCP flow control
tasshi
2
350
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.2k
macOS でできる リアルタイム動画像処理
biacco42
9
2.4k
『ドメイン駆動設計をはじめよう』のモデリングアプローチ
masuda220
PRO
8
530
シェーダーで魅せるMapLibreの動的ラスタータイル
satoshi7190
1
480
エンジニアとして関わる要件と仕様(公開用)
murabayashi
0
280
.NET のための通信フレームワーク MagicOnion 入門 / Introduction to MagicOnion
mayuki
1
1.4k
Generative AI Use Cases JP (略称:GenU)奮闘記
hideg
1
290
OSSで起業してもうすぐ10年 / Open Source Conference 2024 Shimane
furukawayasuto
0
100
Jakarta EE meets AI
ivargrimstad
0
510
ローコードSaaSのUXを向上させるためのTypeScript
taro28
1
610
Featured
See All Featured
Navigating Team Friction
lara
183
14k
Product Roadmaps are Hard
iamctodd
PRO
49
11k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
Teambox: Starting and Learning
jrom
133
8.8k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
126
18k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
Six Lessons from altMBA
skipperchong
27
3.5k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
44
2.2k
The Invisible Side of Design
smashingmag
298
50k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
Transcript
LayoutManagerΛͭ͘Ζ͏ consomme / DroidKaigi 2017
ࣗݾհ • ͜ΜͦΊ / ࢁ࡚ ਖ਼ (Tadashi Yamazaki) • ϐΫγϒגࣜձࣾɹAndroidΞϓϦΤϯδχΞ
• Twitter : @consomme72 • Github : consomme • FGO : 071,679,396 • Nintendo Switch : SW-3116-2713-1429
Do you know pixiv ?
pixiv http://www.pixiv.net
Do you know BOOTH ?
BOOTH https://booth.pm
pixivͷ͍ΖΜͳαʔϏε
ԬʹΦϑΟε͕Ͱ͖·ͨ͠
ؒืूத https://www.wantedly.com/companies/pixiv
ΞδΣϯμ 1. RecyclerViewͱLayoutManager 2. RecyclerViewͰView͕ஔ͞ΕΔ·Ͱ 3. LayoutManagerͷத 4. LayoutManagerΛͭͬͯ͘ΈΑ͏
ҙࣄ߲ • Support Library 25.2.0 લఏͷ͓Ͱ͢ • ࠓޙόʔδϣϯΞοϓͯ͠શવҧ͏࣮ʹมΘΔՄೳੑ େ͍ʹ͋Γ·͢ •
GoogleઌੜΛ৴͡Α • ͍Ζ͍Ζઆ໌͕ෆ͍ͯͨ͠Γؒҧ͍ͬͯΔՄೳੑ ͋Γ·͢ • RecyclerViewͷίʔυશ෦ݟΔͷͱ͔ແཧ
1. RecyclerViewͱLayoutManager
RecyclerView is Կ • A flexible view for providing a
limited window into a large data set. • ڊେͳσʔληοτΛݶΒΕͨྖҬʹฒΔͨΊͷ View • ListViewGridViewͰͰ͖ͳ͔ͬͨॲཧ͕Մೳ • σʔλͷछྨͰViewΛม͑Δͱ͔͕؆୯ • Ξχϝʔγϣϯͱ͔ࣗಈͰͬͯ͘ΕΔ • ͦͷ͔ΘΓࣗલͰ͍Ζ͍Ζ༻ҙ͠ͳ͍ͱ͍͚ͳ͍ • ۠Γઢͱ͔λοϓΠϕϯτͱ͔
LayoutManager is Կ • RecyclerViewʹ͓͍ͯɺࢠViewΛͲͷΑ͏ʹஔ͢Δ ͔Λܾఆ͢Δͷ • ࢠViewͷαΠζܭࢉɺฒํɺεΫϩʔϧʹΑΔView ͷϦαΠΫϧͳͲΛ੍ޚ͍ͯ͠Δ •
LayoutManagerΛมߋ͢ΕɺRecyclerViewAdapter ͷมߋΛ͢Δ͜ͱͳ͘ϨΠΞτͷมߋ͕Մೳ • ListViewGridViewͰෆՄೳ
Ұൠతͳ RecyclerView ͷ͍ํ RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new SampleRecyclerAdapter());
setLayoutManager(LayoutManager) 1/2 public void setLayoutManager(LayoutManager layout) { if (layout ==
mLayout) { return; } stopScroll(); if (mLayout != null) { if (mItemAnimator != null) { mItemAnimator.endAnimations(); } mLayout.removeAndRecycleAllViews(mRecycler); mLayout.removeAndRecycleScrapInt(mRecycler); mRecycler.clear(); if (mIsAttached) { mLayout.dispatchDetachedFromWindow(this, mRecycler); } mLayout.setRecyclerView(null); mLayout = null; } else { mRecycler.clear(); } εΫϩʔϧΛࢭΊΔ ΞχϝʔγϣϯΛࢭΊΔ ࢠ7JFXΛͯ͢ফ͢ EFUBDI͢Δ
setLayoutManager(LayoutManager) 2/2 mChildHelper.removeAllViewsUnfiltered(); mLayout = layout; if (layout != null)
{ if (layout.mRecyclerView != null) { throw new IllegalArgumentException("LayoutManager " + layout + " is already attached to a RecyclerView: " + layout.mRecyclerView); } mLayout.setRecyclerView(this); if (mIsAttached) { mLayout.dispatchAttachedToWindow(this); } } mRecycler.updateViewCacheSize(); requestLayout(); } -BZPVU.BOBHFSʹ 3FDZDMFS7JFXΛηοτ 3FDZDMFS7JFXʹ -BZPVU.BOBHFSΛηοτ ϨΠΞτΛ࠶ඳը
AdapterͱRecycler • RecyclerView.Adapter • ࢠViewͷσʔλͷඥ͚Λߦ͏Ϋϥε • σʔλͷछྨʹΑͬͯViewHolderΛ͍͚ͯෳ ͷViewΛ͍͚Δ͜ͱ͕Մೳ • RecyclerView.Recycler
• ඇදࣔͱͳͬͨViewΛ࠶ར༻͢ΔͨΊʹอ͍࣋ͯ͠ ΔΫϥε
2. RecyclerViewͰView͕ஔ͞ΕΔ·Ͱ
RecyclerView extends ViewGroup • RecyclerViewViewGroupͷαϒΫϥεͳͷͰɺඳը ॲཧͷํ๏جຊతʹҰൠతͳViewͱಉ͡ • onMeasure ͰࢠViewͷαΠζΛܾఆ •
onLayout ͰࢠViewΛฒΔ
RecyclerViewʹ͓͚ΔࢠViewͷαΠζଌఆ • Support Library 23.2.0 ΑΓɺRecyclerViewʹ WRAP_CONTENT ͕͑ΔΑ͏ʹͳͬͨ • WRAP_CONTENT
Λ͏ʹɺLayoutManagerଆͰ setAutoMeasuredEnabled(true) Λࢦఆ͢Δඞཁ͋Γ • ٯʹݴ͑ɺ͜Ε͕trueʹͳ͍ͬͯͳ͍߹ WRAP_CONTENT ͑ͳ͍ʢϨΠΞτ่͕Ε Δʣ
setAutoMeasureEnabled ͷʑ͍͠આ໌ https://developer.android.com/reference/android/support/v7/widget/RecyclerView.LayoutManager.html#setAutoMeasureEnabled(boolean)
setAutoMeasureEnabled ͷ؆୯ͳઆ໌ • RecyclerViewLayoutManager͕ࣗಈͰViewͷαΠζΛܭࢉ͢Δ͔Ͳ ͏͔ΛܾΊΔ • trueΛηοτͨ͠߹ • ࣗಈͰViewͷαΠζܭࢉΛߦ͏ •
WRAP_CONTENT Λ༗ޮʹ͚ͨ͠Εtrueʹ͢Δ • falseΛηοτͨ͠߹ • ViewͷαΠζܭࢉ RecyclerView#onMeasure ʹॲཧΛॻ͘ • ॻ͔ͳ͍ͱView͕දࣔ͞Εͳ͍ • ΧελϚΠζͨ͠ܭࢉϩδοΫΛ͍͍ͨ߹ʹ͏ • σϑΥϧτfalseʹͳ͍ͬͯΔͷͰҙ
setAutoMeasureEnabled(true) ͷ߹ͷॲཧ 1/2 1. LayoutManager#onMeasure Λ࣮ߦ͠ɺRecyclerView ͷαΠζ͕ݻఆʢMATCH_PARENT or dpࢦఆʣͷ߹ ͦ͜Ͱऴྃ
2. αΠζ͕ܾ·͍ͬͯͳ͍߹ɺ LayoutManager#onLayoutChildren ʹͯࢠViewͷ heightͱwidthΛܭࢉ͢Δ
setAutoMeasureEnabled(true) ͷ߹ͷॲཧ 2/2 3. setMeasuredDimensionFromChildren Ͱɺ RecyclerViewͷmarginpaddingΛߟྀͯ͠width ͱheightΛܾఆ͢Δ LayoutManager#setMeasuredDimension Λoverride
ͯ͠ɺࣗಈܭࢉͱҧ͏Λઃఆ͢Δ͜ͱ͕Ͱ͖Δ 4. ܭࢉ͕ऴΘͬͨΒ RecyclerView#onLayout ͕ݺΕͯ View͕ஔ͞ΕΔ
3. LayoutManagerͷத
LayoutManagerͷओͳϝιου • abstractϝιου • generateDefaultLayoutParams • abstract͡Όͳ͍͚Ͳ࣮ඞਢͳϝιου • onLayoutChildren •
canScrollHorizontally / canScrollVertically • scrollHorizontallyBy / scrollVerticallyBy • ͦͷଞॏཁϝιου • scrollToPosition • smoothScrollToPosition
generateDefaultLayoutParams() • abstractϝιου • RecyclerViewͷࢠViewʹ͏LayoutParamsΛฦ͢ • RecyclerView.LayoutParams ͰجຊతʹOK • ΧελϜLayoutParamsΛ͏߹ɺҎԼͷϝιουΛ
override͢Δඞཁ͋Γ • checkLayoutParamsɿܕνΣοΫ • generateLayoutParamsɿϨΠΞτxml͔Βinflateͨ͠ ΓɺଞͷLayoutParamsΛίϐʔͨ͠Γ
onLayoutChildren(Recycler, State) • LayoutManagerͷ࠷ॏཁϝιου • ࢠViewͷஔɺεΫϩʔϧʹ͏ViewੜɺViewͷϦ αΠΫϧͳͲΛߦ͏ • ʮRecyclerViewͷྖҬʹʯදࣔ͢Δͯ͢ͷViewͷ ϨΠΞτॲཧΛߦ͏
• ྖҬ֎ͷͷʹ͍ͭͯScrollܥϝιουͰ
canScroll(Horizontally|Vertically)By • boolean canScrollHorizontallyBy() • boolean canScrollVerticallyBy() • ԣํʗॎํʹεΫϩʔϧͰ͖Δ͔Ͳ͏͔ •
ϨΠΞτํʹΑܾͬͯΊΔͱྑ͍
scroll(Horizontally|Vertically)By • int scrollHorizontallyBy(int, Recycler, State) • int scrollVerticallyBy(int, Recycler,
State) • ࢠViewΛԣʗॎʹҠಈ͢ΔྔΛฦ͢ • ৽͘͠ը໘ʹදࣔ͞ΕΔViewΛadd͢Δ • ը໘֎ʹফ͑ͨViewΛRecycle͢Δ
scrollToPosition(int) • RecyclerView#scrollToPosition ͷ࣌ʹݺΕΔ • positionΛηοτͯ͠ϨΠΞτͤ͠OK ※LinearLayoutMangerͷ࣮ @Override public void
scrollToPosition(int position) { mPendingScrollPosition = position; mPendingScrollPositionOffset = INVALID_OFFSET; if (mPendingSavedState != null) { mPendingSavedState.invalidateAnchor(); } requestLayout(); } QPTJUJPOΛηοτͯ͠ ࠶ϨΠΞτ
smoothScrollToPosition(RecyclerView, State, int) • RecyclerView#smoothScrollToPosition ͷ࣌ʹݺΕΔ • smooth scrollingΛαϙʔτ͍ͨ࣌͠ʹ࣮͢Δ •
RecyclerView.SmoothScroller ͷΠϯελϯεΛ࡞Γɺ startSmoothScroll ʹ͢ ※LinearLayoutMangerͷ࣮ @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()); linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); }
4. LayoutManagerΛͭͬͯ͘ΈΑ͏
खॱ 1. RecyclerView.LayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ 2. onDefaultLayoutParams Λ࣮͢Δ 3. onLayoutManager Λ࣮͢Δ 4.
ViewͷฒํΛม͑ͯΈΔ 5. εΫϩʔϧͰ͖ΔΑ͏ʹ͢Δ
Demo https://github.com/consomme/DroidKaigi2017Sample
·ͱΊ • දࣔ͢Δ͚ͩͳΒ࣮؆୯ • onLayoutChildren ͷ࣮Λ͢Ε͘͠ͳ͍ • ͔ͦ͜ΒઌΛ࣮͢Δͷ͕͍͠ • εΫϩʔϧͱ͔ɺͦΕʹ͏ViewͷϦαΠΫϧͱ͔ɺϓ
ϦϑΣονͱ͔ɺϓϦϩʔυͱ͔… • ͍͔ʹޮతʹදࣔ͢Δ͔Λಥ͖٧ΊΔͱׂͱপ • શ෦Λཧղ͢ΔͷແཧͳͷͰɺ෦తʹগͣͭ͠ཧղΛ ਐΊΔ΄͏͕͍͍ • RecyclerViewͷιʔείʔυ12,000ߦҎ্͋Γ·͢
ʲॏཁͳͷͰ̎ݴ͍·͢ʳؒืूத https://www.wantedly.com/companies/pixiv
͋Γ͕ͱ͏͍͟͝·ͨ͠