How I Created My First Android Watch Face in Jetpack Compose
Why I Chose Jetpack Compose for Watch Face
- XML layouts
- Canvas drawing
- Complicated services
- Declarative ✨
- Less boilerplate
- Easier to maintain
What I Learned First
- Basics of Kotlin
- Jetpack Compose fundamentals
- What Wear OS is
- Difference between mobile apps and watch apps
Step 1: Setting Up the Wear OS Project
- Click New Project
- Select Wear OS
- Choose Empty Compose Activity
- Select Minimum SDK: Wear OS API 30+
- Wear‑specific dependencies
- Compose for Wear OS
Step 2: Understanding Watch Face Architecture
Step 3: Designing the UI with Compose
- Black background (battery‑friendly)
- Large digital time
- Subtle date text
- Box() for center alignment
- Text() for time display
- MaterialTheme for styling
Step 4: Getting the Current Time
- Use LocalTime
- Update UI every second
- Use LaunchedEffect and delay()
Step 5: Handling Always‑On Mode (AOD)
- Animations should stop
- Colors should be minimal
- Brightness must be low
- How Wear OS informs the app about ambient mode
- How to switch UI based on mode
Step 6: Testing on Emulator & Real Device
- Text too big π
- UI clipped on round screen
- Seconds not updating
Mistakes I Made (So You Don’t)
What I Learned from My First Watch Face
- Wear OS is not mobile Android
- Compose simplifies complex UI
- Battery optimization matters
- Small UI changes make big differences
What’s Next?
- Battery complication
- Step counter
- Custom fonts
- User‑selectable themes
Source Code
package com.codingbihar.mywatchface.presentation
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.material.Text
import kotlinx.coroutines.delay
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
setTheme(android.R.style.Theme_DeviceDefault)
setContent {
MyFirstWatchFace()
}
}
}
@Composable
fun MyFirstWatchFace() {
var time by remember { mutableStateOf(LocalDateTime.now()) }
LaunchedEffect(Unit) {
while (true) {
time = LocalDateTime.now()
delay(1000)
}
}
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF87CEEB)) // sky blue
) {
/* ☀️ Sun */
Text(
text = "☀️",
fontSize = 36.sp,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(8.dp)
)
/* ☁️ Clouds */
Text(
text = "☁️",
fontSize = 30.sp,
modifier = Modifier
.align(Alignment.TopStart)
.padding(10.dp)
)
Text(
text = "☁️",
fontSize = 24.sp,
modifier = Modifier
.align(Alignment.TopCenter)
.padding(top = 20.dp)
)
/* π¦ Birds */
Text(
text = "π¦",
fontSize = 24.sp,
modifier = Modifier
.align(Alignment.CenterStart)
.padding(start = 8.dp)
)
Text(
text = "π¦",
fontSize = 22.sp,
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(end = 8.dp)
)
/* ⌚ Time & Date (CENTER) */
Column(
modifier = Modifier.align(Alignment.Center),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("By-codingbihar.com",
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = Color(0xFFFF9800)
)
Text(
text = time.format(DateTimeFormatter.ofPattern("hh:mm")),
fontSize = 38.sp,
fontWeight = FontWeight.Bold,
color = Color(0xFF0D47A1)
)
Text(
text = time.format(DateTimeFormatter.ofPattern("EEE, dd MMM")),
fontSize = 14.sp,
color = Color(0xFF1A237E)
)
}
/* π³ Tree */
Text(
text = "π³",
fontSize = 40.sp,
modifier = Modifier
.align(Alignment.BottomStart)
.padding(6.dp)
)
/* πΌ Flowers */
Row(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 6.dp)
) {
Text("πΌ", fontSize = 20.sp)
Text("πΌ", fontSize = 20.sp)
Text("πΌ", fontSize = 20.sp)
}
/* ⭐ Stars */
Text(
text = "⭐",
fontSize = 16.sp,
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(8.dp)
)
}
}
Output:
Final Thoughts
- UI design
- State management
- Real‑world constraints



