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
WebView+ViewGroupを実現するAOSPメールアプリの内部実装とニュースアプリ...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
790
ScrollViewで 読了計測した話
ogapants
0
880
「AndroidはiOSと同じデザインで!」と言われたときのTips
ogapants
17
8.5k
たのしいAndroidかいはつ
ogapants
0
200
Fabric Digitsで始めるSMS認証
ogapants
1
1.3k
MediaController をカスタマイズするぞ
ogapants
0
2.8k
Other Decks in Technology
See All in Technology
Why Agent Cost Needs Observability
nttcom
0
120
アプリをもっと"iOSアプリっぽく"する小さな工夫 / Small Touches That Make Your App Feel More Like an iOS App
matsuji
2
1k
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
30
18k
「ピッケル本」日本語版は4.0(第6版)が出版されるべき / pickaxe4-nagoyark05
kakutani
2
270
ソフトウェアDNAとクラウドエージェントのススメ
cloudace
0
120
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
2.3k
2026-09-08 そのJavaモダナイゼーション、AIに丸投げで大丈夫?IBM Bobで変わる品質と効率
yutanonaka
1
130
エージェントはローカル、検証はMicroVM — Lambda MicroVMsでつくるServerless CI
fujioka6789
3
660
サーバーレスをどこまで使う? WebRTC対戦ゲームで選んだVPSとの共存設計
kaidouji85
0
310
AIエージェントを最高のパートナーに育てる方法|評価と判断軸を育てる5つのステップ
koichiaoki
1
160
Deployment の 先にある AI Agent 基盤 - kagent vNext、Agent Substrate、Hermes から読み解く Agent Runtime の現在地 / k8s-matsuri-2-ai-agent-platform-amsy810
masayaaoyama
4
700
C#コードの結合を可視化する Roslyn解析による設計改善と リファクタリング判断
dora56
0
330
Featured
See All Featured
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
500
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
Side Projects
sachag
456
43k
ラッコキーワード サービス紹介資料
rakko
1
5M
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
How to train your dragon (web standard)
notwaldorf
97
6.8k
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
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