Compose Weekly #3:Bloom

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

前言

第三周挑战赛是速度比拼,按照官方发出的设计图最快完成且符合所有设计规范者胜出。不仅要做得快,还要做得好,奖品自然不会少。这一期的奖品是:Google Pixel 5。深知干不过业界大佬们,花个半天纯当练手完成题目。

设计图

设计风格

设计风格

界面导航

界面导航

界面标注

界面标注

完整设计图:https://github.com/android/android-dev-challenge-compose/blob/assets/Bloom.zip

知识点

  • 主题:自定义主题
  • 列表:LazyColumn、LazyRow
  • 文字:文本输入框、风格化文本、自定义字体
  • 导航:基础使用、底部导航栏集成

关键实现

定义主题

界面布局中使用主题元素配置color、shape、typography等内容。localImages、localElevations为自定义内容。

@Composable fun BloomTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) { val colors = if (darkTheme) { DarkColorPalette } else { LightColorPalette } val images = if (darkTheme) DarkImages else LightImages val elevations = AllElevations CompositionLocalProvider( localImages provides images, localElevations provides elevations ) { MaterialTheme( colors = colors, typography = typography, shapes = shapes, content = content ) } } object BloomTheme { val colors: Colors @Composable get() = MaterialTheme.colors val typography: Typography @Composable get() = MaterialTheme.typography val shapes: Shapes @Composable get() = MaterialTheme.shapes val images: Images @Composable get() = localImages.current val elevations: Elevations @Composable get() = localElevations.current }
@Immutable data class Images( @DrawableRes val welcomeBackground: Int, @DrawableRes val welcomeIllos: Int, @DrawableRes val welcomeLogo: Int ) internal val localImages = staticCompositionLocalOf<Images> { error("No LocalImages specified") }

风格化文本

val termsString = buildTermsString( stringResource(R.string.login_terms), listOf( stringResource(R.string.terms), stringResource(R.string.privancy) ) ) Text( text = termsString, textAlign = TextAlign.Center, modifier = Modifier.paddingFromBaseline( top = 24.dp, bottom = 16.dp ) )
fun buildTermsString(source: String, segments: List<String>) = buildAnnotatedString { append(source) for (segment in segments) { val startIndex = source.indexOf(segment) val endIndex = startIndex + segment.length addStyle( style = SpanStyle(textDecoration = TextDecoration.Underline), start = startIndex, end = endIndex ) } }

带边框密码文本输入

TextField( modifier = Modifier .height(56.dp) .fillMaxWidth() .border( // 设置边框 width = 1.dp, color = Color(0xFF9E9E9E), shape = BloomTheme.shapes.small ), value = password, onValueChange = { password = it }, singleLine = true, placeholder = { Text( text = stringResource(R.string.password_hint), style = BloomTheme.typography.body1, ) }, textStyle = BloomTheme.typography.body1, colors = TextFieldDefaults.textFieldColors( backgroundColor = Color.Transparent, textColor = BloomTheme.colors.onPrimary ), visualTransformation = PasswordVisualTransformation(), // 密码形式 keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password) // 密码安全键盘 )

底部导航栏

sealed class Screen( val route: String, @StringRes val resourceId: Int, val icon: ImageVector ) { object Home : Screen("home", R.string.home, Icons.Filled.Home) object Favorites : Screen("favorite", R.string.favorites, Icons.Filled.FavoriteBorder) object Profile : Screen("profile", R.string.profile, Icons.Filled.AccountCircle) object Cart : Screen("cart", R.string.cart, Icons.Filled.ShoppingCart) } val items = listOf( Screen.Home, Screen.Favorites, Screen.Profile, Screen.Cart ) @Composable fun Main() { val navController = rememberNavController() Scaffold( bottomBar = { BottomNavigation( modifier = Modifier .navigationBarsPadding() .height(56.dp), backgroundColor = MaterialTheme.colors.primary, contentColor = MaterialTheme.colors.onPrimary, elevation = BloomTheme.elevations.bottomNavigation ) { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.arguments?.getString(KEY_ROUTE) items.forEach { screen -> BottomNavigationItem( selected = currentRoute == screen.route, onClick = { navController.navigate(screen.route) { popUpTo = navController.graph.startDestination launchSingleTop = true } }, icon = { Icon( imageVector = screen.icon, contentDescription = stringResource(id = screen.resourceId), modifier = Modifier.size(24.dp, 24.dp), tint = MaterialTheme.colors.onPrimary ) }, label = { Text( stringResource(id = screen.resourceId), style = MaterialTheme.typography.caption ) } ) } } } ) { NavHost(navController, startDestination = Screen.Home.route) { composable(Screen.Home.route) { Home() } composable(Screen.Favorites.route) { Favorites() } composable(Screen.Profile.route) { Profile() } composable(Screen.Cart.route) { Cart() } } } }

效果

Welcome

Welcome

Login

Login

Home

Home

源码

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

协变和逆变

本文同步发表于我的微信公众号,在微信搜索OpenCVorAndroid即可关注。协变、逆变概念许多程序设计语言的类型系统支持子类型。例如,如果Cat是Animal的子类型,那么Cat类型的表达式可用于任何出现Animal类型表达式的地方。所谓的变型(variance)是指如何根据组成类型之间的子类型关系,来确定更复杂的类型之间(例如C

Compose Weekly #2:Countdown Timer

本文同步发表于我的微信公众号,在微信搜索OpenCVorAndroid即可关注。前言最近Android官方发起了JetpackCompose的推广活动:JetpackCompose开发者挑战赛。活动时间一个月,每周一题,广大开发者根据官方需求,Clone官方模板工程并使用JetpackCompose技术结题后按要求提交,即可参与活动。