Compose Weekly #2:Countdown Timer

onlyloveyd 等级 84 0 0

本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。

前言

最近Android官方发起了Jetpack Compose的推广活动:Jetpack Compose开发者挑战赛。活动时间一个月,每周一题,广大开发者根据官方需求,Clone官方模板工程并使用Jetpack Compose技术结题后按要求提交,即可参与活动。今天抽空完成了第二题,有点丑陋,感兴趣的同学可以做个漂亮点的。

环境

第二周

题目:Countdown Timer

要求:创建一个有效的单屏倒数计时器。

知识点:

思路

简单的计时器操作:设置计时时长,开始计时,等待计时结束或者手动暂停计时。

  • 界面元素:(1)倒计时进度条;(2)时分秒设置计时长度;(3)重置计时按钮、开始计时按钮
  • 可变状态:(1)时长(时分秒);(2)倒计时进度与总时长;(3)计时状态(是否已开始)

倒计时进度条

@Composable
fun counterDown(modifier: Modifier, seconds: Int) {
    ConstraintLayout(
        modifier = modifier
            .fillMaxWidth()
            .fillMaxHeight()
    ) {
        val viewModel: MainViewModel = viewModel()
        val (progressBackground, progress, countdownTimer) = createRefs()

        CircularProgressIndicator(
            1f,
            modifier = Modifier
                .constrainAs(progressBackground) {
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(parent.bottom)
                }
                .height(300.dp)
                .width(300.dp),
            strokeWidth = 32.dp, color = Color.LightGray
        )

        Progress(
            Modifier
                .constrainAs(progress) {
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(parent.bottom)
                }
                .height(300.dp)
                .width(300.dp),
            countdownSeconds = viewModel.clock, totalSeconds = viewModel.totalClock
        )

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .constrainAs(countdownTimer) {
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(parent.bottom)
                },
            horizontalArrangement = Arrangement.Center,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = seconds.div(3600).toString(),
                fontSize = 48.sp,
                fontFamily = FontFamily.Monospace,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold
            )
            Text(
                text = ":",
                fontSize = 48.sp,
                fontFamily = FontFamily.Monospace,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold
            )
            Text(
                text = seconds.rem(3600).div(60).toString(),
                fontSize = 48.sp,
                fontFamily = FontFamily.Monospace,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold
            )
            Text(
                text = ":",
                fontSize = 48.sp,
                fontFamily = FontFamily.Monospace,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold
            )
            Text(
                text = seconds.rem(60).toString(),
                fontSize = 48.sp,
                fontFamily = FontFamily.Monospace,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold
            )
        }
    }
}

设置时长

@Composable
fun timePicker(modifier: Modifier) {
    val viewModel: MainViewModel = viewModel()
    Row(
        modifier = modifier
            .fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceAround
    ) {
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            IconButton(
                onClick = { viewModel.incHour() },
                Modifier
                    .background(
                        Color.LightGray,
                        shape = shapes.large
                    )
                    .size(32.dp, 32.dp),
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_inc),
                    contentDescription = null,
                    modifier = Modifier
                        .size(18.dp),
                    tint = Color.Black
                )
            }
            Text(
                text = viewModel.hours.toString(),
                fontSize = 32.sp,
                fontFamily = FontFamily.Serif,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.padding(0.dp, 8.dp)
            )
            IconButton(
                onClick = { viewModel.decHour() },
                Modifier
                    .background(
                        Color.LightGray,
                        shape = shapes.large
                    )
                    .size(32.dp, 32.dp),
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_dec),
                    contentDescription = null,
                    modifier = Modifier
                        .size(18.dp),
                    tint = Color.Black
                )
            }
        }
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            IconButton(
                onClick = { viewModel.incMinute() },
                Modifier
                    .background(
                        Color.LightGray,
                        shape = shapes.large
                    )
                    .size(32.dp, 32.dp),
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_inc),
                    contentDescription = null,
                    modifier = Modifier
                        .size(18.dp),
                    tint = Color.Black
                )
            }
            Text(
                text = viewModel.minutes.toString(),
                fontSize = 32.sp,
                fontFamily = FontFamily.Serif,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.padding(0.dp, 8.dp)
            )
            IconButton(
                onClick = { viewModel.decMinute() },
                Modifier
                    .background(
                        Color.LightGray,
                        shape = shapes.large
                    )
                    .size(32.dp, 32.dp),
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_dec),
                    contentDescription = null,
                    modifier = Modifier
                        .size(18.dp),
                    tint = Color.Black
                )
            }
        }
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            IconButton(
                onClick = { viewModel.incSecond() },
                Modifier
                    .background(
                        Color.LightGray,
                        shape = shapes.large
                    )
                    .size(32.dp, 32.dp),
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_inc),
                    contentDescription = null,
                    modifier = Modifier
                        .size(18.dp),
                    tint = Color.Black
                )
            }
            Text(
                text = viewModel.seconds.toString(),
                fontSize = 32.sp,
                fontFamily = FontFamily.Serif,
                fontStyle = FontStyle.Normal,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.padding(0.dp, 8.dp)
            )
            IconButton(
                onClick = { viewModel.decSecond() },
                Modifier
                    .background(
                        Color.LightGray,
                        shape = shapes.large
                    )
                    .size(32.dp, 32.dp),
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_dec),
                    contentDescription = null,
                    modifier = Modifier
                        .size(18.dp),
                    tint = Color.Black
                )
            }
        }
    }
}

重置计时、开始计时

@Composable
fun bottomMenu(modifier: Modifier) {
    val viewModel: MainViewModel = viewModel()
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceEvenly,
        verticalAlignment = Alignment.CenterVertically
    ) {
        IconButton(onClick = { viewModel.reset() }) {
            Icon(
                painter = painterResource(id = R.drawable.ic_reset), contentDescription = null,
                modifier = Modifier
                    .size(32.dp),
                tint = Color.Black
            )
        }

        if (!viewModel.started) {
            IconButton(onClick = { viewModel.startCountdown() }) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_start), contentDescription = null,
                    modifier = Modifier
                        .size(32.dp),
                    tint = Color.Black
                )
            }
        }
    }
}

效果

设置时长

倒计时

源码

https://github.com/onlyloveyd/Jetpack-Compose-CountdownTimer

预览图
收藏
评论区
守株待兔
最新文章
Android抖音去水印APP 2021-02-25 06:55
协变和逆变 2021-02-23 22:17

导读