Compose Weekly #2:Countdown Timer

onlyloveyd 等级 725 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
                )
            }
        }
    }
}

效果

Compose Weekly #2:Countdown Timer

Compose Weekly #2:Countdown Timer

源码

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

收藏
评论区

相关推荐

Compose Weekly #1: 小狗领养应用
本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。 前言 最近Android官方发起了Jetpack Compose的推广活动:Jetpack Compose开发者挑战赛。活动时间一个月,每周一题,广大开发者根据官方需求,Clone官方模板工程并使用Jetpack Compose技术结题后按要求提交,即可参与活动。
Compose Weekly #2:Countdown Timer
本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。 前言 最近Android官方发起了Jetpack Compose的推广活动:Jetpack Compose开发者挑战赛。活动时间一个月,每周一题,广大开发者根据官方需求,Clone官方模板工程并使用Jetpack Compose技术结题后按要求提交,即可参与活动。
Compose Weekly #3:Bloom
本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。 前言第三周挑战赛是速度比拼,按照官方发出的设计图最快完成且符合所有设计规范者胜出。不仅要做得快,还要做得好,奖品自然不会少。这一期的奖品是:Google Pixel 5。深知干不过业界大佬们,花个半天纯当练手完成题目。 设计图 设计风格 界面导航 界面标注 完整设计图:
Compose Weekly #4:Weather App
本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。 前言 It's raining... Compose! Pull out all the stops for this final challenge. Build a beautiful weather app for a chance to win a Pixel
04.fabric的swarm集群布署:docker
首先swarm集群为什么使用docker-composer v3来发布: 现在只有v3支持deploy属性(是docker swarm相关配置) 参考:[https://docs.docker.com/compose/compose-file/compose-versioning/#version-3](https://www.oschina.net/a
FIR.im Weekly
本期我们收录的文章有旧主题的延伸,还涉及了新的开发主题,摘要如下: ### Android 性能优化课程笔记 在 [FIR.im Weekly - 不要只做表面功夫](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fblog.fir.im%2F2015%2Fweekly_150407%2F
Docker Compose 版本过高(Docker版本不匹配),降低docker
通过docker-compose启动容器,报错: ERROR: The Docker Engine version is less than the minimum required by Compose. Your current project requires a Docker Engine of version 1.10.0 or grea
Docker Compose、Swarm 集群管理
  docker-machime和compose、swarm被称为docker三剑客。docker-machine是解决docker运行环境问题,之前已经研究过,下面研究compose和swarm。 1.Docker Compose ----------------   dcoker-compose主要是解决本地docker容器编排问题。当然也可以自己编
Docker Compose集成式应用组合及service编排
### Compose简介 Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。其代码目前在 [https://github.com/docker/compose](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdocker
Docker 入门指南
> 原文见: [https://docker-curriculum.com/#docker-compose](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fdocker-curriculum.com%2F%23docker-compose) 最近在看Docker的相关知识,在耗子叔专栏的推
LeetCode 1253. 重构 2 行二进制矩阵
题目链接:[https://leetcode-cn.com/contest/weekly-contest-162/problems/reconstruct-a-2-row-binary-matrix/](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fleetcode-cn.com%2Fco
Netty(7)
改造timer,即客户端与服务端建立连接后,服务端主动向客户端发送当前时间。 server: ch.pipeline().addLast(new TimeEncoder()); ch.pipeline().addLast(new TimeServerHandler()); TimeServerHandler public cl
Python之yield语法
生成器与yield --------- 函数使用yield关键字可以定义生成器对象。生成器是一个函数。它生成一个值的序列,以便在迭代中使用,例如: 1 def countdown(n): 2 print('倒计时:%s' % n) 3 while n > 0: 4 yield n 5
QUIC Weekly 每周一草(20201202期)
QUIC Weekly - 20201202期 ----------------------- * 📽 Robin Marx 的 [QUIC和HTTP/3的队头阻塞:细节](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fcalendar.perfplanet.com%2F2020%2
sum
sum-svn-w.sh #! /bin/sh export LC_ALL=zh_CN.UTF-8 cd /bin2/ sh sum-svn-weekly.sh > sum-svn-weekly.sh.log 2>&1 /usr/bin/mutt -s "scm11-scm12 sum-svn-weekl