Philipp Lackner님의 영상을 보며 열심히 Compose를 배우던 와중, Compose를 활용하여 데스크탑 앱을 만드는 영상이 올라와서 따라해보았습니다.
Intellij
IDE 가 필요합니다. Jetbrains 홈페이지를 통해 다운받아줍니다.
새 프로젝트 생성 창에서 Kotlin - Compose Desktop Application uses Kotlin 1.5.31을 눌러줍니다.
(그 밑에 있는 멀티 플랫폼이랑 웹앱도 상당히 끌리는군요...)
import androidx.compose.material.MaterialTheme
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
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.window.Window
import androidx.compose.ui.window.application
@Composable
@Preview
fun App() {
var text by remember { mutableStateOf("Hello, World!") }
MaterialTheme {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
) {
val stopWatch = remember { StopWatch() }
StopWatchDisplay(
formattedTime = stopWatch.formattedTime,
onStartClick = stopWatch::start,
onPauseClick = stopWatch::pause,
onResetClick = stopWatch::reset
)
}
}
}
fun main() = application {
Window(onCloseRequest = ::exitApplication) {
App()
}
}
Coroutines, State를 활용하여 이전 시간과 현재시간의 차이를 지속적으로 갱신해가면서 시간을 늘려가는 방식이네요.
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import kotlinx.coroutines.*
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.*
class StopWatch {
var formattedTime by mutableStateOf("00:00:000")
private var coroutineScope = CoroutineScope(Dispatchers.Main)
private var isActive = false
private var timeMillis = 0L
private var lastTimestamp = 0L
fun start() {
if (isActive) return
coroutineScope.launch {
lastTimestamp = System.currentTimeMillis()
this@StopWatch.isActive = true
while(this@StopWatch.isActive) {
delay(10L)
timeMillis += System.currentTimeMillis() - lastTimestamp
lastTimestamp = System.currentTimeMillis()
formattedTime = formatTime(timeMillis)
}
}
}
fun pause() {
isActive = false
}
fun reset() {
coroutineScope.cancel()
coroutineScope = CoroutineScope(Dispatchers.Main)
timeMillis = 0L
lastTimestamp = 0L
formattedTime = "00:00:000"
isActive = false
}
private fun formatTime(timeMillis: Long): String {
val localDateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(timeMillis),
ZoneId.systemDefault()
)
val formatter = DateTimeFormatter.ofPattern(
"mm:ss:SSS",
Locale.getDefault()
)
return localDateTime.format(formatter)
}
}
화면에 보여질 UI를 꾸밉니다. 간단하네요..
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
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
@Composable
fun StopWatchDisplay(
formattedTime: String,
onStartClick: () -> Unit,
onPauseClick: () -> Unit,
onResetClick: () -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = formattedTime,
fontWeight = FontWeight.Bold,
fontSize = 30.sp,
color = Color.Black
)
Spacer(Modifier.height(16.dp))
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Button(onStartClick) {
Text("Start")
}
Spacer(Modifier.width(16.dp))
Button(onPauseClick) {
Text("Pause")
}
Spacer(Modifier.width(16.dp))
Button(onResetClick) {
Text("Reset")
}
}
}
}
코틀린을 배운지 한 달정도의 시간이 흐른 것 같은데요,
너무 배울 게 많아서 뭐 부터 배워야할지 모를 정도로 바쁜 나날을 보내고 있습니다.
코틀린 덕분에 올해는 정말 재미있는 한 해가 될 것 같아요.
How to Make a Stop Watch With Compose Desktop - Philipp Lackner
https://www.youtube.com/watch?v=Iw4qFryus4Q