Compose Weekly #2:CountDown Timer

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

前言

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

环境

  • 活动地址:https://developer.android.google.cn/dev-challenge
  • 官方教程:https://developer.android.google.cn/jetpack/compose/documentation
  • Github模板:https://github.com/android/android-dev-challenge-compose
  • Android Studio (Canary build):https://developer.android.com/studio/preview

第二周

题目:Countdown Timer

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

知识点:

  • 状态:https://developer.android.google.cn//jetpack/compose/state
  • 动画:https://developer.android.google.cn/jetpack/compose/animation

思路

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

  • 界面元素:(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
根据您提供的引用内容,您在安装docker-compose时遇到了一些问题。错误信息显示"/usr/local/bin/docker-compose: line 1: html: No such file or directory /usr/local/bin/docker-compose: line 2: syntax error near unexpected token `<'"。解决这个问题的方法有两种。 第一种方法是重新安装docker-compose。有些国内的快捷方式可能存在问题,所以建议直接从GitHub上下载安装。您可以使用以下命令来重新安装docker-compose: ``` curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose ``` 如果一次下载不成功,可以多执行几遍命令。 第二种方法是使用另一个命令来安装docker-compose。您可以使用以下命令来安装docker-compose: ``` curl -L "https://get.daocloud.io/docker/compose/releases/download/v1.25.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose ``` 希望这些方法能够帮助您解决问题。如果还有其他疑问,请随时提问。 #### 引用[.reference_title] - *1* *2* [安装docker-compose出现错误html: No such file or directory syntax error near unexpected token `‘ ...](https://blog.csdn.net/zhangmingfie/article/details/130693070)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [/usr/local/bin/docker-compose:行1: {error:Document not found}: 未找到命令](https://blog.csdn.net/qq_41840735/article/details/128673178)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndroidKt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值