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
910
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
Gradleの実行環境設定を見直す
e10dokup
0
770
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
0
530
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.1k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
690
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.3k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.4k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3.1k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
250
よしなに頑張る画像ロードの話 / image load mettya tsurai
e10dokup
2
470
Other Decks in Programming
See All in Programming
Monixと常駐プログラムの勘どころ / Scalaわいわい勉強会 #4
stoneream
0
270
CSC305 Lecture 26
javiergs
PRO
0
140
「とりあえず動く」コードはよい、「読みやすい」コードはもっとよい / Code that 'just works' is good, but code that is 'readable' is even better.
mkmk884
3
120
数十万行のプロジェクトを Scala 2から3に完全移行した
xuwei_k
0
270
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
5
900
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
210
PHPで学ぶプログラミングの教訓 / Lessons in Programming Learned through PHP
nrslib
2
170
PHPUnitしか使ってこなかった 一般PHPerがPestに乗り換えた実録
mashirou1234
0
130
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
180
バグを見つけた?それAppleに直してもらおう!
uetyo
0
180
Beyond ORM
77web
5
520
KubeCon + CloudNativeCon NA 2024 Overviewat Kubernetes Meetup Tokyo #68 / amsy810_k8sjp68
masayaaoyama
0
250
Featured
See All Featured
Unsuck your backbone
ammeep
669
57k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Building an army of robots
kneath
302
44k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
How to Ace a Technical Interview
jacobian
276
23k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Rails Girls Zürich Keynote
gr2m
94
13k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Building Better People: How to give real-time feedback that sticks.
wjessup
365
19k
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
1.9k
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 簡単な算数が必要だが場合分けさえしっかり考えれば実現は楽 スピーカー一覧画面をよーく見るとラベルが中央からずれているはず