If you’re diving into the world of Jetpack Compose and want to create a widget for your Android app, you’re in the right place. In this guide, we’ll set up a widget using Jetpack Compose.
Prerequisites
Before we begin, make sure you have the following dependencies in your build.gradle
file:
//widget
implementation("androidx.glance:glance:1.1.0-alpha01")
implementation("androidx.glance:glance-appwidget:1.1.0-alpha01")
Manifest Setup
In your AndroidManifest.xml, declare the receiver for your widget:
<receiver android:name=".widget.CounterWidgetReceiver" 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/counter_widget_info" />
</receiver>
Widget Provider Configuration
Create a widget provider XML file (xml/counter_widget_info.xml
) with the necessary configurations:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_name"
android:minWidth="130dp"
android:minHeight="102dp"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
/>
GlanceAppWidget
The widget is represented by the TrackerWidget
object, extending the GlanceAppWidget
:
object TrackerWidget: GlanceAppWidget() {
// Constants and preferences keys
// ...
const val KEY_WIDGET_COUNT = "count"
val countKey = intPreferencesKey(KEY_WIDGET_COUNT)
override suspend fun provideGlance(context: Context, id: GlanceId) {
// Widget content generation logic
// ...
provideContent {
val count = currentState(key = countKey) ?: preferences.getCount()
val goal = 10
val countPercent = count * 100 / goal
context.WidgetContent(count,countPercent)
}
}
}
In this implementation, TrackerWidget
inherits from GlanceAppWidget
, a part of the Glance library. The GlanceAppWidget
provides a framework for building glanceable widgets with simplified configuration and state management.
By extending GlanceAppWidget
, you gain access to convenient functions for handling widget states, preferences, and content updates. The provideGlance
function is where you define the logic for generating widget content based on the current state and user preferences.
Widget Receiver
Handle widget updates in the CounterWidgetReceiver
class:
class CounterWidgetReceiver: GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget
get() = TrackerWidget
}
Action Callback for Incrementing
Implement an action callback (IncrementActionCallback
) to handle widget interactions:
class IncrementActionCallback: ActionCallback {
override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
updateAppWidgetState(context, glanceId) { prefs ->
val currentCount = prefs[TrackerWidget.countKey]
currentCount?.let {
prefs[TrackerWidget.countKey] = currentCount + 1
}?: run{
prefs[TrackerWidget.countKey] = 1
}
}
TrackerWidget.update(context, glanceId)
}
}
Composable Content
Define the Composable functions for rendering widget content:
@Composable
fun Context.WidgetContent(count: Int, countPercent: Int) {
// Composable content for widget with increment button
Column(
modifier = GlanceModifier
.fillMaxSize().padding(4.dp)
.background(White),
verticalAlignment = Alignment.Vertical.CenterVertically,
horizontalAlignment = Alignment.Horizontal.CenterHorizontally
) {
Button(
text = getString(R.string.add_1),
colors = ButtonDefaults.buttonColors(
backgroundColor = ColorProvider(Blue),
ColorProvider(White)
),
onClick = actionRunCallback(IncrementActionCallback::class.java)
)
// ...
}
}
Ensure the correct import statements:
import androidx.glance.Button
import androidx.glance.Text
//or
import androidx.glance.*
That’s it! You’ve configured a Jetpack Compose widget using Kotlin and Glance. Feel free to customize the code according to your app’s requirements.
For a closer look at the sample code and to contribute to the project, check out the GitHub repository:
GitHub Repository — (Drops Water Tracker)
Your feedback and contributions are highly appreciated. Happy coding!