Jetpack Compose实战教程(二)

Jetpack Compose实战教程(二)

第二章 实战一个简易的页面



一、本章目标

在这里插入图片描述
上图即为我们本章要实现的功能,看起来很简单,如果使用xml的话,相信各位看官很快就能实现出来,那么我们来看一下,如果是使用xml的话,我们大致需要哪些:
1.设置全屏背景为黑色
2.头部有一个横向布局(返回图片和标题)
3.滚动布局(scrollview),里面嵌套一个线性布局
4.几个文本Textview

二、了解我们本章将要用到的几种布局

本章我们将要用到的布局分别有Box、Column、Row,它们也是我们接下来的开发实践中使用的最多的布局方式,用一张图来看看它们的区别
在这里插入图片描述

2.1 Box布局

Box布局类似于我们xml里面的RelativeLayout,按照编写代码的顺序,下一个布局会覆盖在上一个布局上方,起点都为左上角

2.2 Row布局

Row布局类似于我们的LinearLayout,并且设置了方向是horizontal

2.3 Column布局

Column 布局类似于我们的LinearLayout,并且设置了方向是vertical

三、开始编码

3.1 新建一个Activity

创建一个activity,并编写最基本的代码

class HeartbeatRuleActivity:ComponentActivity() {
	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //这行代码只是强制页面竖屏显示,各位看官根据需要来决定是否加这行代码
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        setContent {
            contentUI() //为了方便预览,我将布局文件抽离了出来
        }
    }
}

@Composable
    fun contentUI(){
        BaseTheme{
	        Surface(
	                modifier = Modifier.fillMaxSize(),
	                color = Color.Transparent
	            ) {
	            }
        }
    }

	@Preview(showBackground = true)
    @Composable
    fun previewUI(){
    //看到抽离出来的好处了吗?调用的同一个函数,只要有修改,就能预览了
        contentUI() 
    }

3.2 设置一个背景

根据设计图,背景是一个黑色的

	@Composable
    fun contentUI(){
        BaseTheme{
        //整体的布局使用了Surface,然后Modifier.fillMaxSize表示宽高都为屏幕的宽高
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = Color.Transparent
            ) {
            //这里同样设置Modifier.fillMaxSize(),但这个宽高是受外部的Surface的宽高限制的
            //只有当外部的Surface的宽高为屏幕的宽高,那么fillMaxSize才能达到屏幕宽高
            //就相当于我们xml里面的match_parent
            //然后设置全局背景为黑色
                Box(Modifier.fillMaxSize().background(Color.Black)) {
                /**
                *这里添加一种写法,如果背景是一张图片的话,则用到以下代码
                *各位看官可以自己试试,上面的background是不可以设置图片的
                    Image(
                        painter = painterResource(id = R.mipmap.ic_common_bg),
                        contentDescription = null,
                        Modifier.fillMaxWidth().fillMaxHeight()
                    )
                    */
                  
                }
            }
        }
    }

3.3 添加头部

同样的,我将头部的方法抽离出来

	@Composable
    fun title(){
    //Modifier.fillMaxWidth() 表示这个Box布局的宽度为屏幕的宽度
    //没有设置高度的情况下,高度就取决于内容的高度,自适应
        Box(Modifier.fillMaxWidth()){
            Image(painter = painterResource(id = R.mipmap.ic_back_white2),
                null,
                modifier = Modifier
                    .size(48.dp)
                    //根据UI图的话,图片的大小是24dp*24dp,为了扩大点击热点
                    //所以上面设置了size为48dp,然后padding为12dp
                    //这里请留意,compose里面是没有margin的,只有padding,那么到底是
                    //margin还是padding就取决于上下文以及调用padding的顺序
                    .padding(12.dp) 
                    .clickable { //添加点击事件
                        finish()
                    }
            )

            Text(
                text = "心动信号规则描述",
                //这里请留意,如果是要像我这样使用十六进制的颜色的话,一定要是argb
                //比如如果写成0xffffff是会报错的
                color = Color(0xffffffff), 
                fontSize = 18.sp,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.align(alignment = Alignment.Center)
            )
        }
    }

然后将头部添加到内容里面

@Composable
    fun contentUI(){
        BaseTheme{
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = Color.Transparent
            ) {
                Box(Modifier.fillMaxSize().background(Color.Black)) {
                   
                    Column {
                        title()
                        
                    }

                }
            }
        }
    }

3.4 添加内容

同样的,内容也抽离出来

@Composable
    fun content(){
        Column(
            Modifier
            //添加代码表示布局超过一行可以滚动,就不用写ScrollView了
                .verticalScroll(rememberScrollState()) 
                .padding(16.dp, 16.dp, 0.dp, 0.dp)) {

            Text(text = "一、心动匹配方式描述",
                fontWeight = FontWeight.Bold,
                color = Color.White,
                fontSize = 16.sp
            )

            Text(text = "内容,这里我简化了",
                Modifier.padding(top = 8.dp,end = 16.dp),
                fontSize = 12.sp,
                fontWeight = FontWeight.Bold,
                color = Color(0x99ffffff)
                )

            Text(text = "二、道具卡功能说明",
                Modifier.padding(top = 16.dp),
                fontWeight = FontWeight.Bold,
                color = Color.White,
                fontSize = 16.sp
            )

            Text(
                text = "内容,这里我简化了",
                Modifier.padding(top = 8.dp,end = 16.dp),
                fontSize = 12.sp,
                fontWeight = FontWeight.Bold,
                color = Color(0x99ffffff)
                )

            Text(
                text = "内容,这里我简化了",
                Modifier.padding(top = 12.dp,end = 16.dp),
                fontSize = 12.sp,
                fontWeight = FontWeight.Bold,
                color = Color(0x99ffffff)
            )

            Text(
                text = "内容,这里我简化了",
                Modifier.padding(top = 12.dp,end = 16.dp),
                fontSize = 12.sp,
                fontWeight = FontWeight.Bold,
                color = Color(0x99ffffff)
            )
        }
    }

然后将内容也添加进去

@Composable
    fun contentUI(){
        BaseTheme{
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = Color.Transparent
            ) {
                Box(Modifier.fillMaxSize().background(Color.Black)) {
                    
                    Column {
                        title()
                        content()
                    }

                }
            }
        }
    }

3.5 美化布局

OK,运行,界面是出来了,不过有点丑,和我们的UI图布局不太一样,表现为:

  1. 滑动到底部之后,文字都贴底了,不美观
  2. 导航条的颜色和我们的对应不上,没有做沉浸式

我们给底部也添加一个间距,文字就不会贴底了

@Composable
    fun content(){
        Column(
            Modifier
                .verticalScroll(rememberScrollState())
                .padding(16.dp, 16.dp, 0.dp, 0.dp)) {

            // ....这里省略了上面的布局代码
            //Spacer标签就类似于xml里面的View标签,这里就是设置一个空白高度
            Spacer(modifier = Modifier.height(82.dp))
        }
    }

接下来就是沉浸式了

@Composable
    fun contentUI(){
        BaseTheme{
        //添加这行代表,让内容可以延伸到导航栏
            WindowCompat.setDecorFitsSystemWindows(window, false)
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = Color.Transparent
            ) {
                Box(Modifier.fillMaxSize()) {
                    Image(
                        painter = painterResource(id = R.mipmap.ic_common_bg),
                        contentDescription = null,
                        Modifier.fillMaxWidth().fillMaxHeight()
                    )
                    Column {
                    //页面布局既然延伸到导航条了,那么我们的布局就要把导航条的空间留出来
                    //不然title布局就被导航条遮挡啦
                        Spacer(
                            modifier = Modifier.height(
                                DimenUtil.px2dp(this@HeartbeatRuleActivity,StatusBarUtils.getStatusBarHeight(this@HeartbeatRuleActivity).toFloat()).dp)
                        )
                        title()
                        content()
                    }

                }
            }
        }
    }

到此,一个简单的页面已经完工,大家一定要亲自编写代码,才会发现一些细节问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Jetpack Compose是一个全新的Android UI工具包,可以帮助开发者更快速、更简单地构建Android应用程序的用户界面。以下是一个Jetpack Compose实战项目的简介: 项目名称:Compose Countdown Timer 项目描述:这是一个基于Jetpack Compose的倒计时计时器应用程序。用户可以设置计时器的时间,并在计时器倒计时时观看动画。 实现步骤: 1.创建一个Compose项目并添加所需的依赖项。 2.创建一个计时器组件,该组件将显示计时器的当前时间,并在计时器倒计时时触发动画。 3.创建一个设置计时器时间的组件,该组件将允许用户设置计时器的时间。 4.将计时器组件和设置时间组件组合在一起,以创建一个完整的倒计时计时器应用程序。 代码示例: ```kotlin @Composable fun CountdownTimer() { var time by remember { mutableStateOf(0) } var isRunning by remember { mutableStateOf(false) } LaunchedEffect(isRunning) { while (isRunning && time > 0) { delay(1000) time-- } } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { if (time > 0) { Text( text = time.toString(), fontSize = 60.sp, fontWeight = FontWeight.Bold ) } else { Text( text = "Time's up!", fontSize = 60.sp, fontWeight = FontWeight.Bold ) } } } @Composable fun SetTime(onTimeSelected: (Int) -> Unit) { var time by remember { mutableStateOf(0) } Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Set time", fontSize = 24.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(vertical = 16.dp) ) Row( modifier = Modifier.padding(vertical = 16.dp) ) { Text( text = "Minutes:", fontSize = 18.sp, modifier = Modifier.padding(end = 8.dp) ) OutlinedTextField( value = time.toString(), onValueChange = { time = it.toIntOrNull() ?: 0 }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = Modifier.width(100.dp) ) } Button( onClick = { onTimeSelected(time) }, modifier = Modifier.padding(vertical = 16.dp) ) { Text(text = "Start timer") } } } @Composable fun ComposeCountdownTimer() { var time by remember { mutableStateOf(0) } var isRunning by remember { mutableStateOf(false) } if (time == 0) { SetTime(onTimeSelected = { selectedTime -> time = selectedTime * 60 isRunning = true }) } else { CountdownTimer() } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值