Jetpack Compose竟能写出如此炫酷的倒计时APP!

# Compose开发者应战赛二周目

为协作Jetpack Compose beta版的发布,Google官方发起了Compose开发者应战赛活动,现在现已入二周目 android-dev-challengeapplication-2

Jetpack Compose竟能写出如此炫酷的倒计时APP!
第二周的标题是运用Compappearanceose完毕倒计时app 。标题出的十分稳妥,难度不高,可是能引导我们有针对性地去学习Compose的某些特性,比方这google个app的完毕canvas标签appear求我们学习和了解state以及animations的运用。

Note:对Composcanvas动漫e开发者应战赛google地球及其参与方android是什么手机牌子法有喜爱的朋友能够参看:《Jetpack Compose 开发应战赛》

以下是我完毕的项目:TikTik
Jetpack Compose竟能写出如此炫酷的倒计时APP!

项目中运字体转换器用的都是Compose最基础的API,花时刻不多,但完毕作用还比较满意,可见Compose的确有助于提升UI开发功率,这儿简略与我们分享一下完毕进程。

# App完毕

1. 画面构成

Jetpack Compose竟能写出如此炫酷的倒计时APP!

app由两个画面构成:

  • 输入画面(InputScreen) :
    google空间过数字软键盘输入时刻,当新输入数字时,悉数数字左appearance移;backspace回退最近一次输入时,悉数数字右移。相似核算器aappleidpp的输入和闪现逻辑。
  • 倒计时画Google面(Cogoogle浏览器untdownScreen):
    android下载软件app现其时剩余时刻并配有动画作用;依据剩余时刻的不同,文字格式和大小会做出改动:最终10秒倒计时的文字也有更夺目的缩放动画。
more than 1h more than 1m & less than 1h less than 1m
Jetpack Compose竟能写出如此炫酷的倒计时APP! Jetpack Compose竟能写出如此炫酷的倒计时APP! Jetpack Compose竟能写出如此炫酷的倒计时APP!

state操控页面跳转

页面之间的跳转逻辑:

  • InputScreen完毕输入字体大小怎么调后,点击底部Next,跳转到CountdownScreen进入倒计时
  • CountdownScreen点击底部Cancel,回来InputScreen

Compose没有Activitycanvas下载Fragment这样的页面处理单元,所谓的页面只不过是一个全屏的Composable,一般能够运用state完毕。凌乱的页面场景能够凭借navigatiocanvas下载n-compose

enum class Screen {
Input, Countdown
}
@Composable
fun MyApp() {
var timeInSecandroid下载 = 0
Surface(color = MaterialTheme.colors.background) {
var s字体规划creen by remember { mutableStateOf(Screen.Input) }
Crossfade(targetState = screen) {
whenandroid是什么手机牌子 (scapprovereen) {
Screen.Incanvas软件put -> InputScreen {
screen = Screen.CountdownScreen
}
Screen.Countdown -> CountdownScreen(timeInSec) {
screen = Screencanvas动漫.Input
}
}
}
}
}
  • screen: 运字体管家用state保存并监听其时页面google空间的改动,
  • CrossfadeCrossfade能够淡入淡出的切换内部布局;内部依据screen切换不同页面。
  • tandroid的drawable类imeInSec:Inputandroid体系Screen的输入存入timeInSec,并携带到CountdownScreen

2. 输入画面(InputScreen)

Jetpack Compose竟能写出如此炫酷的倒计时APP!

InputgoogleplayScreen包括以下元素:

  1. 输入作用:input-value
  2. 回退:backspace
  3. 软键盘:softkeybappearoard
  4. 底部:next

依据其字体规划时的输入作用,画面各元素会发生改动。

  • 当有输入作用时:next闪现、backspace激活、input-value高亮;
  • 反之,next躲藏、backspace禁用、字体全国input-value低appearance

state驱动UI改写

假定用传统写法会比较烦琐,需求在影响输入作用的当地设置监听,google浏览器例如本例中需求分别监听baandroid体系ckspace和next。当输入改动时指令式地去批改相关字体大师元素,页面凌乱度会跟着页面元素增字体下载多呈指数级添加。

运用Compose则简略得多,我们只需求canvas渠道将输入作用包装成state并监听,当state改动时,悉数Composable从头实施、更新情况。即使元素增多也不会影响已有代码,凌乱度不会android/yunos添加。

var input by remember {
mutableStateOf(listOf<Int>())
}
val hasCountdownValue = remember(input) {
inapplicationput.isNotEmpty()
}
  • mutabl字体美化大师免费下载eStateOf创立一个可改动的state,经过by署理进行google地球订阅,当statappearancee改动时其时Composacanvas软件ble会从头实施。
  • 因为Composable会重复实施,运canvas交大remember{appearance}能够防止因为Compcanvas渠道osable的实施重复而canvas动漫重复googleplay创立state实例。
  • android的drawable类remember的参数改动时,block会从头实施,上面例子中,当input改动时,判别input是否为空并android下载软件app保存在hasCountdownValuandroid体系e中,供其他Composable参照。
Column() {
...
Row(
Modifier
.fillMaxWidth()
.height(100.dp字体大小怎么调)
.padding(start = 30.d字体规划p, eandroid的drawable类nd = 30.dp)
) {
//Input-value
listOandroid体系f(hou to "h", min to "m", sec to "s").forEach {
DisplayTime(it.first, itapplication.secondcanvas动漫, hasCountdownValue)
}
//Backgoogle查找引擎进口口space
Imagooglege(
imageVector = Icons.Default.Backspace,
cgoogle谷歌查找主页ontentDescription = null,
colorFilter = ColorFilter.tint(
Color.Unspecified.copy(
//依据hasCountdownValue闪现不同亮度
if (hasCountdownValue) 1.0f else 0.5f
)
)
)
}
..google地球.
//依据hasCountdownValue,是否闪现next
if (hascanvas软件CountdownValue) {
Image(
imageVector = Icons.Default.PlayCirclecanvas下载,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheappleme.colors.primary)
)
}
}canvas中文

如上,声明UI的一起参与hasCountdowncanvas渠道Value的判别逻辑,然后等候再次改写就OK,无需像传统写法那样设置监听并指令式地更新UI。

3. 倒计时画面(CountdownScreen)

Jetpack Compose竟能写出如此炫酷的倒计时APP!

CountdownScreen主要包括以下元素:

  1. 文字部分:闪现hour、second、minutes 以及ms
  2. 气氛部分:多个不同类型的圆形动画
  3. 底部Cancel

运用animation核算倒计时

怎么准确地核算倒计时呢?

开端的方案是运用canvas交大flow核算倒计时,然APP后将flow转成state,驱动UI改写:

private fun interval(sum: Long, step: Long): Flow<Long> = flow {
while (sum > 0) {
delayandroid下载(step)
sum -= step
emit(sum)
}
}

可是经过字体美化大师查验发现,因为协程切换也有开支,运用delay处理倒计时并不准确。

APP过考虑决定运用animation处理倒计时

var trigger by remember { mutableStateOf(timeInSec) }
val elapsapp装置下载ed by animateIntAsState(
targetValue = trigger * 1000,
animatandroid/yunosionSpec = tween(timeInSec * 1000, easandroid下载装置ing = LinearEasing)
)
DisposableEffect(Unit) {
trigger = 0
onDispose { }
}
  • Compose的动画也是通canvas中文过state驱动的, animateIntAsState界说动画、核算动画估值appearance并转成state。
  • 动画由targetValue的改动触发发动。
  • animationSpec用来配备动画类型,例如这儿经过tweenandroid下载装置配备一个线性的补间动画。duration设置为timeInSec * 1google服务结构000 ,也便是倒计不时长的ms。
  • DisposableEappearanceffect用来在纯函数中实施副作用。假定参数发生改动,block中的逻辑会在每次重绘(Composition)时实施。 DisposableEffect(Unit)因为参googleplay数永久不会改动,意味着block只会在第一次上屏时只实施一次。
  • triggeappleidr初始情况为字体下载timeInSec(倒计时总时长),然后在第一次上屏时设置为0,targetValue改动触Canvas发了动画:从timeIappearnSec*1000 实施到android的drawable类 0 ,duration为timeInSec*1000 ,动画完毕appleid时便是倒计时的完毕,而且Android必定准确,没有差错。

接下来只需求将elapsed换算成合适的文字闪现就OK了

val (hou, min, sec) = remember(elapsed字体 / 1000) {
val elapsedInSec = elapsed / 1000
val hou = elapsedInSec / 3600
val min = elapsedInSec / 60 - hou * 60
val sec = elapsedInSec % 60
Tripl字体规划e(hou, minCanvas, sgoogle网站登录进口ec)
}
...

字体动态改动

剩余时刻的改动,带来文字内容和字体大小不同。这个完毕十分简略,只需Composable中设置size的时分判别剩余时刻就好了。


//依据剩余时刻设置字体大小
val (sizegoogle谷歌查找主页, lab字体规划elSize) = when {
hou > 0 -> 40.sp to 20.sp
min > 0 -> 80.sp to 30.sp
else -> 150.sp to 50.sp
}
...
Row() {
if (hou > 0) {//当剩余时刻短少一小不时,不闪现h
DisplayTime(
hou.fo字体大师rmatTime(),
"h",
fontSize = size,
labelSize = labelSize
)
}
if (min > 0) {//剩余时刻短少1分钟,不闪现m
DisplayTime(
min.formatTime(),字体全国
"m",
fontSize = size,
labelSize = labelSize
)
}
DisplayTimcanvas标签e(
sec.f字体ormatTime(),
"s",
fontSize = size,
labelSize = labelSize
)
}

气氛动画

气氛动画对进步App质感很重要,app中运用了如下几种动画烘托气氛:

  • 正圆呼吸灯作用:1次/2秒
  • 半圆环跑马灯作用字体转换器:1次/1秒
  • 雷达动画:倒计时完毕时扫描发展100%
  • 文字缩放:倒计时10秒缩放,1次/1秒

这儿运用transition同步多个动画

    v字体美化大师免费下载al transition = rem字体美化大师免费下载emberInfiniteTransition()
var trigger by remember { mutableStateOf(0f) }
//线性动画完毕雷达动画
val animateTween by animateFloatAsState字体规划(
targetValue = trigger,
animationSpec = tween(
durationMillis = durationMills,
easing = LinearEasing
),
)
//infiniteRepeatable+restart完毕跑马灯
val animatedRestaapp装置下载rt by transitiongoogle查找引擎进口口.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpeandroid是什么手机牌子c = infinitegoogle查找引擎进口口Repeatable(tween(1000), RepeatMode.Restandroid的drawable类art)
)
//infiniteRepeatable+rever字体大小怎么调se完毕呼吸灯
val animatedReverse by transition.animateFloat(
initialValue = 1.05f,
targetValue = 0.95f,
animationSpec = infiniteRepeatable(tween(2000), RepeatMode.Reverse)
)
//infiniteRepeatable+reverse完毕文字缩放
val animatedFont by transition.animateFloat(
initialValue = 1.5f,
targetValue = 0.8f,
animationSpec = infiniteRepeatable(tween(500), RepeatMode.Reverse)
)
  • rememberInfiniteTransition创立了一个repeatable的transition,transition经过animateXXX创立多个动画(state),同一个transition创立的动画坚持同步。app中创立了3个canvas中文动画:animatedRestartanimatedReverseanimatedFont
  • transition中也能够android/yunos设置animationSpec。app中配备的infandroid/yunosiniteRepeatable是一个repeat动画,能够经过参数设置duration以及RepeatMode

字体美化大师免费下载造圆环图形

接下来就能够依据上面创立的动画state制作各种圆形的气氛了,经过不断地compoition完毕动画作用。

Canvas(字体全国
modifier = Modifier
.align(CanvasAligngooglement.Centergoogle)
.padding(16.dp)
.siandroid什么意思ze(350.dp)
) {
val diameter = size.mcanvas软件inDimension
val radius = diameter字体美化大师 / 2f
val size = Size(radius * 2, radius * 2)
//android平板电脑价格跑马灯半圆
drawArc(
color = color,
startAngle = animatedRestart,
sweepAngle = 150f,
size = size,
style = Stroke(15f),
)
//呼吸灯整圆
drgoogle服务结构awCircle(
color = secondColor,
style = strokeReverse,
radius = radius * aandroid的drawable类nim字体大师atedReverse
)
//雷达扇形
drawArc(
startAngle = 270f,
sweepAngle = animateTween,
brush = Brush.radiagooglelGradiCanvasent(
radius = radius,
colors = listOf(
purple200.copy(0.3f),
teal200.copy(0.2f),
Color.White.copy(0.3f)
),
),
useCenter =android的drawable类 true,
sgoogle查找引擎进口口tyle = Fill,
)
}
  • Canvas{}能够制作自界说图形。Android
  • drawArc用来制作一个带角度的弧形,startAnglesweepAngle设置弧在圆上的 其实方位,这儿设置startAngle为animatedRestart,依据state的改动完毕动画作用。style设置为Stroke表明只制作边框,设置为Fill则表明填充这个Canvas弧形区域构成扇形。
  • drawCircle用来制作一个正圆,这儿经过animatedReverse,改动半径完毕呼吸灯作用

Note: 关于Compose动画的更多内容能够参看 《一文学会运用Jetpack Compose Animations》

# 总结

Compose的中心是Standroid下载软件appate驱动Uandroid什么意思I改写,animatiappstoreon也是googleplay依托state来完毕动画。因此apple除了服务于视觉作用,animation还能够用来核算state。到这时才恍然大悟组织方在标题描绘中提示可能会用到animation,其更主要的目的是用来准确核算countdown的最新情况。

CountdownTimer这样的项目很合适拿来给新技google翻译术练手,第二周应战截止日是3月10日,而且后边还有两个应战,都是以鼓励新手为主所以难度应该不会很高。假定你还没有触摸过Compose,无妨趁这个机遇尝尝鲜吧~

项目appearance地址:TikTik