本文同步发表于我的微信公众号,在微信搜索
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
学习任何技术,首先拜读官文,无一例外。
第一周
题目:小狗领养应用
要求:包含显示小狗列表的概览画面,以及显示每只小狗具体情况的详细信息画面。
知识点:
- 基础控件:Column、Modifier、Card、Box、Text、Icon、Image、IconButton、Spacer等
- 控件修饰:Modifier
- 可变状态:mutableStateOf
定义数据
1// 狗狗实体 2data class Dog(val name: String, val avatar: Int, val desc: String) 3 4// 狗狗列表 5object DogPool { 6 val Dogs = listOf( 7 Dog(getRandomString(6), getRandomAvatar(), getRandomString(100)), 8 Dog(getRandomString(6), getRandomAvatar(), getRandomString(100)), 9 Dog(getRandomString(6), getRandomAvatar(), getRandomString(100)), 10 Dog(getRandomString(6), getRandomAvatar(), getRandomString(100)), 11 Dog(getRandomString(6), getRandomAvatar(), getRandomString(100)), 12 Dog(getRandomString(6), getRandomAvatar(), getRandomString(100)), 13 ) 14} 15 16// 狗狗头像素材 17val avatars = listOf( 18 R.drawable.dog_one, 19 R.drawable.dog_two, 20 R.drawable.dog_three, 21 R.drawable.dog_four, 22 R.drawable.dog_five, 23 R.drawable.dog_six 24) 25 26// 随机产生狗狗头像 27fun getRandomAvatar(): Int { 28 return avatars[Random.nextInt(0, 5)] 29} 30 31// 随机生成固定长度字符串 32fun getRandomString(length: Int): String { 33 val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz" 34 return (1..length) 35 .map { allowedChars.random() } 36 .joinToString("") 37}
列表界面
使用Column展示一个纵向列表,使用Modifier调整布局元素的各种属性。
1Column(modifier = Modifier.verticalScroll(rememberScrollState())) { 2 Spacer(modifier = Modifier.size(16.dp)) 3 DogPool.Dogs.forEach { 4 Box(Modifier.padding(8.dp)) { 5 DogView( 6 dog = it, 7 modifier = Modifier 8 .fillMaxWidth() 9 .clickable { selectedDog = it } 10 ) 11 } 12 } 13}
列表项
1@Composable 2fun DogView(dog: Dog, modifier: Modifier = Modifier) { 3 Card(modifier, shape = RoundedCornerShape(26.dp)) { 4 Box { 5 Image( 6 painterResource(dog.avatar), 7 null, 8 modifier = Modifier.fillMaxWidth(), 9 contentScale = ContentScale.FillWidth 10 ) 11 Box( 12 modifier = Modifier 13 .align(Alignment.BottomStart) 14 .background( 15 Brush.verticalGradient( 16 listOf( 17 Color.Transparent, 18 MaterialTheme.colors.onSurface 19 ) 20 ) 21 ) 22 .fillMaxWidth() 23 .padding(26.dp) 24 ) { 25 Text( 26 text = dog.name, 27 style = MaterialTheme.typography.h5, 28 color = MaterialTheme.colors.surface 29 ) 30 } 31 } 32 } 33}
详情界面
1@Composable 2fun DogDetails(dog: Dog) { 3 val context = LocalContext.current as? Activity 4 val scrollState = rememberScrollState() 5 6 // Calculate the offset of the background image to make it scroll with a parallax effect 7 val imageOffset = (-scrollState.value * 0.2f).dp 8 9 // Calculate the alpha used in the background of the back arrow 10 val iconBackgroundAlpha = 11 ((scrollState.value / START_TOP_PADDING.toFloat()) * 0.2f).coerceAtMost(0.2f) 12 13 Box { 14 Image( 15 painter = painterResource(id = dog.avatar), 16 contentDescription = null, 17 contentScale = ContentScale.FillWidth, 18 modifier = Modifier 19 .offset(y = imageOffset) 20 .height(200.dp) 21 .fillMaxWidth() 22 ) 23 24 Column( 25 Modifier 26 .verticalScroll(scrollState) 27 .padding(top = START_TOP_PADDING.dp) 28 .background( 29 MaterialTheme.colors.surface, 30 RoundedCornerShape(topStart = 3.dp, topEnd = 20.dp) 31 ) 32 .fillMaxHeight() 33 .fillMaxWidth() 34 .padding(all = 32.dp) 35 ) { 36 Text("Hello I Am", style = MaterialTheme.typography.h6) 37 Spacer(Modifier.size(10.dp)) 38 Text(text = dog.name, style = MaterialTheme.typography.h3) 39 Spacer(Modifier.size(16.dp)) 40 Spacer(modifier = Modifier.size(16.dp)) 41 Text(text = dog.desc) 42 } 43 44 IconButton( 45 onClick = { context?.onBackPressed() }, 46 modifier = Modifier 47 .padding(8.dp) 48 .background(Color.Black.copy(alpha = iconBackgroundAlpha), shape = CircleShape) 49 ) { 50 Icon( 51 painter = painterResource(id = R.drawable.ic_arrow_back), 52 contentDescription = null, 53 modifier = Modifier 54 .size(32.dp), 55 tint = Color.White 56 ) 57 } 58 } 59}
代码检查
./gradlew app:spotlessApply
针对Wildcard import错误,进行如下配置后删除对应以*号形式引入的包,重新执行引入操作。

效果


