jetpack compose实战——基本框架搭建

前言

  • 项目地址:https://github.com/Peakmain/ComposeProject
  • 网上现在有不少jetpack compose的文章和教程,但是实战项目不多。
  • 项目接口基于玩Android,这里也非常感谢大佬提供的免费接口

建议
先学习kotlin语言,最好有Android App开发经验

项目结构

新建项目New Project->选择 Empty Compose Activity


image.png

填写必要信息,完成项目创建


image.png
Compose和Android View的区别
Android View compose
Button Button
TextView Text
EditText TextField
ImageView Image
LinearLayout(horizontally) Row
LinearLayout(vertically) Column
FrameLayout Box
RecyclerView LazyColumn
RecyclerView(horizontally) LazyRow
Snackbar Snackbar

一些基础知识

Scaffold
@Composable
fun 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
) 

Scaffold主要用于快速搭建一个项目的结构,包含:

  • topBar:通常是TopAppBar
  • bottomBar 通常是一个 BottomNavigation,里面每个item是BottomNavigationItem
  • floatingActionButton 悬浮按钮
  • floatingActionButtonPosition 悬浮按钮位置
  • isFloatingActionButtonDocked 悬浮按钮是否贴到 bottomBar 上
  • drawerContent 侧滑菜单
  • content:内容区域
BottomNavigationItem
fun RowScope.BottomNavigationItem(
    selected: Boolean,//是否被选中
    onClick: () -> Unit,//点击事件
    icon: @Composable () -> Unit,//icon图标
    modifier: Modifier = Modifier,
    enabled: Boolean = true,//是否可用
    label: @Composable (() -> Unit)? = null,//这里就是文本
    alwaysShowLabel: Boolean = true,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    selectedContentColor: Color = LocalContentColor.current,
    unselectedContentColor: Color = selectedContentColor.copy(alpha = ContentAlpha.medium)
)
  • selected:是否被选中
  • onClick:点击事件
  • icon:Icon的图标
  • modifier: Modifier
  • enabled:是否可用
  • label:这里就是文本内容区域
  • selectedContentColor:选中时的颜色
  • unselectedContentColor:未选中的颜色
状态
  • 官方文档:https://developer.android.google.cn/jetpack/compose/state
状态和组合

由于 Compose 是声明式工具集,因此更新它的唯一方法是通过新参数调用同一可组合项。这些参数是界面状态的表现形式。每当状态更新时,都会发生重组。因此,TextField 不会像在基于 XML 的命令式视图中那样自动更新。可组合项必须明确获知新状态,才能相应地进行更新

@Composable
fun HelloContent() {
   Column(modifier = Modifier.padding(16.dp)) {
       Text(
           text = "Hello!",
           modifier = Modifier.padding(bottom = 8.dp),
           style = MaterialTheme.typography.h5
       )
       OutlinedTextField(
           value = "",
           onValueChange = { },
           label = { Text("Name") }
       )
   }
}
  • OutlinedTextField与 TextField 只是样式不同
  • 如果运行此代码,您将不会看到任何反应。这是因为,TextField 不会自行更新,但会在其 value 参数更改时更新。
Compose中的状态
  • Composable中可以使用remember来记住单个对象。
  • 系统会在初始化由 remember计算的值存储在Composable中,并在重组的时候返回存储的值
  • remember既可以存储可变对象,也可以存储不可变对象。
注意:remember 会将对象存储在组合中,当调用 remember 的可组合项从组合中移除后,它会忘记该对象。

mutableStateOf 会创建可观察的 MutableState,后者是与 Compose 运行时集成的可观察类型。

interface MutableState : State {
    override var value: T
}

value 如有任何更改,系统会安排重组读取 value 的所有可组合函数。

在可组合项中声明 MutableState 对象的方法有三种:

  • val mutableState = remember { mutableStateOf(default) }
  • var value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }

这些声明是等效的,以语法糖的形式针对状态的不同用法提供。您选择的声明应该能够在您编写的可组合项中生成可读性最高的代码。

所以上面代码的解决办法

@Composable
fun HelloContent() {
   Column(modifier = Modifier.padding(16.dp)) {
       var name by remember { mutableStateOf("") }//定义状态
       if (name.isNotEmpty()) {
           Text(
               text = "Hello, $name!",
               modifier = Modifier.padding(bottom = 8.dp),
               style = MaterialTheme.typography.h5
           )
       }
       OutlinedTextField(
           value = name,//要显示的当前值
           onValueChange = { name = it },//请求更改值的事件,其中 T 是建议的新值
           label = { Text("Name") }
       )
   }
}

小技巧:Compose的代码模板

在搭建基本框架之前,我们先来定义一个模板,方便大家开发(我的是Mac电脑)

  • 1、Android Studio-> Preferences->Editor->File and Code Templates


    image.png
  • 2、点击➕号

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}

#end
#parse("File Header.java")

import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview

#if (${Function_Name} == "" )
@Composable
fun ${NAME}() {
}

@Preview
@Composable
fun ${NAME}Preview() {
    ${NAME}()
}
#end

#if (${Function_Name} != "" )
@Composable
fun ${Function_Name}() {
}

@Preview
@Composable
fun ${Function_Name}Preview() {
    ${Function_Name}()
}
#end

image.png
  • 3、使用,右击选择New->kotlin compose


    image.png

    image.png

基本框架搭建

效果图


效果图.gif

13.png
  • 1、新建项目,修改MainActivity
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeProjectTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    MainFrame()
                }
            }
        }
    }
}
  • 2、MainFrame
@Composable
fun MainFrame() {
    val navigationItems = listOf(
        NavigationItem("首页", Icons.Default.Home),
        NavigationItem("项目", Icons.Default.Article),
        NavigationItem("分类", Icons.Default.Category),
        NavigationItem("我的", Icons.Default.Person)
    )
    var currentNavigationIndex by remember {
        mutableStateOf(0)
    }
    Scaffold(
        bottomBar = {
            BottomNavigation(backgroundColor = MaterialTheme.colors.surface) {
                navigationItems.forEachIndexed { index, navigationItem ->
                    BottomNavigationItem(
                        selected = currentNavigationIndex == index,
                        onClick = { currentNavigationIndex = index },
                        icon = {
                            Icon(imageVector = navigationItem.icon, contentDescription = null)
                        },
                        label = {
                            Text(text = navigationItem.title)
                        },
                        selectedContentColor = Color_149EE7,
                        unselectedContentColor = Color_999999
                    )
                }
            }
        },
    ) {
        when (currentNavigationIndex) {
            0 -> HomeFragment()
            1 -> ProjectFragment()
            2 -> TypeFragment()
            else -> MineFragment()
        }
    }
}

代码其实很简单,主要通过Scaffold来搭建一个项目结构,用remember+ mutableStateOf来记住状态。内容区域通过选中的index来展示不同的Fragment

  • 3、这里运用到Google的一个图标库
    • 图标地址:https://fonts.google.com/icons
    • 集成依赖
implementation "androidx.compose.material:material-icons-extended:$compose_version"

总结

到这里呢,基本框架已经搭完了,其实还是比较简单的。有不动的呢,可以多看看Google官方文档:https://developer.android.google.cn/jetpack/compose

你可能感兴趣的:(jetpack compose实战——基本框架搭建)