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
WebView+ViewGroupを実現するAOSPメールアプリの内部実装とニュースアプリ...
Search
ogapants
February 07, 2019
Technology
3.9k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
WebView+ViewGroupを実現するAOSPメールアプリの内部実装とニュースアプリへの応用 / DroidKaigi2019
https://droidkaigi.jp/2019/timetable/70923
ogapants
February 07, 2019
More Decks by ogapants
See All by ogapants
5分でわかるWebView+ViewGroupを実現するAOSPメールアプリの内部実装と ニュースアプリへの応用 / Otemachi.apk02
ogapants
0
770
ScrollViewで 読了計測した話
ogapants
0
870
「AndroidはiOSと同じデザインで!」と言われたときのTips
ogapants
17
8.5k
たのしいAndroidかいはつ
ogapants
0
180
Fabric Digitsで始めるSMS認証
ogapants
1
1.3k
MediaController をカスタマイズするぞ
ogapants
0
2.8k
Other Decks in Technology
See All in Technology
AWS Security Agent といっしょに脅威モデリングをやってみよう
amarelo_n24
1
210
アラート調査向けAIエージェントの本番導入とその後/AI Agents for Alert Investigation: Production Deployment and After
taddy_919
0
120
気軽に使える"情報のハブ"としてのNotion活用 〜フロー情報の集積点 と、 Claude Code × Notion AI〜
syucream
1
190
2026 AI Memory Architecture
nagatsu
0
170
AWS Security Hub CSPMの成功・失敗体験
cmusudakeisuke
0
540
WebGIS AI Agentの紹介
_shimizu
0
560
自宅LLMの話
jacopen
1
720
【FinOps】データドリブンな意思決定を目指して
z63d
0
330
技術・能力を向上する原理原則 #きのこセッションa #きのこ2026
bash0c7
0
120
iOS アプリの「これって不具合ですか?」を AI に調べてもらう
miichan
0
140
スタートアップにAmazon EKSは早すぎる? マルチプロダクト戦略を加速する Platform Engineeringの実践 / Is Amazon EKS Too Soon for Startups? Practical Platform Engineering to Accelerate a Multi-Product Strategy
elmodev09
1
1.8k
AIが自律的に回る開発ループを設計してチーム開発に組み込む
nekorush14
0
130
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
290
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
260
Being A Developer After 40
akosma
91
590k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
250
A better future with KSS
kneath
240
18k
Faster Mobile Websites
deanohume
310
32k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.7k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
540
Six Lessons from altMBA
skipperchong
29
4.3k
The Cult of Friendly URLs
andyhume
79
6.9k
Transcript
WebView+ViewGroupΛ࣮ݱ ͢ΔAOSPϝʔϧΞϓϦͷ෦ ࣮ͱχϡʔεΞϓϦͷԠ༻ 2019/02/08 DroidKaigi @ogapants
ࣗݾհ • ͓͕ͺΜ@ogapants • ຊܦࡁ৽ฉࣾ • ٕज़ॻయͰνʔϜվળͱAndroidStudioͷ Tipsʹ͍ͭͯॻ͖·ͨ͠ɻnoteͰݟΕ·͢ʂ https://goo.gl/AWv7v1
WebView+ViewGroupΛ࣮ݱ ͢ΔAOSPϝʔϧΞϓϦͷ෦ ࣮ͱχϡʔεΞϓϦͷԠ༻
͍͖ͳΓͰ͕͢ • ͜͏͍͏ߏͷը໘ɺͲ͏ͬͯ εΫϩʔϧͤ͞·͔͢ʁ TextView WebView Image View Text View
TextView
͍͖ͳΓͰ͕͢ • ScrollViewͰ ғͬͪΌ͍·ͤΜ͔ʁ TextView WebView Image View Text View
TextView ScrollView?
• ScrollViewͰWebViewΛғ͍͚ͬͯ·ͤΜ • ғ͏ͱͲ͏ͳΔͷʁ • ͡Ό͋Ͳ͏͢Ε͍͍ͷʁ
͜ͷൃදͰ͢͜ͱ • ͳͥScrollViewͰWebViewΛғ͏ͷ͕Α͘ͳ͍͔ • AOSPϝʔϧͰWebViewͲ͏ΘΕ͍ͯΔͷ͔ • Ͳ͏Ԡ༻ͨ͠ͷ͔
AOSPϝʔϧΞϓϦͱ
AOSPͱ • Android Open Source Project • ࣗ༝ʹӾཡɺ࠶ར༻͕Մೳ • OSपลͷใɺ։ൃπʔϧɺαϯϓϧΞϓϦͳͲఏڙ
• ϒϥβిɺΪϟϥϦʔΞϓϦͳͲ
AOSPϝʔϧΞϓϦͱ
AOSPϝʔϧΞϓϦͱ • AOSPʹ্͕ͬͯΔϝʔϧΞϓϦ • 2014͝Ζ·ͰҰ෦ͰϓϦΠϯετʔϧ • ࠓճϝʔϧৄࡉը໘ͷ • ·ͩΞοϓσʔτ͞Ε͍ͯΔ
AOSPϝʔϧΞϓϦϦϙδτϦ • ΞΧϯτपΓ https://android.googlesource.com/platform/packages/ apps/Email/ • ϝΠϯػೳ https://android.googlesource.com/platform/packages/ apps/UnifiedEmail/
AOSPϝʔϧΞϓϦϦϙδτϦ • ͲͪΒEclipseͷϑΝΠϧߏ • Γͳ͍ίϯϙʔωϯτଟ
ඇެࣜAOSPϝʔϧΞϓϦ • https://github.com/jinkg/YalinEmail • ඞཁͳίϯϙʔωϯτ܈ΛαϒϞδϡʔϧԽ͍ͯ͠Δ • AndroidStudioͰϏϧυͰ͖ΔΑ͏ʹͨ͠ඇެࣜΞϓϦ
[ิ]jinkg/YalinEmail modules • app... https://android.googlesource.com/platform/packages/apps/ Email/ • android-bitmap... https://android.googlesource.com/platform/ frameworks/opt/bitmap/
• android-chips... https://android.googlesource.com/platform/ frameworks/opt/chips/ • android-common... https://android.googlesource.com/platform/ frameworks/ex/+/master/common/
[ิ]jinkg/YalinEmail modules • android-emailcommon... https://android.googlesource.com/ platform/packages/apps/Email/+/master/emailcommon/ • android-photoviewer... https://android.googlesource.com/ platform/frameworks/opt/photoviewer/
• android-unifiedemail... https://android.googlesource.com/ platform/packages/apps/UnifiedEmail/
෦࣮Λ͏ܦҢ
͜Ε·Ͱͷݸผهࣄը໘ͷߏ TextView WebView Image View Text View TextView ScrollView ϔομʔViewGroupɿهࣄͷλΠτϧͳͲ
ίϯςϯπWebViewɿهࣄ༰ ϑολʔViewGroupɿؔ࿈هࣄͳͲ
࣮ࡍʹى͖ͨ
࣮ࡍʹى͖ͨᶃ • Ұ෦ͰසͰ هࣄ͕Εͯදࣔ͞ΕΔ • (WebViewͷΞοϓσʔτ ʹΑͬͯఆղܾ)
࣮ࡍʹى͖ͨᶄ • Ұ෦ͰසͰIllegalStateException >Unable to create layer for WebView •
(Ұ෦ͷϋʔυΣΞΞΫηϥϨʔγϣϯOFF Ͱఆղܾ)
࣮ࡍʹى͖ͨ • ͍ͣΕఆରԠͰ͔͠ͳ͍… • ߃ٱରԠ͘͢GoogleͷΤϯδχΞʹ࣭
࣮ࡍʹى͖ͨ • ScrollViewWebViewΛೖΕΔ͜ͱΛఆͯ͠ ࡞͍ͬͯͳ͍ʂ by GoogleΤϯδχΞ
ߟ͑ͨղܾࡦ
ߟ͑ͨղܾࡦ • WebViewΛΊΔ ˠશͯωΠςΟϒʹ͢Δɹ ˠ Өڹൣғ͕େ͖͘ࠔ
ߟ͑ͨղܾࡦ • WebViewͷΈʹ͢Δɹ ˠViewGroup෦ͷHTMLԽ ˠ ը໘ͷঢ়ଶ͕ଟ͘ࠔ
ߟ͑ͨղܾࡦ • AppBarLayoutͷΈΛར༻͢Δ ˠNestedScrollͰಈ͔͢ ˠ ٕज़తʹࠔ
ߟ͑ͨղܾࡦ • ϝʔϧΞϓϦΛࢀߟʹ͢Δ ˠ WebViewΛ͍ͬͯΔͣ ˠ AOSPΛݟΕ͍͚ͦ͏ʁ ˠ deep dive
ͪͳΈʹ • https://developer.android.com/reference/android/widget/ ScrollView • >Never add a RecyclerView or
ListView to a scroll view. • WebViewʹ͍ͭͯͷهࡌແ͠…
WebView+ViewGroupΛ ࣮ݱ͢ΔAOSPϝʔϧΞϓϦͷ ෦࣮
AOSPϝʔϧΞϓϦͰͷߏ • ֬ೝͨ͠όʔδϣϯ https://android.googlesource.com/platform/ packages/apps/UnifiedEmail/ ͷϦϏδϣϯ `1668ada` •
Ϗϧυڥjinkg/YalinEmail
AOSPϝʔϧΞϓϦͰͷߏ ϔομʔViewGroup ίϯςϯπWebView ϑολʔViewGroup
AOSPϝʔϧΞϓϦͰͷߏ WebView in ScrollView AOSPϝʔϧΞϓϦ WebView ViewGroup ScrollView ViewGroup WebView
ViewGroup ViewGroup
AOSPϝʔϧΞϓϦͰͷߏ • WebViewͰεΫϩʔϧͤ͞Δ • ViewGroup࿈ಈ • ViewGroupͷߴ͞cssͰpadding WebView ViewGroup ViewGroup
padding padding
ϝʔϧඳը·ͰͷྲྀΕ ᶃWebViewʹΦʔόʔϨΠ͍ͤͨ͞ViewGroupΛmeasure()ͯ͠ߴ͞ΛଌΔ ᶄςϯϓϨʔτͷhtmlʹcssͰpaddingΛ͚ͭΔ ᶅςϯϓϨʔτͷhtmlʹϝʔϧͷhtmlจࣈྻΛૠೖ ᶆ߹ͨ͠htmlจࣈྻΛWebViewͰඳը͢Δ ᶇpadding্ʹϔομʔɾϑολʔViewGroupΛlayout()Ͱஔ͢Δ
ϝʔϧඳը·ͰͷྲྀΕᶃ ᶃWebViewʹΦʔόʔϨΠ͍ͤͨ͞ViewGroupΛ ɹmeasure()ͯ͠ߴ͞ΛଌΔ ɹˠmeasure()…ViewͷαΠζΛܭଌ͢Δ ɹˠgetMeasuredHeight()Ͱऔಘ
ᶄςϯϓϨʔτͷhtmlʹcssͰpaddingΛ͚ͭΔ ϝʔϧඳը·ͰͷྲྀΕᶄ template_conversation_upper.html <div … style="height: %spx;”></div> ↓ ViewGroupͷߴ͞ <div
… style="height: 288px;”></div>
ᶅςϯϓϨʔτͷhtmlʹϝʔϧͷhtmlจࣈྻΛૠೖ ϝʔϧඳը·ͰͷྲྀΕᶅ template_message.html <div class=“mail-message-content“>%s</div> ↓ <div class=“mail-message-content“>࣮ࡍͷϝʔϧ༰</div>
ϝʔϧඳը·ͰͷྲྀΕᶆ ᶆ߹ͨ͠htmlจࣈྻΛWebViewͰඳը͢Δ ConversationViewFragment.java mWebView.loadDataWithBaseURL(mBaseUri, convHtml, "text/html", "utf-8", null);
ϝʔϧඳը·ͰͷྲྀΕᶇ ᶇpadding্ʹϔομʔɾϑολʔViewGroupΛ ɹlayout()Ͱஔ͢Δ
࣮ϙΠϯτ
ConversationContainer • ViewGroupΛΦʔόʔϨΠ ͱͯ͠औΓ࣋ͭ • WebViewͱViewGroupͷ Լʹ͍ΔFrameLayoutతଘࡏ WebView ViewGroup ViewGroup
ConversationContainer
ViewGroupͷಈ͔͠ํ • ϔομʔɾϑολʔWebViewͷεΫϩʔϧʹ࿈ಈ͢Δ • ConversationContainer͕ಈ͔͢ • offsetTopAndBottom()ͰsetTransitionY()Ͱͳ͘layout()
λονΠϕϯτ • ConversationContainerͷλονΠϕϯτͦͷ·· WebViewʹͤ͞Δ • ScrollViewͷonInterceptTouchEventΛࢀߟʹͯ͠ ViewGroupͷλονΠϕϯτΛ੍ݶ͍ͯ͠Δ
ViewGroupͷϦαΠΫϧ • ConversationContainerͷViewGroupListViewͷΑ͏ʹ ViewΛഁغɾ࠶ੜ͢ΔϦαΠΫϧͷΈ͕ΘΕ͍ͯΔ
ϔομʔλοϓ࣌ͷಈ͖ • ϔομʔΛλοϓ͢ΔͱɺjavascriptͰcssͷstyle.display Λݺͼɺදࣔ/ඇදࣔΛΓସ͑Δ λοϓ
ඳըͷऴྃͷड͚औΓ • ඳըͷऴྃΛcssͷίʔϧόοΫ(webkitAnimationStart) Ͱड͚औΔ • ओʹProgressBarͷඇදࣔͷͨΊʹ͏
εΫϩʔϧόʔ • WebViewͷεΫϩʔϧόʔ Λ͏ͱViewGroupʹ ӅΕͯ͠·͏ͨΊࣗલͰੜ • android:scrollbars=“vertical” ʹͯ͠Έͨঢ়ଶ→
AOSPϝʔϧΞϓϦ͍͢͝
GmailΞϓϦͱҧ͏ͷʁ
͓ͼ • 1݄ʹGmailͷσβΠϯϦχϡʔΞϧ͕ൃද https://jp.techcrunch.com/ 2019/01/30/2019-01-29-gmail-on-mobile- gets-a-fresh-coat-of-material-design-paint/ • ࠓճൺֱͨ͠όʔδϣϯͦͷલͷ8.12.30 (2019/1/24ߋ৽)
GmailΞϓϦͱͷൺֱ AOSPϝʔϧ Gmail
GmailΞϓϦͱͷൺֱ • ػೳɺࡉ͔͍UIͳͲҧ͏ • ϝʔϧৄࡉը໘ͷߏಉ͡
ϔομʔΦʔόʔϨΠʁ • ԡͯ͠͠ʮͯ͢બʯ
• ϔομʔViewGroup WebView্ʹΦʔόʔϨΠ ͞Εͯͦ͏ ϔομʔΦʔόʔϨΠʁ ͜͜͡Όͳ͍ʂ
ϑολʔΦʔόʔϨΠʁ • ζʔϜΠϯͨ͠ঢ়ଶ
ϑολʔΦʔόʔϨΠʁ • ϑολʔViewGroup WebView্ʹΦʔόʔϨΠ ͞Εͯͦ͏
GmailΞϓϦͱͷൺֱ • WebView্ʹϔομʔɾϑολʔViewGroup ͕ΦʔόʔϨΠ͞Ε͍ͯΔ • AOSPϝʔϧͱಉ͡ߏͷՄೳੑ͕ߴ͍
χϡʔεΞϓϦͷԠ༻
ϓϩμΫτೖ·ͰͷྲྀΕ • ͕ൃੜɺݪҼΛݕূ • AOSPʹࢀߟʹͳΔ࣮͕ͳ͍͔୳͢ • ෦࣮ΛಡΈਐΊΔ • ࠷ݶͰಈ͘ΞϓϦΛ࡞ͬͯݕূ •
ϓϩμΫτʹೖ
ϓϩμΫτೖ • ϑολʔͷΈඞཁͳը໘͔Β࣮ࢪ WebView ϑολʔViewGroup
ࢀߟʹ͠ͳ͔ͬͨͱ͜Ζ
ࢀߟʹ͠ͳ͔ͬͨͱ͜Ζ • ViewͷϦαΠΫϧΛ͍ͯ͠ͳ͍ ˠࠓճͷέʔεͰෆཁ
ࢀߟʹ͠ͳ͔ͬͨͱ͜Ζ • WebViewඳըऴྃͷίʔϧόοΫ DOMContentLoadedΛ͏ ˠૣ͍ɺ؆୯
ࢀߟʹ͠ͳ͔ͬͨͱ͜Ζ • ViewGroupͷҠಈlayout()Ͱͳ͘ ViewCompat.offsetTopAndBottom()Λ༻ ˠίʔυͷ໌֬Խ ˠsetTransitionYΞχϝʔγϣϯ͖
࣮ࡍͲ͏ͩͬͨͷ͔
࠾༻ͯ͠Α͔ͬͨ͜ͱ • ͷରॲ͕Ͱ͖ͨ • ඳը͕एׯૣ͘ͳͬͨ
࠾༻ͯ͠େมͩͬͨ͜ͱ • Մಡੑ͕Լ͕Γɺϝϯςίετ͕૿͑ͨ • ಋೖ͢Δ·Ͱ͕͔͔࣌ؒͬͨ ɾରԠํ๏ͷݕূ࣌ؒ ɾಋೖํ๏ͷݕূ࣌ؒ
ਅࣅ͖͔͢Ͳ͏͔ • ݕ౼ͷ༨͋Δ͕࠾༻ίετߴ͍ • WebView in ScrollViewͷϦεΫΛߟ͑Δ
͠WebView+ViewGroup ͨ͘͠ͳͬͨΒʁ
͠ඞཁʹഭΒΕͨΒ… • WebViewΛΊΔʢ࠷ਪʣ • WebViewͷΈʹ͢Δʢڧ͘ਪʣ • AOSPϝʔϧํࣜΛࢀߟʹ͢Δʢਪʣ
͠ඞཁʹഭΒΕͨΒ… • https://github.com/angebagui/medium-textview/ https://github.com/m7mdra/HtmlRecycler ͷϥΠϒϥϦΛͬͯΈΔʢرʣ • ৽͍͠ΓํΛߟ͑Δʢେ݀ʣ • ScrollViewʹWebViewΛೖΕΔʢඇਪʣ
αϯϓϧΞϓϦ
αϯϓϧΞϓϦ • https://github.com/ogapants/WebViewWithViewGroup • ̎ͭͷํ๏ͰWebView+ButtonΛ࣮ݱ - WebView in ScrollView
- WebView only
αϯϓϧΞϓϦཁ݅ • 1͔Β260·Ͱදࣔ͢ΔHTML • WebViewͷ্ԼʹButton • શମΛεΫϩʔϧͰ͖Δ WebView
Button Button 1 2 3 … 258 259 260
ํ๏ᶃ WebView in ScrollView
WebView in ScrollView • ్தͰΕΔ • <ScrollView> <LinerLayout> ɹɹɹ<Button> <WebView>
<Button> </LinerLayout> <ScrollView>
WebView in ScrollView • ࠶ݱΤϛϡϨʔλ Pixel2XLɺNexus6PʢόʔδϣϯدΒͣʣ • ඇ࠶ݱΤϛϡϨʔλ Pixel2ɺNexus5XͳͲʢόʔδϣϯدΒͣʣ •
࣮ػ࠶ݱੑ͕ᐆດ
ํ๏ᶄ WebView only
WebView only • ͳ͘දࣔ͞ΕΔ • <ArticleContainer> <ArticleWebView> <Button> <Button> </ArticleContainer>
WebView only • ArticleContainerͷ࣮ • ϔομʔͱϑολʔΛεΫϩʔϧͤ͞Δ fun dispatchScroll(oldScrollY:
Int, scrollY: Int) { this.offsetY = scrollY val oldScrollYAbs = Math.abs(oldScrollY) val scrollYAbs = Math.abs(scrollY) val offset = oldScrollYAbs - scrollYAbs ViewCompat.offsetTopAndBottom(header, offset) ViewCompat.offsetTopAndBottom(footer, offset) }
WebView only • ςϯϓϨʔτHTMLͷ࣮ <!DOCTYPE html>ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ <html>ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ <script
type="text/javascript">ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ window.addEventListener("DOMContentLoaded", function () {ɹɹɹɹɹɹ var contentHeight = document.getElementById(“content").offsetHeight; window.JS._onDomContentLoaded(contentHeight);ɹɹɹɹɹɹɹɹɹ });ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ </script>
• ςϯϓϨʔτHTMLͷ࣮ WebView only <body> <div id="header-spacer" style="height: %spx;"></div> <div
id="content"> %s </div>ɹɹɹɹɹɹɹɹɹɹɹɹɹ <div id="footer-spacer" style="height: %spx;"></div> </body>ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ </html>ɹɹɹɹɹɹ
͍͞͝ʹ
͓͞Β͍ • WebViewͰεΫϩʔϧͤ͞Δ • ViewGroup࿈ಈ • ViewGroupͷߴ͞cssͰpadding WebView ViewGroup ViewGroup
padding padding
·ͱΊ • AOSPݟͷմͳͷͰ͏·͘ར༻͠Α͏ • AOSPϝʔϧΞϓϦͷϝʔϧৄࡉը໘ͷඳըͷΈ͍͢͝ • ඞཁ࠷ݶͷߏΛ࡞ͬͯ࠶ݱੑΛݟͯɺ࠷ݶͷ࣮ͰΔ͜ͱ Λ֬ೝͯ͠ɺطଘίʔυΛՃຯͭͭ͠ɺϓϩμΫτʹೖ͠Α͏ • ScrollViewͷதʹWebViewΛೖΕΔͷආ͚Α͏
࠾༻ͬͯ·͢ https://s.nikkei.com/s_android