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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
consomme
March 10, 2017
Programming
3.1k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
LayoutManagerをつくろう
DroidKaigi 2017 にて発表した資料です。
consomme
March 10, 2017
More Decks by consomme
See All by consomme
Firebaseでゼロからアプリを作る / Make app from scratch with Firebase
consomme
3
2.2k
Other Decks in Programming
See All in Programming
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
17k
ITヒヤリハットを整理してみた ~ライフサイクルと原因から考える再発防止策~
koukimiura
1
120
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
280
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
750
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
340
Claude Team Plan導入・ガイド
tk3fftk
0
240
「正の参照」と 「負の導出」で組む ハーネスエンジニアリング
cottpan
1
150
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
1
260
信頼性について考えてみる(SRE NEXT 2026 miniLT)
hayama17
0
230
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
440
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
490
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
160
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.7k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
340
sira's awesome portfolio website redesign presentation
elsirapls
0
310
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
Utilizing Notion as your number one productivity tool
mfonobong
4
490
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.7k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.2k
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
͋Γ͕ͱ͏͍͟͝·ͨ͠