Slide 1

Slide 1 text

DroidKaigi.collect{ #1@Tokyo } 2023/03/31 kako351@おいしい健康 Composeの 座標を取得する ~コーチマークにおける活用事例~

Slide 2

Slide 2 text

自己紹介 kako351 / @kako_351 おいしい健康 Androidエンジニア Androidエンジニア募集中! 仕事 ● バイク(ハンターカブ) ● ギター ● コーヒー自宅焙煎 趣味 2

Slide 3

Slide 3 text

本日話す内容 ・事例紹介 ・ライブラリの紹介 - Spotlight / intro-showcase-viewSpotlightを採用! ・Composeの座標を取得する ・座標をSpotlightに渡す ・まとめ 3

Slide 4

Slide 4 text

事例紹介 4 Compose座標を取得して 何ができるのか活用事例を紹介

Slide 5

Slide 5 text

実現したいこと コーチマークによるチュートリアル表示。 初めてアプリを使うユーザーに対して機能の役割 を説明します。 ローディング中はコーチマークを表示せず、コン テンツを取得できたタイミングで表示します。 5 コーチマーク形式の チュートリアル

Slide 6

Slide 6 text

ライブラリで簡単に実装できそう! そう思っていたころが僕にもありました…… 6

Slide 7

Slide 7 text

コーチマークの対象画面は以下のようになっています ターゲット領域: Compose それ以外の領域: Fragment ターゲット領域にスポットライトを当てて、それ以外 の領域はマスクをかけたい・・・ 7 対象画面の構成 Fragment Compose

Slide 8

Slide 8 text

8 Spotlight(https://github.com/TakuSemba/Spotlight) Kotlinのコーチマークライブラリ。指定したAndroidViewまたは座標を指定してス ポットライトを当てることができる。 Intro-showcase-view(https://github.com/canopas/Intro-showcase-view) JetpackComposeで利用可能なコーチマークライブラリ。Modifierに introShowCaseTargetをつけることでスポットライトを当てることができる。 Composeのみで構成されている画面ならこちらが有効そう。
 ライブラリ紹介

Slide 9

Slide 9 text

9 Spotlight(https://github.com/TakuSemba/Spotlight) Kotlinのコーチマークライブラリ。指定したAndroidViewまたは座標を指定して スポットライトを当てることができる。今回の主役。 Intro-showcase-view(https://github.com/canopas/Intro-showcase-view) JetpackComposeで利用可能なコーチマークライブラリ。Modifierに introShowCaseTargetをつけることでスポットライトを当てることができる。 Composeのみで構成されている画面ならこちらが有効そう。
 ライブラリ紹介 Composableの座標を渡せばできそう Spotlightを採用!

Slide 10

Slide 10 text

Composeの 座標を取得する 10

Slide 11

Slide 11 text

11 RecommendedMenuCard.kt @Composable fun RecommendedMenuCard( //… ) { Card( modifier = Modifier, // … }

Slide 12

Slide 12 text

12 RecommendedMenuCard.kt @Composable fun RecommendedMenuCard( //… ) { Card( modifier = Modifier.onGloballyPositioned { layoutCoordinates -> // layoutCoordinatesにレイアウトの情報が含まれている }, // … } onGloballyPositionedによって コンポジションされた後のレ イアウト情報を取得

Slide 13

Slide 13 text

13 Modifier.onGloballyPositioned 呼び出しタイミング コンテンツのグローバル位置が変更された可能性があると呼び出され、呼び出さ れるタイミングは座標が確定するコンポジションの後になります。 呼び出し頻度 LayoutCoordinatesが使用可能な時に最低1回呼び出さ、ウィンドウ内で要素の位 置が変わるたびに呼び出されます。 呼び出されない場合 変更された要素の画面に対する相対位置が変わっても呼び出されるとは限りませ ん。(どういうことだってばよ・・・) https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/OnGloballyPositionedModifier

Slide 14

Slide 14 text

14 LayoutCoordinates レイアウトの境界を測定するときに用いるホルダー 拡張関数 ● boundsInParent() 親のコンテンツ領域内の子の境界ボックスを返す ● boundsInRoot() ルート コンポーザブル内のこのレイアウトの境界を返す ● boundsInWindow() ウィンドウの原点に対するこのレイアウトの境界を返す

Slide 15

Slide 15 text

15 LayoutCoordinates レイアウトの境界を測定するときに用いるホルダー 拡張関数 ● boundsInParent() 親のコンテンツ領域内の子の境界ボックスを返す ● boundsInRoot() ルート コンポーザブル内のこのレイアウトの境界を返す ● boundsInWindow() ウィンドウの原点に対するこのレイアウトの境界を返す ウィンドウ上での位置情報・コン テンツサイズが欲しかったのでこ れを採用

Slide 16

Slide 16 text

16 RecommendedMenuCard.kt Modifier.onGloballyPositioned { layoutCoordinates -> val rect = layoutCoordinates.boundsInWindow() // Rect.fromLTRB(left = 84.0, top = 701.0, right = 996.0, bottom = 827.0) rect.center // Offset(x = 540.0, y = 764.0) rect.size // Size(width = 912.0, height = 126.0)

Slide 17

Slide 17 text

17 RecommendedMenuCard.kt Modifier.onGloballyPositioned { layoutCoordinates -> val rect = layoutCoordinates.boundsInWindow() // Rect.fromLTRB(left = 84.0, top = 701.0, right = 996.0, bottom = 827.0) rect.center // Offset(x = 540.0, y = 764.0) rect.size // Size(width = 912.0, height = 126.0) Rectを返す ウィンドウを原点にした位置 が返ってくる

Slide 18

Slide 18 text

18 RecommendedMenuCard.kt Modifier.onGloballyPositioned { layoutCoordinates -> val rect = layoutCoordinates.boundsInWindow() // Rect.fromLTRB(left = 84.0, top = 701.0, right = 996.0, bottom = 827.0) rect.center // Offset(x = 540.0, y = 764.0) rect.size // Size(width = 912.0, height = 126.0) 中央の座標も取得可能 サイズも取得できる

Slide 19

Slide 19 text

座標をSpotlightに渡す 19

Slide 20

Slide 20 text

HomeFragment#startSpotLight() 20 // layoutCoordinatesからTargetを作成 Target.Builder() .setAnchor( x = layoutCoordinates.center.x.absoluteValue, y = layoutCoordinates.center.y.absoluteValue ) .setShape( RoundedRectangle( height = layoutCoordinates.size.height * 1.05f, width = layoutCoordinates.size.width * 1.05f, radius = 25f ) ).build() // Spotlightを作成してTargetを渡す val spotlight = Spotlight.Builder(requireActivity()).setTargets(targets).build() 取得した座標を指定

Slide 21

Slide 21 text

HomeFragment#startSpotLight() 21 // layoutCoordinatesからTargetを作成 Target.Builder() .setAnchor( x = layoutCoordinates.center.x.absoluteValue, y = layoutCoordinates.center.y.absoluteValue ) .setShape( RoundedRectangle( height = layoutCoordinates.size.height * 1.05f, width = layoutCoordinates.size.width * 1.05f, radius = 25f ) ).build() // Spotlightを作成してTargetを渡す val spotlight = Spotlight.Builder(requireActivity()).setTargets(targets).build() スポットライトの サイズを指定

Slide 22

Slide 22 text

コーチマークを表示できました。 Composeの座標やサイズの取得は、 onGloballyPositionedで割と簡単にできました! 22 成果物

Slide 23

Slide 23 text

まとめ 23

Slide 24

Slide 24 text

● Modifier.onGloballyPositionedでComposeの座標を取得可能 ● 座標以外にもサイズも取得できる ● 座標はRectで取得できるのでCompose外に渡すことも可能 24 まとめ 「もっといい方法があるよ!」という場合は優しく教えてくれると嬉しいです!

Slide 25

Slide 25 text

ご静聴 ありがとう ございました 25 DroidKaigi.collect{ #1@Tokyo } 2023/03/31 
 kako351@おいしい健康