728x90
목적
Compose에서 Glance를 이용해서 Widget을 만들어본다
Widget이란?
안드로이드 앱의 소형 버전을 바탕화면에 간략하게 보여줄 수 있는 기능
방법
Dependency 추가
- libs.versions.toml
[versions]
glance = "1.1.0"
[libraries]
glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glance" }
glance-material = { group = "androidx.glance", name = "glance-material", version.ref = "glance" }
- build.gradle.kts
dependencies {
implementation(libs.glance.appwidget)
implementation(libs.glance.material)
}
AppWidget 기본 코드 추가
- MyAppWidget
class MyAppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
MyContent()
}
}
}
- MyAppWidgetReceiver
class MyAppWidgetReceiver: GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget
get() = MyAppWidget()
}
xml package 아래에 my_app_widget_info.xml 생성 및 AppWidgetProviderInfo 메타데이터 추가
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="100dp"
android:minHeight="50dp"
android:minResizeWidth="50dp"
android:minResizeHeight="50dp"
android:resizeMode="horizontal|vertical"
>
</appwidget-provider>
AndroidManifest.xml
<receiver
android:name=".glance.MyAppWidgetReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>
UI 꾸미기
- my_app_widget_info.xml 내에 필요한 속성들을 공식 홈페이지 확인 후 추가. API 버전에 따라 지원 속성이 다르니 별도 구성 필요
- MyContent() 는 Glance Composable 코드로 아래와 같이 만듦
import android.content.Context
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.LocalSize
import androidx.glance.action.actionStartActivity
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.SizeMode
import androidx.glance.appwidget.lazy.LazyColumn
import androidx.glance.appwidget.provideContent
import androidx.glance.background
import androidx.glance.layout.Alignment
import androidx.glance.layout.Column
import androidx.glance.layout.Spacer
import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.height
import androidx.glance.layout.padding
import androidx.glance.text.FontWeight
import androidx.glance.text.Text
import androidx.glance.text.TextStyle
import com.example.glancetest.MainActivity
import com.example.glancetest.R
class MyAppWidget : GlanceAppWidget() {
companion object {
val SMALL_WIDGET = DpSize(100.dp, 100.dp)
val MEDIUM_WIDGET = DpSize(250.dp, 100.dp)
val LARGE_WIDGET = DpSize(250.dp, 250.dp)
}
override val sizeMode: SizeMode
get() = SizeMode.Responsive(
setOf(
SMALL_WIDGET,
MEDIUM_WIDGET,
LARGE_WIDGET,
)
)
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
GlanceTheme {
MyContent()
}
}
}
@Composable
private fun MyContent() {
val widgetSize = LocalSize.current
Column(
modifier = GlanceModifier.fillMaxSize()
.background(color = MaterialTheme.colorScheme.background)
.clickable(actionStartActivity<MainActivity>()),
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = Alignment.CenterHorizontally,
) {
when (widgetSize) {
SMALL_WIDGET -> {
Image(
provider = ImageProvider(R.drawable.ic_launcher_foreground),
contentDescription = "icon"
)
}
MEDIUM_WIDGET -> {
Text(
text = "Hello, Glance!",
style = TextStyle(
color = GlanceTheme.colors.primary,
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
)
Spacer(modifier = GlanceModifier.height(8.dp))
Text(
text = "This is a medium widget",
style = TextStyle(
color = GlanceTheme.colors.secondary,
fontSize = 14.sp,
)
)
}
LARGE_WIDGET -> {
Text(
text = "This is a large widget",
style = TextStyle(
color = GlanceTheme.colors.primary,
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
)
Spacer(modifier = GlanceModifier.height(8.dp))
LazyColumn(
modifier = GlanceModifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
items(30) { index ->
Text(
text = "item ${index + 1}",
modifier = GlanceModifier.fillMaxWidth()
.background(color = MaterialTheme.colorScheme.inversePrimary)
.padding(4.dp),
)
if (index < 29) {
Spacer(modifier = GlanceModifier.height(4.dp))
}
}
}
}
}
}
}
}
유의깊게 봐야할 것은 import 부분에 androidx.glance 로 시작하는 부분. compose 처럼 구성되어 있지만 Widget은 Glance를 라이브러리를 사용하기 때문에, compose랑 코드가 약간 다름.
한가지 참고사항. Glance는 빌드할 때마다 업데이트가 자동으로 되지 않음. 즉, 빌드하고 기존 Widget으로 사용하고 있던 것이 있다면 삭제하거나 새로 Widget을 생성해야함
바탕화면에 Widget 추가하는 방법
Widget
끝!
728x90
'개발 > 안드로이드' 카테고리의 다른 글
Android Compose Scroll Indicator 그리기 (0) | 2024.08.01 |
---|---|
안드로이드 4대 컴포넌트 (0) | 2020.06.30 |
안드로이드, 플랫폼, 액티비티 - Android, Platform, Activity (0) | 2020.06.05 |
지도 API 비교(구글, 네이버, 카카오) (0) | 2020.05.06 |
댓글