Slide 1

Slide 1 text

2024/11/21 日本経済新聞社 郷治 雅 Androidでウィジェットサイズを固定したい 時の困りごととその対処法 NIKKEI TECH TALK

Slide 2

Slide 2 text

ハッシュタグ #nikkei_tech_talk 名前: 郷治 雅 入社: 2016年 仕事: API開発を経てアプリチームにて日経電子版・ 紙面ビューアーのAndroidアプリを開発中 データを用いたユーザー動向分析からアプリ開発の企画や効果 検証も実施 自己紹介 2

Slide 3

Slide 3 text

ハッシュタグ #nikkei_tech_talk 2024年DroidKaigiにて登壇しました Jetpack Glanceを用いてウィジェットを開発する際のTipsとデータ分 析を用いたウィジェット開発から改善までの効果検証プロセスを紹介する 発表をしました。 本日はこちらのセッションのAsk the Speakerにて質 問が多かったウィジェットサイズについての課題と解決法の共有をしま す。 3

Slide 4

Slide 4 text

ハッシュタグ #nikkei_tech_talk 話すこと・話さないこと 話すこと ● Jetpack Glanceを用いて固定サイズのウィジェットを開発し た際に直面したサイズやレイアウトに関する問題点と解決法 話さないこと ● Jetpack Glanceを用いたウィジェット開発に関する事前知識 4

Slide 5

Slide 5 text

ハッシュタグ #nikkei_tech_talk 2レイアウトでそれぞれ固定サイズのウィジェットを開発 ● 検索 + アプリ内の4タブを開く機能のウィジェット ● ウィジェットのリサイズによってレイアウトを変更し、小さい サイズの時は検索機能のみを提供 固定サイズウィジェットの要件 5 4x2 (デフォルト) 4x1

Slide 6

Slide 6 text

ハッシュタグ #nikkei_tech_talk 問題が起きた実装 class SearchMenuWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { provideContent { Content() } } companion object { val LAYOUT_BREAKPOINT = 220.dp internal val NORMAL_SIZE = DpSize(250.dp, LAYOUT_BREAKPOINT) internal val LOW_SIZE = DpSize(250.dp, 92.dp) } 6 レイアウトが変わる縦サイズ

Slide 7

Slide 7 text

ハッシュタグ #nikkei_tech_talk 問題が起きた実装 @Composable private fun Content() { GlanceTheme { when (LocalSize.current) { NORMAL_SIZE -> NormalSizeWidget(MenuItem.entries) LOW_SIZE -> LowSizeWidget() } } } override val sizeMode: SizeMode = SizeMode.Responsive( setOf(NORMAL_SIZE, LOW_SIZE), ) 7 サイズによる それぞれのレイアウト

Slide 8

Slide 8 text

ハッシュタグ #nikkei_tech_talk 問題が起きた実装 @Composable private fun NormalSizeWidget() { Column( modifier = GlanceModifier .wrapContentHeight() .fillMaxWidth() .background(R.color.widget_bg) .padding(16.dp) ) { LogoAndSearch() MenuButton() ….. ウィジェット全体の padding: 16dp メニューボタン : 60dp ボタン間の padding: 12dp ウィジェット全体の高さ : 236dp 8

Slide 9

Slide 9 text

ハッシュタグ #nikkei_tech_talk 問題が起きた実装 @Composable private fun LowSizeWidget() { Box( modifier = GlanceModifier .wrapContentHeight() .fillMaxWidth() .background(R.color.widget_bg) .padding(16.dp) ) { LogoAndSearch() } } ウィジェット全体の padding: 16dp メニューボタン : 60dp ウィジェット全体の高さ : 92dp 9

Slide 10

Slide 10 text

ハッシュタグ #nikkei_tech_talk 4x1レイアウトで横画面にすると想定より小さくなってしまう問題 困りごと① 10 画面回転直後に縦の高さが指定したコンテ ンツの高さより小さくなってしまう

Slide 11

Slide 11 text

ハッシュタグ #nikkei_tech_talk 困りごと①の対処法 4x1の最小サイズを用意 11 companion object { // デフォルトサイズ. 4x2 internal val MEDIUM_HEIGHT_SIZE = DpSize(250.dp, 220.dp) // 4x1 internal val SMALL_HEIGHT_SIZE = DpSize(250.dp, 92.dp) // 最小サイズ internal val X_SMALL_HEIGHT_SIZE = DpSize(250.dp, 40.dp) } 元の実装 追加の実装

Slide 12

Slide 12 text

ハッシュタグ #nikkei_tech_talk

Slide 13

Slide 13 text

ハッシュタグ #nikkei_tech_talk 文字サイズ最大時にコンテンツが見切れる端末がある 困りごと② 13 Pixel8 / API 34 文字サイズ200% Pixel Tablet / API 34 文字サイズ200%

Slide 14

Slide 14 text

ハッシュタグ #nikkei_tech_talk メニューアイテム内の縦方向のpaddingを無くし、各アイテム・ ウィジェット全体の縦方向のサイズを固定 困りごと②の対処法 14 private val searchBarHeight : Dp = 56.dp private val menuButtonHeight: Dp = 54.dp private val fullWidgetHeight: Dp = 224.dp Pixel8 / API 34 文字サイズ200% object Size { internal val FULL = DpSize(250.dp, fullWidgetHeight) internal val ONLY_SEARCH = DpSize(250.dp, 88.dp) internal val ONLY_SEARCH_SMALL = DpSize(250.dp, searchBarHeight) }

Slide 15

Slide 15 text

ハッシュタグ #nikkei_tech_talk 困りごと②の対処法 @Composable private fun NormalSizeWidget() { Column( modifier = GlanceModifier .wrapContentHeight() .fillMaxWidth() .background(R.color.widget_bg) .padding(16.dp) ) { LogoAndSearch() MenuButton() ….. 15 @Composable private fun NormalSizeWidget() { Column( modifier = GlanceModifier .height(SearchMenuWidget.Size.FULL.height) .fillMaxWidth() .background(R.color.widget_bg), verticalAlignment = Alignment.CenterVertically, ) { LogoAndSearch() MenuButton() Befor e After 元の実装 高さを指定して 縦方向の中央寄せ

Slide 16

Slide 16 text

ハッシュタグ #nikkei_tech_talk 端末の解像度によってデフォルトレイアウトが変わってしまう 困りごと③ 16 Pixel4a

Slide 17

Slide 17 text

ハッシュタグ #nikkei_tech_talk ウィジェットの高さを小さめに設定 困りごと③の対処法 17 private val searchBarHeight : Dp = 48.dp private val menuButtonHeight: Dp = 46.dp private val fullWidgetHeight: Dp = 200.dp private val searchBarHeight : Dp = 56.dp private val menuButtonHeight: Dp = 54.dp private val fullWidgetHeight: Dp = 224.dp

Slide 18

Slide 18 text

ハッシュタグ #nikkei_tech_talk 18 Pixel4a

Slide 19

Slide 19 text

ハッシュタグ #nikkei_tech_talk ● 固定サイズのウィジェットを開発する際、横画面でのレイア ウト崩れに注意する必要がある ● 文字サイズを最大にした時にレイアウト崩れやコンテンツ の見切れに注意する必要がある ● 端末の解像度によって意図しない挙動になることがある ためできるだけ多くの端末で検証する必要がある まとめ 19