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
900
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
700
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
0
490
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
670
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.2k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.3k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
250
よしなに頑張る画像ロードの話 / image load mettya tsurai
e10dokup
2
460
Other Decks in Programming
See All in Programming
【Kaigi on Rails 2024】YOUTRUST スポンサーLT
krpk1900
1
250
qmuntal/stateless のススメ
sgash708
0
120
RailsのPull requestsのレビューの時に私が考えていること
yahonda
5
1.7k
offers_20241022_imakiire.pdf
imakurusu
2
360
デプロイを任されたので、教わった通りにデプロイしたら障害になった件 ~俺のやらかしを越えてゆけ~
techouse
52
32k
のびしろを広げる巻き込まれ力:偶然を活かすキャリアの作り方/oso2024
takahashiikki
1
410
Vaporモードを大規模サービスに最速導入して学びを共有する
kazukishimamoto
4
4.3k
2万ページのSSG運用における工夫と注意点 / Vue Fes Japan 2024
chinen
3
1.3k
Outline View in SwiftUI
1024jp
1
160
Tuning GraphQL on Rails
pyama86
2
1k
プロジェクト新規参入者のリードタイム短縮の観点から見る、品質の高いコードとアーキテクチャを保つメリット
d_endo
1
1k
Piniaの現状と今後
waka292
5
1.5k
Featured
See All Featured
Speed Design
sergeychernyshev
24
570
Fontdeck: Realign not Redesign
paulrobertlloyd
81
5.2k
Why You Should Never Use an ORM
jnunemaker
PRO
53
9k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Designing for Performance
lara
604
68k
Building an army of robots
kneath
302
42k
The Cult of Friendly URLs
andyhume
78
6k
Scaling GitHub
holman
458
140k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
290
The Art of Programming - Codeland 2020
erikaheidi
51
13k
Unsuck your backbone
ammeep
668
57k
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 簡単な算数が必要だが場合分けさえしっかり考えれば実現は楽 スピーカー一覧画面をよーく見るとラベルが中央からずれているはず