이 페이지에서는 크기를 처리하고 유연한 반응형 광고 소재를 제공하는 방법을 설명합니다. 기존 Glance 구성요소를 사용하여 Glance
Box
, Column
, Row
사용
Glance에는 세 가지 기본 컴포저블 레이아웃이 있습니다.
Box
: 요소를 다른 요소 위에 배치합니다. 이는RelativeLayout
로 변환됩니다.Column
: 세로축에서 요소를 나란히 배치합니다. 번역합니다. 세로 방향의LinearLayout
로 설정합니다.Row
: 가로축에서 요소를 서로 뒤에 배치합니다. 번역합니다. 가로 방향의LinearLayout
로 변환합니다.
Glance는 Scaffold
객체를 지원합니다. Column
, Row
,
지정된 Scaffold
객체 내의 Box
컴포저블
![열, 행, 상자 레이아웃 이미지](https://developer.android.com/static/develop/ui/compose/images/column_row_box.png?authuser=0000&hl=ko)
이러한 각 컴포저블을 사용하면 세로 및 가로 정렬을 정의할 수 있습니다. 너비, 높이, 두께 또는 패딩 제약 조건을 사용하여 특수키를 사용합니다. 또한 각 하위 요소는 수정자를 정의하여 공백을 변경할 수 있습니다. 배치를 확인할 수 있습니다.
다음 예는 Row
를 만드는 방법을 보여줍니다.
다음 그림 1과 같이 하위 요소를 수평으로 배열합니다.
Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) { val modifier = GlanceModifier.defaultWeight() Text("first", modifier) Text("second", modifier) Text("third", modifier) }
Row
는 사용 가능한 최대 너비를 채우며, 각 하위 요소가 동일하기 때문에
사용 가능한 공간을 균등하게 공유합니다. 서로 다른 가중치를 정의할 수 있고,
크기, 패딩 또는 정렬을 사용하여 필요에 맞게 레이아웃을 조정할 수 있습니다.
스크롤 가능한 레이아웃 사용
반응형 콘텐츠를 제공하는 또 다른 방법은 스크롤 가능하게 만드는 것입니다. 이것은
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
를 지정하지 않습니다. 이
itemId
는 성능을 개선하고 스크롤을 유지하는 데 도움이 됩니다.
Android 12부터 목록 및 appWidget
업데이트를 통해 포지셔닝합니다(
(예: 목록에서 항목을 추가하거나 삭제하는 경우)). 다음 예를 참고하세요.
itemId
지정 방법을 보여줍니다.
items(items = peopleList, key = { person -> person.id }) { person -> Text(person.name) }
SizeMode
정의
AppWidget
크기는 기기, 사용자 선택 또는 런처에 따라 다를 수 있습니다.
따라서
유연한 위젯 레이아웃 페이지를 참조하세요. Glance는 SizeMode
를 통해 이를 단순화합니다.
정의 및 LocalSize
값 다음 섹션에서는 이 세 가지 방법을 설명합니다.
있습니다.
SizeMode.Single
SizeMode.Single
가 기본 모드입니다. 이는 다음 중 한 가지 유형만
제공되는지 확인합니다. 즉, 사용 가능한 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
에서 세 가지 크기와
콘텐츠:
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
메서드는 세 번 호출되며
정의된 크기에 매핑됩니다.
- 첫 번째 호출에서 크기는
100x100
로 평가됩니다. 콘텐츠가 추가 버튼이나 상단 및 하단 텍스트를 포함하지 마세요. - 두 번째 호출에서 크기는
250x100
로 평가됩니다. 콘텐츠에는 추가 버튼을 사용하고 상단과 하단 텍스트는 사용하지 않습니다. - 세 번째 호출에서 크기는
250x250
로 평가됩니다. 콘텐츠에는 추가 버튼과 두 텍스트를 모두 사용합니다.
SizeMode.Responsive
는 다른 두 모드의 조합으로, 이 모드를 사용하면
미리 정의된 경계 내에서 반응형 콘텐츠를 정의합니다. 일반적으로 이 모드는
성능이 향상되고 AppWidget
의 크기가 조절될 때 전환이 더 원활해집니다.
다음 표는 SizeMode
및
사용 가능한 AppWidget
크기:
사용 가능한 크기 | 105 x 110 | 203 x 112 | 72 x 72 | 203 x 150 |
---|---|---|---|---|
SizeMode.Single |
110 x 110 | 110 x 110 | 110 x 110 | 110 x 110 |
SizeMode.Exact |
105 x 110 | 203 x 112 | 72 x 72 | 203 x 150 |
SizeMode.Responsive |
80 x 100 | 80 x 100 | 80 x 100 | 150 x 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 | Scaffold와 제목 표시줄이 같은 데모에 있습니다. |
디자인 세부사항에 대한 자세한 내용은 이 도움말의 구성요소 디자인을 참조하세요. 디자인 키트를 사용해 보세요.