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
Contact AppっぽいSticky Headerをつくる
Search
Yoshihiro WADA
February 22, 2018
Programming
1k
3
Share
Contact AppっぽいSticky Headerをつくる
2018/02/22に開催されたpotatotips #48での発表スライドです。
Yoshihiro WADA
February 22, 2018
More Decks by Yoshihiro WADA
See All by Yoshihiro WADA
AndroidデバイスにFTPサーバを建立する
e10dokup
0
1.2k
Gradleの実行環境設定を見直す
e10dokup
0
1.3k
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
1
720
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.3k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
790
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.9k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.9k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3.6k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
300
Other Decks in Programming
See All in Programming
Making the RBS Parser Faster
soutaro
0
670
Agent Skills を社内で育てる仕組み作り
jackchuka
1
1.6k
From Formal Specification to Property Based Test
ohbarye
0
730
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
530
Import assertionsが消えた日~ECMAScriptの仕様はどう決まり、なぜ覆るのか~
bicstone
2
180
Programming with a DJ Controller — not vibe coding
m_seki
3
790
AIを導入する前にやるべきこと
negima
2
340
How We Practice Exploratory Testing in Iterative Development( #scrumniigata ) / 反復開発の中で、探索的テストをどう実施しているか
teyamagu
PRO
3
730
実用!Hono RPC2026
yodaka
2
300
mruby on C#: From VM Implementation to Game Scripting (RubyKaigi 2026)
hadashia
2
1.6k
Structured Concurrency, Scoped Values and Joiners in the JDK 25 26 27
josepaumard
1
140
when storing skills in S3 file
watany
3
1.4k
Featured
See All Featured
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
280
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2k
Facilitating Awesome Meetings
lara
57
6.8k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
390
Visualization
eitanlees
150
17k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
130
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
230
Into the Great Unknown - MozCon
thekraken
41
2.4k
Transcript
Contact App っぽい Sticky Header をつくる Yoshihiro Wada a.k.a. @e10dokup
2018/02/22 @ potatotips #48
自己紹介 Yoshihiro Wada CyberAgent, Inc. でいろいろやったりやらなかったり @e10dokup
作りたい物 Android の Contact App や droidkaigi-conference-app みたいな 「名前一覧のアレ」
つかうもの 3FDZDMFS7JFX*UFN%FDPSBUJPO 3 つのメソッドを Override する RecyclerView のアイテムに対して装飾をする adstract class
divider の線を引いたりアイテム間のドラッグをしたり… HFU*UFN0GGTFUT 3FDUPVU3FDU 7JFXWJFX 3FDZDMFS7JFXQBSFOU 3FDZDMFS7JFX4UBUFTUBUF PO%SBX $BOWBTD 3FDZDMFS7JFXQBSFOU 3FDZDMFS7JFX4UBUFTUBUF PO%SBX0WFS $BOWBTD 3FDZDMFS7JFXQBSFOU 3FDZDMFS7JFX4UBUFTUBUF
HFU*UFN0GGTFUT RecyclerView の各 Item の描画位置をずらすメソッド 第一引数の outRect をいじることで描画位置をずらすことができる item の
parent ごと弄るイメージなので item 側の layout XML は outRect の中で描画されることになる 今回作りたい Sticky Header の場合だと left の座標を作りたいマージン分 加えるだけで良さそう。
PO%SBXPO%SBX0WFS Decoration の描画時 / 描画後に呼ばれるメソッド 第一引数の c (Canvas) を操作することで装飾を描画できる この
Canvas は RecyclerView 全体の Canvas で、 RecyclerView の再描画 毎に 1 回だけ呼び出される 今回作りたい Sticky Header の場合だと表示されている要素をループで 見ながら頭文字を DESBX5FYU で然る場所に描画したら良さそう
Canvas 上に文字を書く DBOWBTESBX5FYU 'POU.FUSJDT 指定した座標に指定した 'POU.FUSJDT で文字列を描画するメソッド 指定した座標が中央ではないので補正してあげる必要がある 5FYU1BJOU に対し色やフォントサイズを決定した後、
HFU'POU.FUSJDT で取得する abcdfeghi (0,0) top ascent leading descent bottom ※原点は 5FYU1BJOUUFYU"MJHO1BJOU"MJHO-&'5 の場合
ItemDecoration を実装する (下準備) リスト要素からラベルに表示したい文字 (大体頭文字) を取り出して渡す interface を用意しておく JOUFSGBDF$BMMCBDL\ GVOHFU*OJUJBM
QPTJUJPO*OU 4USJOH ^ ӊҮӉҮ JOUFSGBDF Әᇴ⸢әҽӽӔᖚӂ㮢6QQFS$BTF Ӓҵә⢰ᗍӁӐҮӔҮ㮣 PCKFDU4UJDLZ-BCFM*UFN%FDPSBUJPO$BMMCBDL\ PWFSSJEFGVOHFU*OJUJBM QPTJUJPO*OU 4USJOH\ SFUVSOJUFNT<QPTJUJPO>OBNF<>UP4USJOH ^ ^ ESPQXIJMF とか UP6QQFS$BTF を使うといい感じに @ を 省いたり大文字小文字を揃えたりできそう
ItemDecoration を実装する (初期化) 初期化中に 'POU.FUSJDT と要素の margin、 ラベルの padding を
設定する。 今回は Context を拾って resource から引く感じ JOJU\ WBMSFTPVSDFDPOUFYUSFTPVSDFT 5FYU1BJOU Ә⼀ᇰ UFYU1BJOUBQQMZ\ UZQFGBDF5ZQFGBDF%&'"6-5 JT"OUJ"MJBTUSVF UFYU4J[FSFTPVSDFHFU%JNFOTJPO 3EJNFOTUJDLZ@MBCFM@GPOU@TJ[F DPMPS$POUFYU$PNQBUHFU$PMPS DPOUFYU 3DPMPSQSJNBSZ UFYU"MJHO1BJOU"MJHO-&'5 ^ ൵ኃᓬӘᴀᇰ GPOU.FUSJDTUFYU1BJOUGPOU.FUSJDT MBCFM1BEEJOHSFTPVSDFHFU%JNFOTJPO1JYFM4J[F 3EJNFOMBCFM@QBEEJOH DPOUFOU.BSHJOSFTPVSDFHFU%JNFOTJPO1JYFM4J[F 3EJNFODPOUFOU@NBSHJO ^
ItemDecoration を実装する (HFU*UFN0GGTFUT) init で得た contentMargin の分だけ outRect の left
を増加させ、 ラベルが入る場所を作る PWFSSJEFGVOHFU*UFN0GGTFUT PVU3FDU3FDU WJFX7JFX QBSFOU3FDZDMFS7JFX TUBUF3FDZDMFS7JFX4UBUF \ TVQFSHFU*UFN0GGTFUT PVU3FDU WJFX QBSFOU TUBUF PVU3FDUMFGUDPOUFOU.BSHJO ^ このままだとラベルを与えたい要素以外も全部左にマージンが入るので Callback.getInitial() に不正な値が入ったときはマージンを与えない等 すると本来ラベル与えたい要素以外は画面前幅に描画される 全幅
ItemDecoration を実装する (PO%SBX) PWFSSJEFGVOPO%SBX D$BOWBT QBSFOU3FDZDMFS7JFX TUBUF3FDZDMFS7JFX4UBUF \ TVQFSPO%SBX D
QBSFOU TUBUF WBMUPUBM*UFN$PVOUTUBUFJUFN$PVOUᩈ✊ӁӐҮӵ⺙✛ᡔ WBMDIJME$PVOUQBSFOUDIJME$PVOUজⷭ⒈ҿӶӐҮӵ⺙✛ᡔ WBMGPOU$FOUFS GPOU.FUSJDTBTDFOU GPOU.FUSJDTEFTDFOU WBSQSFWJPVT*OJUJBM4USJOH WBSJOJUJBM GPS JJOVOUJMDIJME$PVOU \ ⷭ⒈ҿӶӐҮӵ⺙✛ҶՑՁՓӼᝡ∈Ӄӣҷ⺙✛ҵᴀᇰӃӵ WBMWJFXQBSFOUHFU$IJME"U J WBMQPTJUJPOQBSFOUHFU$IJME"EBQUFS1PTJUJPO WJFX QSFWJPVT*OJUJBMJOJUJBM JOJUJBMDBMMCBDLHFU*OJUJBM QPTJUJPO JG 5FYU6UJMTJT&NQUZ JOJUJBM ]]QSFWJPVT*OJUJBMJOJUJBM DPOUJOVF ᝡ∈৴⡕Ә : ᏍᮏӼᴀᇰӁӐᝡ∈Ӄӵ㮢ᰪՂդԠ㮣 ^ ^
ItemDecoration を実装する (PO%SBX) PWFSSJEFGVOPO%SBX D$BOWBT QBSFOU3FDZDMFS7JFX TUBUF3FDZDMFS7JFX4UBUF \ TVQFSPO%SBX D
QBSFOU TUBUF WBMUPUBM*UFN$PVOUTUBUFJUFN$PVOU ᩈ✊ӁӐҮӵ⺙✛ᡔ WBMDIJME$PVOUQBSFOUDIJME$PVOUজⷭ⒈ҿӶӐҮӵ⺙✛ᡔ WBMGPOU$FOUFS GPOU.FUSJDTBTDFOU GPOU.FUSJDTEFTDFOU WBSQSFWJPVT*OJUJBM4USJOH WBSJOJUJBM GPS JJOVOUJMDIJME$PVOU \ ⷭ⒈ҿӶӐҮӵ⺙✛ҶՑՁՓӼᝡ∈Ӄӣҷ⺙✛ҵᴀᇰӃӵ WBMWJFXQBSFOUHFU$IJME"U J WBMQPTJUJPOQBSFOUHFU$IJME"EBQUFS1PTJUJPO WJFX QSFWJPVT*OJUJBMJOJUJBM JOJUJBMDBMMCBDLHFU*OJUJBM QPTJUJPO JG 5FYU6UJMTJT&NQUZ JOJUJBM ]]QSFWJPVT*OJUJBMJOJUJBM DPOUJOVF ᝡ∈৴⡕Ә : ᏍᮏӼᴀᇰӁӐᝡ∈Ӄӵ㮢ᰪՂդԠ㮣 ^ ^ リストの前要素と initial が 一致するときは描画しない 描画するのは同じ initial の 先頭の要素だけ
ItemDecoration を実装する (実際の描画) ラベルを描画すべきと判定した要素について描画位置の Y 座標を決定して c.DrawText() で描画する ᇴ㗖Ә 'POU.FUSJDT
ӘसႠᏍᮏ㮢నՂդԠҵӳᛝӍӐҷӉӊһ㮣 WBMGPOU$FOUFS GPOU.FUSJDTBTDFOU GPOU.FUSJDTEFTDFOU ᇴ㗖Әᝡ∈ⅈ WBMWJFX$FOUFS WJFXUPQ WJFXCPUUPN WBMWJFX.JEEMFWJFXIFJHIU WBSUFYU:.BUINBY WJFX.JEEMF WJFX$FOUFS GPOU$FOUFS JG QPTJUJPO UPUBM*UFN$PVOU \ WBMOFYU*OJUJBMDBMMCBDLHFU*OJUJBM QPTJUJPO JG OFYU*OJUJBMJOJUJBMWJFX$FOUFSWJFX.JEEMF \ UFYU:WJFX.JEEMFWJFX$FOUFS ^ ^ DESBX5FYU JOJUJBM MBCFM1BEEJOHUP'MPBU UFYU: UFYU1BJOU
ItemDecoration を実装する (実際の描画) ラベルを描画すべきと判定した要素について描画位置の Y 座標を決定して c.DrawText() で描画する ᇴ㗖Ә 'POU.FUSJDT
ӘसႠᏍᮏ㮢నՂդԠҵӳᛝӍӐҷӉӊһ㮣 WBMGPOU$FOUFS GPOU.FUSJDTBTDFOU GPOU.FUSJDTEFTDFOU ᇴ㗖Әᝡ∈ⅈ WBMWJFX$FOUFS WJFXUPQ WJFXCPUUPN WBMWJFX.JEEMFWJFXIFJHIU WBSUFYU:.BUINBY WJFX.JEEMF WJFX$FOUFS GPOU$FOUFS JG QPTJUJPO UPUBM*UFN$PVOU \ WBMOFYU*OJUJBMDBMMCBDLHFU*OJUJBM QPTJUJPO JG OFYU*OJUJBMJOJUJBMWJFX$FOUFSWJFX.JEEMF \ UFYU:WJFX.JEEMFWJFX$FOUFS ^ ^ DESBX5FYU JOJUJBM MBCFM1BEEJOHUP'MPBU UFYU: UFYU1BJOU まず先頭要素の View 中央に Y 座標をとるようにする A ascent descent FontMetrics 原点から 実際の中央への補正 もやっておく
各 initial の先頭要素か画面最上部に張り付くようにラベルが描画される
ItemDecoration を実装する (実際の描画) ラベルを描画すべきと判定した要素について描画位置の Y 座標を決定して c.DrawText() で描画する ᇴ㗖Ә 'POU.FUSJDT
ӘसႠᏍᮏ㮢నՂդԠҵӳᛝӍӐҷӉӊһ㮣 WBMGPOU$FOUFS GPOU.FUSJDTBTDFOU GPOU.FUSJDTEFTDFOU ᇴ㗖Әᝡ∈ⅈ WBMWJFX$FOUFS WJFXUPQ WJFXCPUUPN WBMWJFX.JEEMFWJFXIFJHIU WBSUFYU:.BUINBY WJFX.JEEMF WJFX$FOUFS GPOU$FOUFS JG QPTJUJPO UPUBM*UFN$PVOU \ WBMOFYU*OJUJBMDBMMCBDLHFU*OJUJBM QPTJUJPO JG OFYU*OJUJBMJOJUJBMWJFX$FOUFSWJFX.JEEMF \ UFYU:WJFX.JEEMFWJFX$FOUFS ^ ^ DESBX5FYU JOJUJBM MBCFM1BEEJOHUP'MPBU UFYU: UFYU1BJOU 次の initial が迫ってきたらラベル を上に逃がすように view の中央が 上にずれた分だけ補正する
次の initial の要素が来ると画面外に押し出されるアニメーションが実現できる
最後に 実は DroidKaigi 公式アプリでは座標計算が適当だったので修正しました ↓一応コードが通しで見れるサンプルはこちら↓ https://github.com/e10dokup/StickyHeaderSample 簡単な算数が必要だが場合分けさえしっかり考えれば実現は楽 スピーカー一覧画面をよーく見るとラベルが中央からずれているはず