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

news2025/7/22 21:39:30

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

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

class 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.Preview

class 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.Preview

class 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.dp

class 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.dp

class 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 = it
            println("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.dp

class 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 = it
            println("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.Preview

class 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.Dialog

class 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.dp

class 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.1f
                else
                    progress.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.dp

class 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.dp

class 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.dp

class 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.dp

class 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.dp

class 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.dp

class 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.dp

class 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.coloradmin.cn/o/2397980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯_DS18B20温度传感器---新手入门级别超级详细解析

目录 一、引言 DS18B20的原理图 单总线简介&#xff1a; ​编辑暂存器简介&#xff1a; DS18B20的温度转换与读取流程 二、代码配置 maic文件 疑问 关于不同格式化输出符号的使用 为什么要rd_temperature()/16.0&#xff1f; onewire.h文件 这个配置为什么要先读lo…

C++中锁与原子操作的区别及取舍策略

文章目录 锁与原子操作的基本概念锁&#xff08;Lock&#xff09;原子操作&#xff08;Atomic Operations&#xff09; 锁与原子操作的区别1. **功能**2. **性能**3. **复杂性**4. **适用场景** 锁与原子操作的取舍策略1. **简单变量操作**2. **复杂共享资源**3. **性能敏感场景…

C++语法系列之类型转换

前言 类型转换是经常存在的情况&#xff0c;类型转换分为隐式类型转化 和 显式类型转化 隐式类型转化&#xff1a;编译器在编译阶段自动进行&#xff0c;能转就转&#xff0c;不能转就编译失败 double i 3.3; int b i; //隐式类型转化 double -> intC搞出来了四种强制类…

详解开漏输出和推挽输出

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

【八股消消乐】索引失效与优化方法总结

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《八股消消乐》旨在记录个人所背的八股文&#xff0c;包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点&#xff…

一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录——4. 配置服务器终端环境 zsh , oh my zsh, vim

前言 通过前面几篇文章&#xff0c;我们顺利的 安装了 ubuntu server 服务器&#xff0c;并且配置好了 ssh 免密登录服务器&#xff0c;也安装好了 服务器常用软件安装,接下来&#xff0c;我们要仔细的配置一下我们的终端环境&#xff0c;让服务器的终端更加好用。 一般情况下…

数据安全合规体系构建的“三道防线“

引言 "三道防线"模型架构图 #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基本使用 三步&#xff1a; 将业务逻辑组件和切面类都加入到容器中&#xff0c;告诉Spring哪个是切面类&#xff08;Aspect&#xff09;在切面类上的每一个通知方法上标注通知注解&#xff0c;告诉Spring何时&#xff08;Before、After、Around……&#xff09;何地运…

新德通科技:以创新驱动光通信一体化发展,赋能全球智能互联

在数字经济与AI技术高速发展的今天&#xff0c;光通信作为信息传输的核心基础设施&#xff0c;正迎来前所未有的升级浪潮。深圳新德通科技有限公司&#xff08;以下简称“新德通科技”&#xff09;凭借其深厚的技术积累与一体化产品布局&#xff0c;成为行业内的中坚力量。本文…

C++ 内存泄漏检测器设计

文章目录 1. C中的动态内存分配2. 什么是内存泄漏3. 内存泄漏的代码案例4. 内存泄漏检查器的设计模块1&#xff1a;位置信息捕获&#xff1a;模块2&#xff1a;内存分配跟踪&#xff1a;模块3&#xff1a;内存释放跟踪&#xff1a;模块4&#xff1a;泄漏记录存储&#xff1a;模…

破局与进阶:ueBIM 在国产 BIM 赛道的差距认知与创新实践

作为国产BIM领域的探索者&#xff0c;斯维尔ueBIM自诞生以来始终以追赶国际头部技术为目标&#xff0c;但不可否认的是&#xff0c;在核心功能覆盖、行业生态成熟度以及全球市场占有率等方面&#xff0c;我们与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…

帝可得 - 设备管理

一. 需求说明 设备管理主要涉及到三个功能模块&#xff0c;业务流程如下&#xff1a; 新增设备类型: 允许管理员定义新的售货机型号&#xff0c;包括其规格和容量。 新增设备: 在新的设备类型定义后&#xff0c;系统应允许添加新的售货机实例&#xff0c;并将它们分配到特定的…

【iOS安全】使用LLDB调试iOS App | LLDB基本架构 | LLDB安装和配置

LLDB基本架构 参考&#xff1a; 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 最初…

Idea 配置 Maven 环境

下载 Maven 官网&#xff1a;https://maven.apache.org/index.html 点击左侧 Downloads&#xff0c;然后选择 Files 中的 zip 包下载&#xff08;下载慢可以使用迅雷&#xff09; 配置 Maven 将压缩包解压&#xff0c;比如我解压后放到了 D:\developer\environment\apache-…

Kafka 如何保证不重复消费

在消息队列的使用场景中&#xff0c;避免消息重复消费是保障数据准确性和业务逻辑正确性的关键。对于 Kafka 而言&#xff0c;保证不重复消费并非单一机制就能实现&#xff0c;而是需要从生产者、消费者以及业务层等多个维度协同配合。接下来&#xff0c;我们将结合图文详细解析…

RNN结构扩展与改进:从简单循环网络到时间间隔网络的技术演进

本文系统介绍 RNN 结构的常见扩展与改进方案。涵盖 简单循环神经网络&#xff08;SRN&#xff09;、双向循环神经网络&#xff08;BRNN&#xff09;、深度循环神经网络&#xff08;Deep RNN&#xff09; 等多种变体&#xff0c;解析其核心架构、技术特点及应用场景&#xff0c;…

类 Excel 数据填报

类 Excel 填报模式&#xff0c;满足用户 Excel 使用习惯 数据填报&#xff0c;可作为独立的功能模块&#xff0c;用于管理业务流程、汇总采集数据&#xff0c;以及开发各类数据报送系统&#xff0c;因此&#xff0c;对于报表工具而言&#xff0c;其典型场景之一就是利用报表模…

Office文档图片批量导出工具

软件介绍 本文介绍一款专业的Office文档图片批量导出工具。 软件特点 这款软件能够批量导出Word、Excel和PPT中的图片&#xff0c;采用绿色单文件设计&#xff0c;体积小巧仅344KB。 基本操作流程 使用方法十分简单&#xff1a;直接将Word、Excel或PPT文件拖入软件&#xf…