Android Compose 组件学习(一)

源码 2024-9-12 13:32:04 85 0 来自 中国
Android Compose自推出正式版本后,google 就不停保举利用Compose来开辟。恰好疫情期间,作为一个 Android 摸鱼达人,就来探索一下Compose的开辟。说真话开辟了2天感觉对Android 开辟职员来说变革是巨大的,但是作为从业者我们还必须学习和学会,才能不被甩开。
学习利用 Compose 我们必要坐什么呢?
1.利用 Kotlin
2.利用Android Studio 最新版本开辟工具
3.去官网查察教程,跟着google 一步一个脚迹的学习->官方文档速转通道

  • Jetpack Compose 利用入门
    https://developer.android.google.cn/jetpack/compose/documentation
  • Compose 教程
    https://developer.android.google.cn/courses/pathways/compose
  • Compose 示例
    https://github.com/android/compose-samples
  • Codelab: 在 Jetpack Compose 中利用状态
    https://developer.android.google.cn/codelabs/jetpack-compose-state
4.找其他开辟者的文档,更详细更服从的学习

  • https://jetpackcompose.cn/docs文档和开源项目
  • https://github.com/Gurupreet/ComposeCookBook开源项目
下载工具

利用 Android Studio Bumblebee 大黄蜂?版本,假如不想影响老版本 Android Studio 的运行项目,可以下载 zip 的版本。AS尽大概升级到最新版,最少也要Arctic Fox,老版本无法实现 Compose 的预览和开辟
官方下载地点:https://developer.android.google.cn/studio
快速下载地点:https://www.androiddevtools.cn/
下载后创建 Compose 项目,假如你电脑配置的 java为11,那么就没题目。假如出现题目如下:
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
You can try some of the following options:

  • changing the IDE settings.
  • changing the JAVA_HOME environment variable.
  • changing org.gradle.java.home in gradle.properties.
    Gradle settings
    办理方案为:
    1.更新 java 到11,完善。固然你根本用不到11
    2.到体系设置中Preferences -> Build Tools ->Gradle , 选择 Gradle JDK 为11
    1.png
Compose项目构成

在项目可以正式运行后,我们可以先打开MainActivity,继承ComponentActivity()包罗了setContent()方法,假如去除setContent内的代码运行可以看到一个空页面。
然后我们添加一个文本控件Text,对应原生的TextView。
class MainActivity : ComponentActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContent {            Text("Hello world!")        }    }}项目运行起来后我们看下整个项目标代码是怎么样的。
Compose 的引入

buildscript {    ext {        compose_version = '1.0.1'    }}//compose 核心implementation "androidx.compose.ui:uicompose_version"implementation "androidx.compose.material:materialcompose_version"implementation "androidx.compose.ui:ui-tooling-previewcompose_version"另外 google 提供了非常多的compose 库,详细查察可以到https://developer.android.google.cn/jetpack/androidx/explorer查察。

2.png
初识组件

Compose 内部的组件非常少,但是合理的搭配可以做到比安卓原生更好的开辟体验。大要如下:
分类Compose原生文本TextTextView文本TextFieldEdittext图片IconImageView图片ImageImageViewButtonButtonButtonButtonIconButtonButtonButtonIconToggleButtonCheckBox,SwitchButtonSwitchSwitchButtonRadioButtonRadioButtonButtonCheckboxCheckBox布局BoxFrameLayout布局ColumnLinearLayout布局RowLinearLayout布局Scaffold无布局ConstraintlayoutConstraintlayout列表LazyColumnRecyclerView,ListView列表LazyRowRecyclerView,ListView间距类SpacerSpace(估计许多人都没用过)我们直接在setContent添加个 Text 和 Image 控件,下面代码就是最简单的写法。
Text、Image应该是我们最常用的控件,特别是 Text 可实现的功能特别多,详细可以去看后续文章大概看下其他博客。
setContent {            Text("Hello world!")            Image(                      painter = painterResource(R.drawable.share_calc),                      contentDescription = null                )}上面的展示代码会使内容重叠,必要利用 Row 大概 Column。
按照下面展示,我们添加了Column垂直布局,控件就往下绘制不重叠了。
Row 、Column、Box

Column 垂直布局 -- 对用 LinearLayout 的androidrientation="vertical";Row 程度布局 -- 对用 LinearLayout 的androidrientation="horizontal";Box靠近FrameLayout,详细利用可以看下图的例子.
Compose 中的三个根本尺度布局元素是 Column、Row 和 Box 可组合项。

Column(){Text("Hello world!")Image(            painter = painterResource(R.drawable.share_calc),            contentDescription = null        )}Row(){Text(" Row W")Image(            painter = painterResource(R.drawable.share_calc),            contentDescription = null        )}Box(            modifier = Modifier                .background(Color.Cyan)                .size(180.dp)        ) {            Box(                modifier = Modifier                    .align(Alignment.TopCenter)                    .size(60.dp, 60.dp)                    .background(Color.Red)            ) {            }            Box(                modifier = Modifier                    .align(Alignment.BottomEnd)                    .size(60.dp, 60.dp)                    .background(Color.Blue)            ) {            }        } 4.png Scaffold脚手架和Constraintlayout布局

Scaffold脚手架我们先看下源码,可以看到包罗了topBar、bottomBar、floatingActionButton等控件的页面。这是个固定布局,当我们的首页符合该页面固定样式时,可以直接利用该布局。
Constraintlayout布局和Android 原生一样
@Composablefun Scaffold(    modifier: Modifier = Modifier,    scaffoldState: ScaffoldState = rememberScaffoldState(),    topBar: @Composable () -> Unit = {},    bottomBar: @Composable () -> Unit = {},    snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },    floatingActionButton: @Composable () -> Unit = {},    floatingActionButtonPosition: FabPosition = FabPosition.End,    isFloatingActionButtonDocked: Boolean = false,    drawerContent: @Composable (ColumnScope.() -> Unit)? = null,    drawerGesturesEnabled: Boolean = true,    drawerShape: Shape = MaterialTheme.shapes.large,    drawerElevation: Dp = DrawerDefaults.Elevation,    drawerBackgroundColor: Color = MaterialTheme.colors.surface,    drawerContentColor: Color = contentColorFor(drawerBackgroundColor),    drawerScrimColor: Color = DrawerDefaults.scrimColor,    backgroundColor: Color = MaterialTheme.colors.background,    contentColor: Color = contentColorFor(backgroundColor),    content: @Composable (PaddingValues) -> Unit) TextField文本输入控件

@Composablefun InputText() {    val input = remember { mutableStateOf("") }    TextField(value = input.value, onValueChange = { input.value = it })}Icon 和 Image图片类

      Row {            Icon(painter = painterResource(R.drawable.database_set), contentDescription = null)            Spacer(modifier = Modifier.width(8.dp))            Image(                painter = painterResource(R.drawable.share_calc),                contentDescription = null            )            }Button 类

Compose Button多种多样,详细的各人可以先看 UI 展示,就能明确在详细场景下利用什么 button。估计是参考的H5前端的按钮样式
Button 就是带配景致的按钮,OutlinedButton是带边框绘制的,TextButton是无配景致的按钮。其他都可以参考原生的样式

Row() {            //普通按钮            Button(onClick = { /*TODO*/ }) {                Text(text = "Button")            }            Spacer(modifier = Modifier.width(8.dp))            //带边框绘制的 button            OutlinedButton(onClick = { /*TODO*/ }) {                Text(text = "OutlinedButton")            }            Spacer(modifier = Modifier.width(8.dp))            //纯笔墨按钮            TextButton(onClick = {}) {                Text("TextButton")            }        }Row() {            //带Icon的按钮            //圆形水波纹和 Checkbox,Switch 水波纹效果同等,            //android 可以看下设置android:background="?attr/selectableItemBackgroundBorderless"("?attr/actionBarItemBackground")的效果            IconButton(modifier = Modifier.width(120.dp), onClick = { /*TODO*/ }) {                Row() {                    Icon(                        painter = painterResource(id = R.drawable.database_set),                        contentDescription = null                    )                    Spacer(modifier = Modifier.width(8.dp))                    Text("IconButton")                }            }            //图标切换 button,雷同于switch,但是更靠近于CheckBox            //圆形水波纹和Checkbox,Switch 水波纹效果同等,            //android 可以看下设置android:background="?attr/selectableItemBackgroundBorderless"("?attr/actionBarItemBackground")的效果            IconToggleButton(checked = false, onCheckedChange = {}) {                Text(text = "IconToggleButton")            }            //悬浮按钮            ExtendedFloatingActionButton(text = { Text(text = "FAB") }, onClick = { })        }RadioButton\Checkbox和原生对应,但是没 text 属性,假如必要体现文本必要和 Text 控件组合利用
       RadioDefault()        RadioText()        RadioButtonGroup()        Row() {            CheckboxDefault()            SwitchDefault()        }@Composablefun RadioDefault() {    val isSelected = remember { mutableStateOf(false) }    RadioButton(selected = isSelected.value, onClick = {        isSelected.value = !isSelected.value        Log.e(TAG, "默认Checkbox,同RadioButton不带text文本控件")    })}@Composablefun RadioText() {    val isSelected = remember { mutableStateOf(false) }    // 假如必要 text 必要和 Text 组合利用,click处置惩罚在row上    Row(modifier = Modifier.clickable {        isSelected.value = !isSelected.value    }) {        RadioButton(            selected = isSelected.value, onClick = null,            colors = RadioButtonDefaults.colors(                selectedColor = MaterialTheme.colors.primary,                unselectedColor = MaterialTheme.colors.error,                disabledColor = MaterialTheme.colors.secondary            )        )        Text("选项②")    }}@Composablefun RadioButtonGroup() {    val options = listOf("选项③", "选项④", "选项⑤", "选项⑥")    val selectedButton = remember { mutableStateOf(options.first()) }    //RadioButton 不带 text 文本控件,    Row() {        options.forEach {            val isSelected = it == selectedButton.value            Row(verticalAlignment = Alignment.CenterVertically,                modifier = Modifier.clickable {                    selectedButton.value = it                }) {                RadioButton(                    selected = isSelected, onClick = null,                )                Text(it, textAlign = TextAlign.Justify)            }        }    }}@Composablefun CheckboxDefault() {    val isSelected = remember { mutableStateOf(false) }    Checkbox(checked = isSelected.value, onCheckedChange = {        isSelected.value = it        Log.e(TAG, "默认Checkbox,同RadioButton不带text文本控件")    })}@Composablefun SwitchDefault() {    val isSelected = remember { mutableStateOf(false) }    Switch(checked = isSelected.value, onCheckedChange = {        isSelected.value = it        Log.e(TAG, "默认Checkbox,同RadioButton不带text文本控件")    })}界说一个带 Text 的 RadioButton
@Composablefun RadioText() {    val isSelected = remember { mutableStateOf(false) }    // 假如必要 text 必要和 Text 组合利用,click处置惩罚在row上    Row(modifier = Modifier.clickable {        isSelected.value = !isSelected.value    }) {        RadioButton(            selected = isSelected.value, onClick = null,            colors = RadioButtonDefaults.colors(                selectedColor = MaterialTheme.colors.primary,                unselectedColor = MaterialTheme.colors.error,                disabledColor = MaterialTheme.colors.secondary            )        )        Text("选项②")    }}Compose 无RadioGroup 组件,假如必要实现RadioGroup也必要组合利用
界说 RadioGroup 组件,在循环中改变状态
@Composablefun RadioButtonGroup() {    val options = listOf("选项③", "选项④", "选项⑤", "选项⑥")    val selectedButton = remember { mutableStateOf(options.first()) }    //RadioButton 不带 text 文本控件,    Row() {        options.forEach {            val isSelected = it == selectedButton.value            Row(verticalAlignment = Alignment.CenterVertically,                modifier = Modifier.clickable {                    selectedButton.value = it                }) {                RadioButton(                    selected = isSelected, onClick = null,                )                Text(it, textAlign = TextAlign.Justify)            }        }    }}同理Checkbox和Switch控件就不细说了。对应的参数改成了checked和onCheckedChange,也是没有 text 属性,必要组合利用。
@Composablefun CheckboxDefault() {    val isSelected = remember { mutableStateOf(false) }    Checkbox(checked = isSelected.value, onCheckedChange = {        isSelected.value = it        Log.e(TAG, "默认Checkbox,同RadioButton不带text文本控件")    })}@Composablefun SwitchDefault() {    val isSelected = remember { mutableStateOf(false) }    Switch(checked = isSelected.value, onCheckedChange = {        isSelected.value = it        Log.e(TAG, "默认Checkbox,同RadioButton不带text文本控件")    })}LazyColumn、LazyRow

LazyColumn 和 LazyRow 相称于 Android View 中的 RecyclerView。它们只会渲染屏幕上可见的内容,从而在渲染大型列表时提拔服从。
注意:LazyColumn 不会像 RecyclerView 一样回收其子级。它会在您滚动它时发出新的可组合项,并保持高效运行,由于与实例化 Android Views 相比,发出可组合项的资本相对较低。
@Composablefun RecyclerView(names: List<String> = List(1000) { "$it" }) {    LazyColumn() {        items(items = names) { item ->            MessageCard(item)        }    }}@Composablefun MessageCard(msg: String) {    var isExpanded by remember { mutableStateOf(false) }    val surfaceColor: Color by animateColorAsState(        if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface,    )    Row(modifier = Modifier        .fillMaxWidth()        .clickable {            isExpanded = !isExpanded        }        .padding(8.dp)    ) {        Image(            painter = painterResource(R.drawable.share_calc),            contentDescription = null,            modifier = Modifier                .size(40.dp)                .clip(CircleShape)                .border(1.5.dp, MaterialTheme.colors.secondaryVariant, CircleShape)        )        Spacer(modifier = Modifier.width(8.dp))        // We toggle the isExpanded variable when we click on this Column        Column() {            Text("当前索引:")            Spacer(modifier = Modifier.height(4.dp))            Surface(                shape = MaterialTheme.shapes.medium,                elevation = 1.dp,                // surfaceColor color will be changing gradually from primary to surface                color = surfaceColor,                // animateContentSize will change the Surface size gradually                modifier = Modifier                    .animateContentSize()                    .padding(1.dp)            ) {                Text(                    text = "索引为--------> $msg ,这是一个可睁开和关闭的 Text 控件:" +                            "微凉的晨露 沾湿黑制服\n" +                            "石板路有雾 父在低诉\n" +                            "无奈的觉悟 只能更暴虐\n" +                            "统统都为了通往圣堂的路",                    modifier = Modifier.padding(all = 4.dp),                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,                    style = MaterialTheme.typography.body2                )            }        }    }}这边界说了一个内容为1000行的 List,利用LazyColumn包裹,同时在 MessageCard 中对点击坐了处置惩罚,点击后放开 Text 的行数限定。详细效果如下


这篇博客只是只是展示了控件的简单利用,快速的相识控件的创建及展示效果。
下一篇我们先容怎样跳转页面。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 20:23, Processed in 0.163515 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表