Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
LayoutManagerをつくろう
Search
consomme
March 10, 2017
Programming
2
3k
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
2.1k
Other Decks in Programming
See All in Programming
宅宅自以為的浪漫:跟 AI 一起為自己辦的研討會寫一個售票系統
eddie
0
510
Canon EOS R50 V と R5 Mark II 購入でみえてきた最近のデジイチ VR180 事情、そして VR180 静止画に活路を見出すまで
karad
0
130
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
110
dotfiles 式年遷宮 令和最新版
masawada
1
800
20251127_ぼっちのための懇親会対策会議
kokamoto01_metaps
2
450
認証・認可の基本を学ぼう前編
kouyuume
0
260
TerraformとStrands AgentsでAmazon Bedrock AgentCoreのSSO認証付きエージェントを量産しよう!
neruneruo
3
910
WebRTC、 綺麗に見るか滑らかに見るか
sublimer
1
190
Full-Cycle Reactivity in Angular: SignalStore mit Signal Forms und Resources
manfredsteyer
PRO
0
150
Microservices rules: What good looks like
cer
PRO
0
1.5k
GISエンジニアから見たLINKSデータ
nokonoko1203
0
170
Pythonではじめるオープンデータ分析〜書籍の紹介と書籍で紹介しきれなかった事例の紹介〜
welliving
1
290
Featured
See All Featured
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandezseo
1
1.3k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
63
35k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Building the Perfect Custom Keyboard
takai
1
660
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
72
Building Applications with DynamoDB
mza
96
6.8k
Making the Leap to Tech Lead
cromwellryan
135
9.7k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
340
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
87
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
0
2.2k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.2k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
320
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
͋Γ͕ͱ͏͍͟͝·ͨ͠