このページでは、サイズを適切に処理し、柔軟性とレスポンシブ デザインを持たせる方法について説明します。 Glance の既存の Glance コンポーネントを使用します。
Box
、Column
、Row
を使用する
Glance には、主に次の 3 つのコンポーザブル レイアウトがあります。
Box
: 要素を別の要素の上に重ねて配置します。これはRelativeLayout
に変換されます。Column
: 要素を縦軸で並べます。翻訳機能 縦向きのLinearLayout
にマッピング。Row
: 要素を横軸に並べます。翻訳機能 横向きのLinearLayout
に変更します。
Glance は Scaffold
オブジェクトをサポートしています。Column
、Row
、
特定の Scaffold
オブジェクト内の Box
コンポーザブル。
これらのコンポーザブルのそれぞれで、垂直方向と水平方向の配置を定義できます。 コンテンツの幅、高さ、太さ、パディングの制約を、 使用します。さらに、各子は修飾子を定義してスペースを変更できます 親内のプレースメントです
次の例は、均等に分散する Row
の作成方法を示しています。
その子を水平方向にスケールします(図 1 を参照)。
Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) { val modifier = GlanceModifier.defaultWeight() Text("first", modifier) Text("second", modifier) Text("third", modifier) }
Row
は利用可能な最大幅を埋めます。また、それぞれの子は同じ幅を持ちます。
利用可能なスペースを均等に共有します。さまざまな重みを定義したり
サイズ、パディング、配置を調整し、ニーズに合わせてレイアウトを調整できます。
スクロール可能なレイアウトを使用する
レスポンシブ コンテンツを提供するもう 1 つの方法は、スクロール可能にすることです。これは、
LazyColumn
コンポーザブルで指定することをおすすめします。このコンポーザブルを使用すると、一連の
アプリ ウィジェットのスクロール可能なコンテナ内に表示されるアイテムの数。
次のスニペットは、
LazyColumn
。
アイテムの数を指定できます。
// Remember to import Glance Composables // import androidx.glance.appwidget.layout.LazyColumn LazyColumn { items(10) { index: Int -> Text( text = "Item $index", modifier = GlanceModifier.fillMaxWidth() ) } }
個々のアイテムを指定します。
LazyColumn { item { Text("First Item") } item { Text("Second Item") } }
項目のリストまたは配列を指定します。
LazyColumn { items(peopleNameList) { name -> Text(name) } }
前述の例を組み合わせて使用することもできます。
LazyColumn { item { Text("Names:") } items(peopleNameList) { name -> Text(name) } // or in case you need the index: itemsIndexed(peopleNameList) { index, person -> Text("$person at index $index") } }
前のスニペットでは itemId
を指定していないことに注意してください。Pod の
itemId
は、パフォーマンスの向上とスクロールの維持に役立ちます。
Android 12 以降の appWidget
の更新(
(例: リストのアイテムの追加または削除)。次の例をご覧ください。
は、itemId
を指定する方法を示しています。
items(items = peopleList, key = { person -> person.id }) { person -> Text(person.name) }
SizeMode
を定義する
AppWidget
のサイズは、デバイス、ユーザーの選択、ランチャーによって異なる場合があります。
柔軟なレイアウトを用意することが重要です。詳細については、
柔軟なウィジェット レイアウトのページです。Glance は、これを SizeMode
で簡素化しています。
LocalSize
値を使用します。以降のセクションでは、この 3 つの
あります。
SizeMode.Single
SizeMode.Single
モード(デフォルト モード): つまり、1 つのタイプのデータのみが
コンテンツが提供されること。つまり、AppWidget
使用可能なサイズが変更されても、
コンテンツサイズは変更されません。
class MyAppWidget : GlanceAppWidget() { override val sizeMode = SizeMode.Single override suspend fun provideGlance(context: Context, id: GlanceId) { // ... provideContent { MyContent() } } @Composable private fun MyContent() { // Size will be the minimum size or resizable // size defined in the App Widget metadata val size = LocalSize.current // ... } }
このモードを使用する場合は、次のことを確認してください。
- メタデータ値の最小値と最大値が、次の値に基づいて適切に定義されている。 コンテンツサイズに応じて変わります
- コンテンツが、想定されたサイズ範囲内で十分に柔軟であること。
一般に、次の場合にこのモードを使用する必要があります。
a)AppWidget
のサイズが固定されている。または
b)サイズ変更時にコンテンツが変わらない。
SizeMode.Responsive
このモードは、レスポンシブ レイアウトを提供するのと同等です。これにより、
GlanceAppWidget
: 特定のリソースによって制限されるレスポンシブ レイアウトのセットを、
あります。定義されたサイズごとにコンテンツが作成され、特定のサイズに
AppWidget
が作成または更新されたときのサイズ。するとシステムは
最適なサイズのサムネイルが表示されます。
たとえば、デスティネーション AppWidget
では、3 つのサイズと
content:
class MyAppWidget : GlanceAppWidget() { companion object { private val SMALL_SQUARE = DpSize(100.dp, 100.dp) private val HORIZONTAL_RECTANGLE = DpSize(250.dp, 100.dp) private val BIG_SQUARE = DpSize(250.dp, 250.dp) } override val sizeMode = SizeMode.Responsive( setOf( SMALL_SQUARE, HORIZONTAL_RECTANGLE, BIG_SQUARE ) ) override suspend fun provideGlance(context: Context, id: GlanceId) { // ... provideContent { MyContent() } } @Composable private fun MyContent() { // Size will be one of the sizes defined above. val size = LocalSize.current Column { if (size.height >= BIG_SQUARE.height) { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) } Row(horizontalAlignment = Alignment.CenterHorizontally) { Button() Button() if (size.width >= HORIZONTAL_RECTANGLE.width) { Button("School") } } if (size.height >= BIG_SQUARE.height) { Text(text = "provided by X") } } } }
上記の例では、provideContent
メソッドが 3 回呼び出され、
マッピングされます。
- 最初の呼び出しで、サイズは
100x100
と評価されます。コンテンツが 追加ボタンや上下のテキストを含められます - 2 番目の呼び出しでは、サイズは
250x100
と評価されます。内容には、 上部と下部のテキストは除きます - 3 番目の呼び出しでは、サイズは
250x250
と評価されます。内容には、 追加ボタンと両方のテキストが必要です
SizeMode.Responsive
は他の 2 つのモードを組み合わせたもので、
事前定義された境界内でレスポンシブ コンテンツを定義します。一般にこのモードでは
パフォーマンスが向上し、AppWidget
のサイズ変更時の遷移がより滑らかになります。
次の表に、SizeMode
と
利用可能な AppWidget
のサイズ:
利用可能なサイズ | 105×110 | 203×112 | 72×72 | 203×150 |
---|---|---|---|---|
SizeMode.Single |
110×110 | 110×110 | 110×110 | 110×110 |
SizeMode.Exact |
105×110 | 203×112 | 72×72 | 203×150 |
SizeMode.Responsive |
80×100 | 80×100 | 80×100 | 150×120 |
* 正確な値はデモ用です。 |
SizeMode.Exact
SizeMode.Exact
は、正確なレイアウトを指定することと同等です。
利用可能な AppWidget
サイズが返されるたびに GlanceAppWidget
コンテンツをリクエスト
(ユーザーがホーム画面で AppWidget
のサイズを変更したときなど)。
たとえば、デスティネーション ウィジェットで、 利用可能な幅が特定の値を超えています。
class MyAppWidget : GlanceAppWidget() { override val sizeMode = SizeMode.Exact override suspend fun provideGlance(context: Context, id: GlanceId) { // ... provideContent { MyContent() } } @Composable private fun MyContent() { // Size will be the size of the AppWidget val size = LocalSize.current Column { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) Row(horizontalAlignment = Alignment.CenterHorizontally) { Button() Button() if (size.width > 250.dp) { Button("School") } } } } }
このモードは他のモードよりも柔軟性に優れていますが、 注意点:
- サイズが変更されるたびに、
AppWidget
を完全に再作成する必要があります。この コンテンツが複雑な場合、パフォーマンスの問題や UI の切り替わりにつながる可能性があります。 - 使用可能なサイズは、ランチャーの実装によって異なる場合があります。 たとえば、ランチャーでサイズのリストが提供されていない場合、 使用されます。
- Android 12 より前のデバイスでは、サイズ計算ロジックが 対応できます。
一般に、SizeMode.Responsive
を使用できない場合は、このモードを使用する必要があります
(つまり、少数のレスポンシブ レイアウトを使用することは現実的ではありません)。
リソースにアクセスする
次に示すように、LocalContext.current
を使用して任意の Android リソースにアクセスします。
次の例をご覧ください。
LocalContext.current.getString(R.string.glance_title)
最終的なファイルのサイズを小さくするために、リソース ID を直接指定することをおすすめします。
RemoteViews
オブジェクトを作成し、動的リソース
色。
コンポーザブルとメソッドは、「プロバイダ」を使用してリソースを受け入れます。
ImageProvider
、または次のようなオーバーロード メソッドを使用する
GlanceModifier.background(R.color.blue)
。例:
Column( modifier = GlanceModifier.background(R.color.default_widget_background) ) { /**...*/ } Image( provider = ImageProvider(R.drawable.ic_logo), contentDescription = "My image", )
テキストを処理する
Glance 1.1.0 には、テキストのスタイルを設定するための API が含まれています。テキスト スタイルを設定する
TextStyle クラスの fontSize
、fontWeight
、または fontFamily
属性。
次の例に示すように、fontFamily
はすべてのシステム フォントをサポートしますが、
以下のアプリはサポートされていません。
Text(
style = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
),
text = "Example Text"
)
複合ボタンを追加する
複合ボタンは Android 12 で導入されました。Glance は後ろ向きに対応 次のタイプの複合ボタンの互換性:
これらの複合ボタンにはそれぞれ、クリック可能なビューが表示され、 「オン」あります。
var isApplesChecked by remember { mutableStateOf(false) } var isEnabledSwitched by remember { mutableStateOf(false) } var isRadioChecked by remember { mutableStateOf(0) } CheckBox( checked = isApplesChecked, onCheckedChange = { isApplesChecked = !isApplesChecked }, text = "Apples" ) Switch( checked = isEnabledSwitched, onCheckedChange = { isEnabledSwitched = !isEnabledSwitched }, text = "Enabled" ) RadioButton( checked = isRadioChecked == 1, onClick = { isRadioChecked = 1 }, text = "Checked" )
状態が変化すると、指定されたラムダがトリガーされます。保存できる チェック状態を確認します。
class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { val myRepository = MyRepository.getInstance() provideContent { val scope = rememberCoroutineScope() val saveApple: (Boolean) -> Unit = { scope.launch { myRepository.saveApple(it) } } MyContent(saveApple) } } @Composable private fun MyContent(saveApple: (Boolean) -> Unit) { var isAppleChecked by remember { mutableStateOf(false) } Button( text = "Save", onClick = { saveApple(isAppleChecked) } ) } }
colors
属性は、CheckBox
、Switch
、および
RadioButton
を使用して色をカスタマイズします。
CheckBox( // ... colors = CheckboxDefaults.colors( checkedColor = ColorProvider(day = colorAccentDay, night = colorAccentNight), uncheckedColor = ColorProvider(day = Color.DarkGray, night = Color.LightGray) ), checked = isChecked, onCheckedChange = { isChecked = !isChecked } ) Switch( // ... colors = SwitchDefaults.colors( checkedThumbColor = ColorProvider(day = Color.Red, night = Color.Cyan), uncheckedThumbColor = ColorProvider(day = Color.Green, night = Color.Magenta), checkedTrackColor = ColorProvider(day = Color.Blue, night = Color.Yellow), uncheckedTrackColor = ColorProvider(day = Color.Magenta, night = Color.Green) ), checked = isChecked, onCheckedChange = { isChecked = !isChecked }, text = "Enabled" ) RadioButton( // ... colors = RadioButtonDefaults.colors( checkedColor = ColorProvider(day = Color.Cyan, night = Color.Yellow), uncheckedColor = ColorProvider(day = Color.Red, night = Color.Blue) ), )
追加コンポーネント
Glance 1.1.0 には、追加コンポーネントのリリースが含まれています。 次の表をご覧ください。
名前 | 画像 | 参照リンク | その他の注意事項 |
---|---|---|---|
塗りつぶしボタン | コンポーネント | ||
アウトライン ボタン | コンポーネント | ||
アイコンボタン | コンポーネント | メイン / セカンダリ / アイコンのみ | |
タイトルバー | コンポーネント | ||
Scaffold | スキャフォールドとタイトルバーは同じデモにあります。 |
設計の詳細については、こちらのコンポーネント設計に関する Design kit を使用してください。