安卓jetpack compose学习笔记-UI基础学习
哲学知识应该用哲学的方式学习,技术知识也应该用技术的方式学习。没必要用哲学的态度来学习技术。
学完安卓技术能做事就ok了,安卓技术肯定是有哲学的,但是在初学阶段没必要讨论什么安卓哲学。
学习一们复杂技术的路径有很多,这里不妨碍尝试介绍一条。
1、简单概述,这个很简单。
2、自己需要学习的东西有哪有,即这个技术常用的技能。
3、学习对应技能,建立感性认识。
4、实操这些组件的使用。
5、将这些组件组合成一个完整应用。
一、概述
Jetpack Compose 是 Google 推出的一款基于 Kotlin API 的框架,旨在重新定义 Android 应用的布局方式。它通过使用可组合函数(Composable)来构建用户界面,使得开发过程更加高效、快速,并且能够减少应用的包体积,提高性能。
Jetpack Compose可以直接翻译为喷气背包组合,jetpack是形容词,compose的组合性才是主要意思。
Material Design中午意思是材料设计语言。Material Design是Google提出的设计理念,安卓的Compose技术则是这一理念的具体表现方式。
二、常用UI组件
UI组件:Button、Text等。
布局组件:Column、Row、Box三种。
参数控制:Modifier修饰符。
其他的还有控制组件,权限组件等。
1、UI组件
1)Text
一个文字组件。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.spclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent { AText() }}
}@Composable
fun AText(){Text(text = "Hello,world!",// 为了方便更容易看清fontSize =24.sp,modifier = Modifier.padding(top = 300.dp,start=100.dp))
}
效果:
其他文字输入组件:TextField、OutlinedTextField。前者是填充风格的输入框,后者的外面会带一个边框。其他操作类似。两个常用参数:
1、placeholder参数控当输入框为空时显示的内容。
2、visualTransformation控制输入框内容的视觉效果,设置为PasswordVisualTransformation()时为密码框效果,将输入框内容替换为*号进行显示。
2)Button
一个按钮组件,可以设置点击函数或者在这个按钮上面显示个文字。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Previewclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染AButton函数setContent { AButton() }}
}@Composable
fun AButton() {// 按钮的定义Button(// 点击即打印字符串onClick = {println("hello, world!")},// 填满屏幕,不填满,我的机器好像点不了。modifier = Modifier.fillMaxSize()) {Text(text = "我是按钮")}
}@Preview
@Composable
fun PreviewAButton() {AButton()
}
效果:
3)Image
一张图片。除了显示图片,这个组件还可以放在Box中用来作为一种图片背景。和Image比较类似的还有Icon组件。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Previewclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {AImage()}}
}@Composable
fun AImage() {// 加载一个矢量图Image(imageVector = Icons.Filled.Favorite,contentDescription = null,modifier = Modifier.fillMaxSize())
}@Preview
@Composable
fun PreviewAImage() {AImage()
}
效果:
4)FloatingActionButton
悬浮按钮。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.FloatingActionButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {AFloatingButton()}}
}@Composable
fun AFloatingButton() {FloatingActionButton(onClick = {println("hello, Floating!")},Modifier.padding(start = 16.dp,top = 300.dp)) { }
}@Preview
@Composable
fun PreviewAFloatingButton() {AFloatingButton()
}
效果:
5)Checkbox复选框
复选框组件。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Checkbox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {ACheckbox()}}
}@Composable
fun ACheckbox() {var checkState = remember {mutableStateOf(true)}Checkbox(checked = checkState.value,onCheckedChange = {checkState.value = itprintln("change: " + checkState.value)},modifier = Modifier.padding(top = 300.dp))println("end: " + checkState.value)
}@Preview
@Composable
fun PreviewACheckbox() {ACheckbox()
}
效果:
6)Switch单选框
单选开关。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Switch
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {ASwitch()}}
}@Composable
fun ASwitch() {var checkState = remember {mutableStateOf(true)}Switch(checked = checkState.value,onCheckedChange = {checkState.value = itprintln("change: " + checkState.value)},modifier = Modifier.padding(top = 300.dp))println("end: " + checkState.value)
}@Preview
@Composable
fun PreviewASwitch() {ASwitch()
}
效果:
7)Slider滑竿组件
可以用来做音量、亮度之类的数值调整,或者进度条。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Previewclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {ASlider()}}
}@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ASlider() {val sliderState = remember {mutableStateOf(0.3f)}Column(modifier = Modifier.fillMaxSize(),// 需要把这个列填满父空间,垂直居中才能看出来,否则Column可能太小,无法看出居中效果。verticalArrangement = Arrangement.Center) {// 显示具体值Text(text = "音量:%.0f".format(sliderState.value * 100))// 滑竿组件Slider(value = sliderState.value,onValueChange = {sliderState.value = it},)}
}@Preview
@Composable
fun PreviewASlider() {ASlider()
}
效果:
8)Dialog对话框
在需要的时候弹出一个对话框。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialogclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {ADialog()}}
}@Composable
fun ADialog() {// 因为Compose是不可变的,所以需要使用这种共享变量的方式。val state = remember {mutableStateOf(false)}Column(modifier = Modifier.fillMaxSize(),// 需要把这个列填满父空间,垂直居中才能看出来,否则Column可能太小,无法看出居中效果。verticalArrangement = Arrangement.Center) {// 使用开关触发对话框。// 因为Compose是根据变量是否改变进行渲染的模式,所以需要通过变量来控制对话框是否显示。// 比如下边通过单选框来控制对应变量。Switch(checked = state.value,onCheckedChange = {state.value = it})}// 对话框的开启和关闭实际上是由state.value来控制的if (state.value) {// properties可以设置对话框的一些东西。Dialog(// 点击对话框之外的区域关闭对话框onDismissRequest = {state.value = false}) {// 对话框实际上是用Window重新渲染的这个Box。Box(modifier = Modifier.size(300.dp, 300.dp).background(Color.White)) {Text(text = "我是对话框!")}}}
}@Preview
@Composable
fun PreviewA() {ADialog()
}
效果:
类似组件:AlertDialog。
9)进度条
Compose自带圆形和直线两种进度条。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 渲染Compose函数setContent {ACircular()}}
}@Composable
fun ACircular() {// 因为Compose是不可变的,所以需要使用这种共享变量的方式。val progress = remember {mutableFloatStateOf(0.1f)}Column(modifier = Modifier.fillMaxSize(),// 需要把这个列填满父空间,垂直居中才能看出来,否则Column可能太小,无法看出居中效果。verticalArrangement = Arrangement.Center) {// 圆形进度条CircularProgressIndicator(progress = {progress.value})// 用几个空白区域把进度条顶上去。Spacer(Modifier.requiredHeight(30.dp))// 直线进度条LinearProgressIndicator(progress = {progress.value})// 用几个空白区域把进度条顶上去。Spacer(Modifier.requiredHeight(30.dp))OutlinedButton(onClick = {if (progress.value < 1f)progress.value += 0.1felseprogress.value = 0.1f}) {Text("增加进度!")}}
}@Preview
@Composable
fun PreviewA() {ACircular()
}
效果:
2、布局组件
1)Column
一个列布局组件,将内部的其他UI组件以列的方式进行组织。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent { AColumn(name = "Bob") }}
}@Composable
fun AColumn(name: String){Column(modifier = Modifier.padding(top = 300.dp,start=100.dp)) {// Column会使用列的方式组织下述Text组件。Text(text = "hello, $name")Text(text = "我是第二列")Text(text = "我是第三列")Text(text = "...")Text(text = "我是第N列")}
}@Preview
@Composable
fun PreviewAColumn() {AColumn(name = "Bob")
}
效果:
2)Row
一个行组件。可以把这个组件里的子组件以行的方式进行组织。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {ARow()}}
}@Composable
fun ARow(){Row(modifier = Modifier.padding(top = 300.dp,start=5.dp)) {// Row会使用行的方式组织下述Text组件。Text(text = "|我是第1行|")Text(text = "我是第2行|")Text(text = "我是第3行|")Text(text = "...|")Text(text = "我是第N行|")}
}@Preview
@Composable
fun PreviewARow() {ARow()
}
效果:
3)Box
一个盒子组件。会以堆叠的方式组织子组件。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)println("onCreate")// 渲染Compose函数setContent {ABox()}}
}@Composable
fun ABox() {Box {// Box会使用堆叠的方式组织下述Compose组件。Button(onClick = {},modifier = Modifier.fillMaxSize()) { }Text(text = "|我是第1行|",modifier = Modifier.padding(top = 300.dp,start = 100.dp))}
}@Preview
@Composable
fun PreviewABox() {ABox()
}
效果:
4)Surface
一个平面组件。和Box很像,只是可以快速完成阴影等风格的设置。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 渲染Compose函数setContent {ASurface()}}
}@Composable
fun ASurface() {// 一个平面,和Box很像,自带一定的风格,可以快速设置阴影等。// 如果需要风格设置,考虑Surface。否则直接用没有风格的Box。Surface(shape = RoundedCornerShape(8.dp),modifier = Modifier.height(300.dp).width(300.dp)) {Image(imageVector = Icons.Filled.Favorite,contentDescription = null,modifier = Modifier.fillMaxSize())// Box和Surface都是堆叠的模式,行列布局需要使用Column和Row。Column(// 子组件的对齐方式,需要Column有足够的空间才能看出来。verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally,modifier = Modifier.fillMaxSize()) {// 如果没有Column,Text就会堆在一起。Text(text = "1234", color = Color.White)Text(text = "1234", color = Color.White)}}
}@Preview
@Composable
fun PreviewA() {ASurface()
}
效果:
5)Spacer
空白区域。主要用来分割不同的组件。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 渲染Compose函数setContent {ASpacer()}}
}@Composable
fun ASpacer() {Column(// 子组件的对齐方式,需要Column有足够的空间才能看出来。verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally,modifier = Modifier.fillMaxSize()) {Text(text = "1234")Text(text = "1234")Spacer(modifier = Modifier.padding(vertical = 10.dp))Text(text = "1234")Spacer(modifier = Modifier.padding(vertical = 10.dp))Text(text = "1234")}
}@Preview
@Composable
fun PreviewA() {ASpacer()
}
效果:
6)Scaffold脚手架
快速构建一个应用的基础布局。
代码:
import android.annotation.SuppressLint
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 渲染Compose函数setContent {AScaffold()}}
}data class Item(val name: String,val icon:Int
)@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AScaffold() {var selectedItem = remember { mutableStateOf(0) }var items = listOf<Item>(Item("主页", R.drawable.home),Item("列表", R.drawable.liebiao),Item("设置", R.drawable.shezhi))Scaffold(topBar = {TopAppBar(title = { Text("主页") },navigationIcon = {IconButton(onClick = {}) {Icon(Icons.Filled.Menu, null)}})},bottomBar = {NavigationBar {items.forEachIndexed { index,item ->NavigationBarItem(selected = selectedItem.value == index,onClick = {selectedItem.value = index},icon = {Icon(painterResource(item.icon), null)},alwaysShowLabel = false,label = {Text(item.name)},modifier = Modifier.size(20.dp))}}}) {Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center) {Text("主页界面")}}
}@Preview
@Composable
fun PreviewA() {AScaffold()
}
效果:
其他布局组件:ConstraintLayout约束布局,及其Barrier分界线、Guideline引导线、Chain链接约束、
3、Modifier修饰符
可以为组件应用样式设置。如边距、字体、位移等。每个基础Compose组件都有一个modifier参数,通过传入的modifier参数修改组件的样式。
代码:
Text(text = "|我是第1行|",modifier = Modifier.padding(top = 300.dp,start = 100.dp))
效果:
其他一些作用:
1、通过size修改被修饰组件的大小。
2、通过background修改被修饰组件的背景。
3、通过fillMaxSize让被修饰组件填满父组件的空间。
4、通过border为被修饰组件添加边框。通过padding为被修饰组件增加间隙。
5、通过offset移动被修饰组件的位置。
6、通过clickable为被修饰组件增加点击函数。
注意事项:
Compose作用于限定实现了Modifier的安全调用,我们只能在特定作用于中调用修饰符。这个设计可能会导致上层的Modifier设置在子组件中无法使用,这是设计哲学上的取舍,暂不细究。在初学阶段把Modifier的定义移到需要这个Modifier的组件即可。
4、逻辑组件
1)列表
基本逻辑就是用循环把一个组件多创建出来几个。
代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dpclass MainActivity : ComponentActivity() {// 在这个Activity被创建的时候调用这个函数。override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 渲染Compose函数setContent {AList()}}
}data class Item(val name: String,val icon: Int
)@Composable
fun AList() {var items = listOf<Item>(Item("主页", R.drawable.home),Item("列表", R.drawable.liebiao),Item("设置", R.drawable.shezhi),Item("设置", R.drawable.shezhi),Item("设置", R.drawable.shezhi),Item("设置", R.drawable.shezhi),)Row{Column {items.forEachIndexed { index, opt->Text("我是Column $index")}}Spacer(Modifier.padding(horizontal = 10.dp))LazyColumn(state = rememberLazyListState(3,4),contentPadding = PaddingValues(30.dp)) {itemsIndexed(items) { index, it ->Text("我是LazyColumn。index: ${index}, name: ${it.name}")}}}
}@Preview
@Composable
fun PreviewA() {AList()
}
效果:
其他列表:一行的列表可以用Row来实现。
三、UI组合实践
1、简单页面的实践
可以随便找个页面,然后自己以素描的方式构建出该页面的仿制版。比如下述界面:
代码:
把BloomLogin的Compose函数放到setContent中即可。
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp@Composable
fun BloomLogin() {var email = remember { mutableStateOf("") }var password = remember { mutableStateOf("") }Surface {Column(verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally,modifier = Modifier.fillMaxSize().padding(start = 20.dp, end = 20.dp)) {Text(text="Log in with email",fontWeight = FontWeight.Bold)Spacer(Modifier.padding(vertical = 6.dp))TextField(value = email.value,onValueChange = {email.value = it},modifier = Modifier.fillMaxWidth(),placeholder = {Text("Email address")})Spacer(Modifier.padding(vertical = 3.dp))TextField(value = password.value,onValueChange = {password.value = it},modifier = Modifier.fillMaxWidth(),placeholder = {Text("Password(8+ characters)")},visualTransformation = PasswordVisualTransformation())Spacer(Modifier.padding(vertical = 6.dp))var text = "Dy clicking below. " +"you agree to our Terms of Use and " +"consent to our Privacy Policy."Text(text=text,textAlign = TextAlign.Center,modifier = Modifier)Spacer(Modifier.padding(vertical = 6.dp))Button(onClick = {},modifier = Modifier.fillMaxWidth()) {Text("Log in")}}}
}@Preview
@Composable
fun PreviewBloomLogin() {BloomLogin()
}
效果:
也可以用github上面安卓官方提供的例子练手:https://github.com/android/compose-samples
2、实践总结
学会上述的布局组件、UI组件和Modifier修饰符之后,基本上可以模仿现有的手机页面。如果还有不足之处,那么应该在于设计审美和资源素材的不足。其他遗漏的组件,有了上诉的经验后,从网络上或官网上寻找对应的使用例子应该是比较容易的了。
一门技术,如果你已经懂了90%,那么限制你提高的水平的因素,将不再是表面上的技术,而是相关的哲学。
3、未来提升方向:
1、不断模仿其他页面进行仿写,或者参与实际的项目开发,提升实践能力。
2、学习其他遗漏或者新出的组件。
3、学习、思考jetpack compose android的设计哲学。
参考内容:
书籍《Jetpack Compose从入门到实战》。
百度AI。
相关文章:

安卓jetpack compose学习笔记-UI基础学习
哲学知识应该用哲学的方式学习,技术知识也应该用技术的方式学习。没必要用哲学的态度来学习技术。 学完安卓技术能做事就ok了,安卓技术肯定是有哲学的,但是在初学阶段没必要讨论什么安卓哲学。 学习一们复杂技术的路径有很多,这里…...
线性回归用于分类
线性回归本身是一种用于回归问题的技术,即预测一个连续的目标变量值。然而,线性回归也可以被改造或结合其他技术来用于分类问题,尽管这不是其最直接或最常见的用途。以下是几种将线性回归应用于分类问题的方法或相关概念: 阈值划分…...
解锁电商新势能:商城系统自动 SaaS 多开功能深度解析
在电商行业加速向精细化、多元化运营转型的当下,传统的商城系统部署模式已难以满足企业快速拓展业务的需求。此时,商城系统自动 SaaS 多开功能横空出世,以智能、高效、灵活的特性,成为众多电商企业突破发展瓶颈的关键利器。这一功…...

蓝桥杯_DS18B20温度传感器---新手入门级别超级详细解析
目录 一、引言 DS18B20的原理图 单总线简介: 编辑暂存器简介: DS18B20的温度转换与读取流程 二、代码配置 maic文件 疑问 关于不同格式化输出符号的使用 为什么要rd_temperature()/16.0? onewire.h文件 这个配置为什么要先读lo…...

C++中锁与原子操作的区别及取舍策略
文章目录 锁与原子操作的基本概念锁(Lock)原子操作(Atomic Operations) 锁与原子操作的区别1. **功能**2. **性能**3. **复杂性**4. **适用场景** 锁与原子操作的取舍策略1. **简单变量操作**2. **复杂共享资源**3. **性能敏感场景…...
ESP32对接巴法云实现配网
目录 序言准备工作巴法云注册与使用Arduino准备 开发开始配网 序言 本文部分内容摘抄原创作者巴法云-做优秀的物联网平台 代码有部分修改并测试运行正常 巴法云支持免费用户通过开发对接实现各智能音箱设备语音控制智能家居设备,并有自己的App进行配网和控制&…...
《深度剖析:基于Meta的GameFormer构建自博弈AI游戏代理》
自博弈AI游戏代理,是一种具备自主学习和自我提升能力的人工智能系统。它打破了传统AI依赖预设规则和固定策略的局限,能够在游戏过程中不断与自身进行对战,通过反复博弈来积累经验、优化策略,从而实现智能水平的持续提升 。这种独特…...

C++语法系列之类型转换
前言 类型转换是经常存在的情况,类型转换分为隐式类型转化 和 显式类型转化 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败 double i 3.3; int b i; //隐式类型转化 double -> intC搞出来了四种强制类…...
Qwen3 技术报告解读一
📘 Qwen3 技术报告解读:通义千问系列新成员的技术亮点与能力分析 一、论文写了什么? 本文来自阿里通义实验室发布的 《Qwen3 Technical Report》,介绍了其最新一代大语言模型 Qwen3 的技术架构、训练方法以及在多个关键任务上的…...

详解开漏输出和推挽输出
开漏输出和推挽输出 以上是 GPIO 配置为输出时的内部示意图,我们要关注的其实就是这两个 MOS 管的开关状态,可以组合出四种状态: 两个 MOS 管都关闭时,输出处于一个浮空状态,此时他对其他点的电阻是无穷大的ÿ…...

【八股消消乐】索引失效与优化方法总结
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点ÿ…...

一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录——4. 配置服务器终端环境 zsh , oh my zsh, vim
前言 通过前面几篇文章,我们顺利的 安装了 ubuntu server 服务器,并且配置好了 ssh 免密登录服务器,也安装好了 服务器常用软件安装,接下来,我们要仔细的配置一下我们的终端环境,让服务器的终端更加好用。 一般情况下…...

数据安全合规体系构建的“三道防线“
引言 "三道防线"模型架构图 #mermaid-svg-wbeppAbwa3Vb3nL2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-wbeppAbwa3Vb3nL2 .error-icon{fill:#552222;}#mermaid-svg-wbeppAbwa3Vb3nL2 .error-text{fi…...

【Spring底层分析】Spring AOP基本使用+万字底层源码阅读分析
一、AOP基本使用 三步: 将业务逻辑组件和切面类都加入到容器中,告诉Spring哪个是切面类(Aspect)在切面类上的每一个通知方法上标注通知注解,告诉Spring何时(Before、After、Around……)何地运…...
Python数据分析及可视化中常用的6个库及函数(二)
Python数据分析及可视化中常用的6个库及函数(二) 摘要:以下是Python数据分析及可视化常用的6个库的详细介绍,包括它们的概述以及每个库中最常用的10个函数(如果某些库常用函数不足10个,则列出所有常用函数)。每个函数都附带功能描述、用法说明和使用示例。这些库…...

新德通科技:以创新驱动光通信一体化发展,赋能全球智能互联
在数字经济与AI技术高速发展的今天,光通信作为信息传输的核心基础设施,正迎来前所未有的升级浪潮。深圳新德通科技有限公司(以下简称“新德通科技”)凭借其深厚的技术积累与一体化产品布局,成为行业内的中坚力量。本文…...
Selenium的底层原理
Selenium 底层主要依赖于 WebDriver 协议(即 W3C WebDriver 规范,早期也有 JSON Wire Protocol)来实现对浏览器的远程控制,其核心架构可以分为以下几层: Selenium 客户端(Client Library) 支持多…...
PostgreSQL的扩展 auth_delay
PostgreSQL的扩展 auth_delay auth_delay 是 PostgreSQL 提供的一个安全相关扩展,主要用于防止暴力破解攻击。它通过在认证失败后引入人为延迟来增加暴力破解的难度。 一、扩展基础 功能:在认证失败后增加延迟目的:减缓暴力破解和字典攻击…...
[Java 基础]Java 是什么
Java 是一门编程语言。 查看编程语言热门排行:https://www.tiobe.com/tiobe-index/ Java 的特点: 面向对象:Java 是面向对象的语言,支持封装、继承和多态等特性。 平台无关性:Java 通过“一次编写,到处…...
Qt学习2
跟学视频 1.菜单栏和工具栏 //菜单栏最多只能有一个//菜单栏创建QMenuBar * bar menuBar();//将菜单栏放到窗口中setMenuBar(bar);//创建菜单QMenu * fileMenu bar->addMenu("开始");QMenu * editMenu bar->addMenu("编辑");//创建菜单项QAction…...

C++ 内存泄漏检测器设计
文章目录 1. C中的动态内存分配2. 什么是内存泄漏3. 内存泄漏的代码案例4. 内存泄漏检查器的设计模块1:位置信息捕获:模块2:内存分配跟踪:模块3:内存释放跟踪:模块4:泄漏记录存储:模…...
在 Linux 上安装 Nmap 工具
📦 在 Linux 上安装 Nmap 工具指南 Nmap(Network Mapper)是功能强大的网络扫描工具,以下是各种 Linux 发行版的安装方法: 🧩 通用安装方法 1. 使用包管理器安装(推荐) # Debian/…...
从零打造AI面试系统全栈开发
🤖 AI面试系统开发完整教程 📋 项目概述 本教程将带你从零开始构建一个完整的AI面试系统,包含前端、后端、AI集成和部署的全流程。 源码地址 技术栈 前端: React TypeScript Vite Vaadin Components后端: Spring Boot Spring Securi…...

破局与进阶:ueBIM 在国产 BIM 赛道的差距认知与创新实践
作为国产BIM领域的探索者,斯维尔ueBIM自诞生以来始终以追赶国际头部技术为目标,但不可否认的是,在核心功能覆盖、行业生态成熟度以及全球市场占有率等方面,我们与Autodesk Revit、Bentley Systems等国际巨头仍存在显著差距。这种差…...

分布式流处理与消息传递——向量时钟 (Vector Clocks) 算法详解
Java 实现向量时钟 (Vector Clocks) 算法详解 一、向量时钟核心原理 #mermaid-svg-JcZ1GT0r1ZNSy6W7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JcZ1GT0r1ZNSy6W7 .error-icon{fill:#552222;}#mermaid-svg-JcZ…...

20250603在荣品的PRO-RK3566开发板的Android13下的命令行查看RK3566的温度
20250603在荣品的PRO-RK3566开发板的Android13下的命令行查看RK3566的温度 2025/6/3 11:58 RK3566的cpu运行效率 top rk3566_t:/ # rk3566_t:/ # rk3566_t:/ # cd /sys/class/thermal/ rk3566_t:/sys/class/thermal # ls -l rk3566_t:/sys/class/thermal # cd thermal_zone0/ r…...

帝可得 - 设备管理
一. 需求说明 设备管理主要涉及到三个功能模块,业务流程如下: 新增设备类型: 允许管理员定义新的售货机型号,包括其规格和容量。 新增设备: 在新的设备类型定义后,系统应允许添加新的售货机实例,并将它们分配到特定的…...
FTXUI配置
对于 FTXUI 的安装与配置, 官方已经给出了三种方案. 第一种: 使用 FetchContent 远程拉取第二种: 在你本地安装 FTXUI 库, 然后通过 find_package 使用第三种: 使用 Git 子模块 FetchContent 无需手动下载安装 FTXUI, 通过 CMake 自动从 GitHub 拉取并编译依赖 include(Fet…...
Caliper压力测试
目前FISCO BCOS适配的Caliper版本为0.2.0,请在部署Caliper运行环境时确保Caliper的版本为0.2.0,如在部署或使用过程中遇到任何问题,请优先参考 https://github.com/FISCO-BCOS/FISCO-BCOS/issues/1248 中的解决方案进行排查。 1. 环境要求 …...

【iOS安全】使用LLDB调试iOS App | LLDB基本架构 | LLDB安装和配置
LLDB基本架构 参考: https://crifan.github.io/ios_re_dynamic_debug/website/debug_code/lldb_debugserver.html https://book.crifan.org/books/ios_re_debug_debugserver_lldb/website/ LLDB安装和配置 1. 让iPhone中出现/Developer/usr/bin/debugserver 最初…...