安卓jetpack compose学习笔记-UI基础学习

article/2025/8/11 19:15:02

        哲学知识应该用哲学的方式学习,技术知识也应该用技术的方式学习。没必要用哲学的态度来学习技术。

        学完安卓技术能做事就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。


http://www.hkcw.cn/article/nBIShkGkWk.shtml

相关文章

[蓝桥杯]螺旋折线

螺旋折线 题目描述 如下图所示的螺旋折线经过平面上所有整点恰好一次。 对于整点 (X,Y)(X,Y)&#xff0c;我们定义它到原点的距离 dis(X,Y)dis(X,Y) 是从原点到 (X,Y)(X,Y) 的螺旋折线段的长度。 例如 dis(0,1)3,dis(−2,−1)9dis(0,1)3,dis(−2,−1)9。 给出整点坐标 (X,Y…

【动态规划】子序列问题(一)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的动态规划算法学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码&#xff1b;&…

一文读懂Ingress-Nginx以及实践攻略

一文读懂Ingress-Nginx以及实践攻略 目录 1 概念 1.1 什么是Ingress? 1.1.1 主要功能:1.2 Ingress的组件1.3 什么是ingress-nginx1.4 ingress-nginx优点和限制1.5 版本兼容性矩阵2 实践: Ingress nginx部署 2.1 使用helm部署ingress-nginx 2.1.1 安装和配置Helm2.1.2 配置和…

一、【专栏启动篇】:为什么是 Django + Vue3?测试平台的技术选型与架构蓝图

【专栏启动篇】&#xff1a;为什么是 Django Vue3&#xff1f;测试平台的技术选型与架构蓝图 前言一、为什么是 Django Vue3&#xff1f;二、测试平台的架构设计蓝图三、测试平台模块功能概述 结语 前言 一个高效、稳定、易用的测试平台&#xff0c;不仅能够帮助团队提升测试…

基于OAuth2+SpringSecurity+Jwt实现身份认证和权限管理后端服务

1、简介 本文讲述了如何实现简易的后端鉴权服务。所谓“鉴权”&#xff0c;就是“身份鉴定”“权限判断”。涉及的技术有&#xff1a;OAuth2、SpringSecurity、Jwt、过滤器、拦截器。OAuth2用于授权&#xff0c;使用Jwt签发Access Token和Refresh Token&#xff0c;并管理token…

基于SpringBoot和PostGIS的云南与缅甸的千里边境线实战

目录 前言 一、PostGIS空间求解 1、相邻的求解 二、后台程序实现 1、数据查询的实现 2、API接口实现 三、WebGIS可视化实现 1、空间面展示 2、增加面标注 3、图例展示 4、与缅甸距离较近的区县信息 四、总结 前言 云南&#xff0c;这个位于中国西南边陲的省份&…

【带小白做项目】如何在SpringBoot项目中接入AI大模型?

随着chatGPT的兴起&#xff0c;越来越多的应用接入了AI大模型&#xff0c;那么我们要怎么在自己的项目中接入AI大模型呢&#xff1f;本节我们一起做一个简单的demo来尝试一下。 一 为什么要在项目中接入大模型 1. 增强业务功能和用户体验 AI 大模型&#xff08;如 GPT、BERT…

【计算机主板架构】ATX架构

一、引言 在计算机的世界里&#xff0c;主板就如同一个城市的基础设施&#xff0c;承载着各种重要的组件并协调它们的工作。而ATX&#xff08;Advanced Technology Extended&#xff09;架构的主板&#xff0c;自问世以来&#xff0c;一直在计算机硬件领域占据着举足轻重的地位…

精选了几道MySQL的大厂面试题,被提问的几率很高!

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

搞定mysql的 行转列(7种方法) 和 列转行

一、行转列 1、使用case…when…then 2、使用SUM(IF()) 生成列 3、使用SUM(IF()) 生成列 WITH ROLLUP 生成汇总行 4、使用SUM(IF()) 生成列&#xff0c;直接生成汇总结果&#xff0c;不再利用子查询 5、使用SUM(IF()) 生成列 UNION 生成汇总行,并利用 IFNULL将汇总行标题…

高并发场景下的热点key问题探析与应对策略

目录 一、问题描述 二、发现机制 三、解决策略分析 &#xff08;一&#xff09;解决策略一&#xff1a;多级缓存策略 客户端本地缓存 代理节点本地缓存 &#xff08;二&#xff09;解决策略二&#xff1a;多副本策略 &#xff08;三&#xff09;解决策略三&#xff1a;热点…

SQL Server——SSMS中数据库、表的创建

目录 一、引言 二、数据库、表的创建与删除 &#xff08;一&#xff09;方法一&#xff1a;在SSMS控制平台上进行创建 &#xff08;二&#xff09;方法二&#xff1a;使用 SQL 代码实现对数据库和表的创建 三、SQL 和 T-SQL 一、引言 在学习数据库的过程中&#xff0c;初…

spring AOP详解

文章目录 AOP1 环境准备1.1 工程及接口创建1.2 工程存在的问题1.2.1 问题1.2.2 解决思路 2 AOP面向切面编程2.1 AOP概述2.2 AOP原理分析 3 基于注解的AOP3.1 入门示例3.2 使用流程3.3 切入点表达式3.4 练习3.5 通知类型 AOP ​ AOP&#xff08;Aspect Orient Programming&…

重看Spring聚焦ApplicationContext分析

目录 一、理解下ApplicationContext的设计 &#xff08;一&#xff09;功能性的理解 &#xff08;二&#xff09;ApplicationContext 结构类图 二、ApplicationContext根接口 &#xff08;一&#xff09;源码展示 &#xff08;二&#xff09;分析说明 三、子接口Configu…

【MySQL安装】—报错“Can‘t connect to local MySQL server through socket ‘varlibmysqlmysql.sock‘”

项目场景&#xff1a; 执行 “mysql -uroot -p” 命令&#xff0c;进入MySQL数据库。 问题描述&#xff1a; 报错&#xff1a; Cant connect to local MySQL server through socket /var/lib/mysql/mysql.sock 原因分析&#xff1a; /var/lib/mysql路径下缺少mysql.sock文件。 …

本地部署Vanna实战,快速解决NLP2SQL

一、背景 ​ 随着DeepSeek的火爆&#xff0c;基于AI的应用也如雨后春笋般迸发出来&#xff0c;如何根据用户的一句话来找到用户所需要的信息&#xff0c;采用传统的方式无法通过模糊匹配等实现复杂的业务场景&#xff0c;故探索一种新的思路来实现信息获取。Text2SQL将自然语言…

【MySQL】基础操作

MySQL(二)基础操作 一、数据库操作 1.创建库 2.查看库 3.选中库 4.删除库 二、表操作 1.创建表 1.1[comment 注释]&#xff1a; 1.2,...&#xff1a; 2.查看表 2.1查看所有表 2.2查看表结构 3.删除表 三、记录操作 1.插入记录 1.1全列插入 1.2指定列插入 1.3…

嵌入式硬件篇---蜂鸣器

蜂鸣器是一种常用的电子发声元件&#xff0c;主要分为有源蜂鸣器和无源蜂鸣器两类。它们在结构、工作原理、驱动方式、应用场景等方面存在显著差异。以下是详细介绍&#xff1a; 一、核心定义与结构差异 1. 有源蜂鸣器 定义&#xff1a; “有源” 指内部自带振荡电路&#x…

工程的焊接技术

一、焊接设备与材料 焊接设备&#xff1a;对应不同焊接方法&#xff0c;如焊条电弧焊设备包括电焊机、焊钳、接地夹等。 焊接材料 焊条 分类&#xff1a;按熔渣性质分为碱性焊条&#xff08;低氢型&#xff09;和酸性焊条。 选用原则&#xff1a;根据焊接场景选择&#xff0c;…

HackMyVM-Teacher

信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-01 01:02 EDT Nmap scan report for 192.168.43.1 Host is up (0.0084s latency). MAC Address: C6:45:66:05:91:88 (Unknow…