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
3
970
Contact AppっぽいSticky Headerをつくる
2018/02/22に開催されたpotatotips #48での発表スライドです。
Yoshihiro WADA
February 22, 2018
Tweet
Share
More Decks by Yoshihiro WADA
See All by Yoshihiro WADA
AndroidデバイスにFTPサーバを建立する
e10dokup
0
480
Gradleの実行環境設定を見直す
e10dokup
0
1.1k
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
0
650
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.2k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
750
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.7k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.7k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3.3k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
270
Other Decks in Programming
See All in Programming
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
310
The state patternの実践 個人開発で培ったpractice集
miyanokomiya
0
160
オープンセミナー2025@広島「君はどこで動かすか?」アンケート結果
satoshi256kbyte
0
230
ProxyによるWindow間RPC機構の構築
syumai
3
810
Kiroの仕様駆動開発から見えてきたAIコーディングとの正しい付き合い方
clshinji
1
190
print("Hello, World")
eddie
1
390
ECS初心者の仲間 – TUIツール「e1s」の紹介
keidarcy
0
150
Jakarta EE Core Profile and Helidon - Speed, Simplicity, and AI Integration
ivargrimstad
0
310
Rancher と Terraform
fufuhu
2
200
実用的なGOCACHEPROG実装をするために / golang.tokyo #40
mazrean
1
140
AIレビュアーをスケールさせるには / Scaling AI Reviewers
technuma
2
240
Claude Codeで挑むOSSコントリビュート
eycjur
0
190
Featured
See All Featured
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
510
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
910
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.9k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
Art, The Web, and Tiny UX
lynnandtonic
302
21k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
19k
The Language of Interfaces
destraynor
160
25k
Typedesign – Prime Four
hannesfritz
42
2.8k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
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 簡単な算数が必要だが場合分けさえしっかり考えれば実現は楽 スピーカー一覧画面をよーく見るとラベルが中央からずれているはず