AppWidgetにはその表示されているサイズ情報が通知されます。
API 31未満では、縦横ぞれぞれのサイズ、API 31以上ではFoldableなどの複数の画面モードの情報も含めて通知されます。
Jetpack Glanceにて、sizeMode = SizeMode.Exactの設定時は、通知されたそれぞれのサイズのレイアウトをまとめて出力します。LocalSize.current は現在構成すべきサイズ情報を参照することができ、この情報に応じてレイアウトを切り替えることでレスポンシブルなWidgetを作成することができます。
しかし、実際にサイズ情報を元に細かな調整を行ったレイアウトを返却してみると、端末によってレイアウトが崩れてしまう場合があります。原因の一つはホームアプリ側がSizedRemoteViewsに対応していないにもかかわらず、複数のサイズを通知してしまっている場合もあります。
が、そもそもサイズ情報がおかしいのでは?ということで調査してみます
調査用ウィジェット
というわけで、以下のように枠一杯のBox,指定サイズのBox,指定サイズから16dp小さいBox,指定サイズの半分のBoxを表示させてみます。
class TestAppWidget : GlanceAppWidget() {
override val sizeMode = SizeMode.Exact
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
val size = LocalSize.current
Box(
modifier = GlanceModifier.fillMaxSize()
.appWidgetBackground()
.background(color = Color.White)
) {
Box(
contentAlignment = Alignment.Center,
modifier = GlanceModifier.fillMaxSize(),
) {
Box(
contentAlignment = Alignment.Center,
modifier = GlanceModifier
.size(
width = size.width,
height = size.height
)
.background(Color.Green)
) {
Box(
contentAlignment = Alignment.Center,
modifier = GlanceModifier
.size(
width = size.width - 16.dp,
height = size.height - 16.dp,
)
.background(Color.Yellow)
) {
Box(
contentAlignment = Alignment.Center,
modifier = GlanceModifier
.size(
width = size.width / 2,
height = size.height / 2,
)
.background(Color.Cyan)
) {}
}
}
}
Text(
text = "${size.width.value.toInt()}x${size.height.value.toInt()}",
modifier = GlanceModifier.padding(16.dp)
)
}
}
}
}
Pixel Launcher
ホームアプリのリファレンスとも言えるPixel Launcher、きっちりと表示されているものと一致するサイズを通知してくれています。
Nova Launcher
実際のサイズよりも横幅が大きく、縦幅が小さく通知されているようです。
ただ、これはAndroid 15での現象のようで、Android 12の端末ではきっちり表示サイズと一致するサイズが通知されていました。こちらはいずれ修正されるのではないかと思います。
Yahoo!きせかえ
表示サイズと一致するサイズが通知されています。
Microsoft Launcher
横幅はあっているようですが、縦が実際のサイズよりも大きな値が通知されるようです。
SmartLauncher
表示サイズと一致するサイズが通知されています。
OPPO システムランチャー
縦横ともにすこし小さな値が通知されています。
さらに、サイズを変更していると、グリッドに沿わなくなり表示サイズが狂っていってしまいます。
仕様と言うにはおかしな挙動なので、バグなのかなとも思いますが、これでも以前よりは改善しているほうで、ウィジェットに関してはあまり力を入れていないのかもしれないです。
続報
システムアップデートで挙動が変わりました、リサイズ時におかしくなるのは同じですが、端末再起動後にほぼ通知と同じサイズになることが多くなったようです。
Xiaomi システムランチャー
表示サイズと一致するサイズが通知されています。
Moto App Launcher (motorola)
縦は小さく、横幅は大きく通知されています。
One UI ホーム (Samsung)
表示サイズと一致するサイズが通知されています。
docomo LIVE UX
ドコモから発売されているスマホに搭載されているランチャーです。
縦方向に白いラインが見えるため、わずかに小さい値が通知されていますが、概ね表示サイズと一致するサイズが通知されています。
AQUOS Phoneランチャー
シャープのAQUOS Phoneには3種類のランチャーが搭載されていました。
いずれも表示サイズと一致するサイズが通知されています。
AQUOS Home
AQUOSかんたんホーム
AQUOSジュニアホーム
+Home
ホーム画面のカスタマイズアプリ、どのサイズでも40x40となっています。
これはサイズ情報がない場合に、GlanceがminResizeWidth/minResizeHeightを埋め込んでいるためです。
こういうアプリがあるというのは想定外でした。
手持ちの端末のメーカーにバリエーションがないため、あんまり突っ込んだ調査になりませんでしたが、それなりのシェアを持っているだろうホームアプリでも、表示サイズとのズレが発生するものがありました。
ウィジェットのレイアウトが崩れていたら、そのアプリが悪いとユーザーは思うでしょうけど、ホームアプリが信頼できる情報を渡してくれないと適切な調整ができないですね。
何か良い方法はないでしょうか?