当前位置:   article > 正文

JetPack Compose 入门教程(持续整理笔记)_createrefs

createrefs

1.为什么要学?

 1.命令式和声明式 UI大战,个人认为命令式UI自定义程度较高,能更深入到性能,内存优化方面,而申明式UI 是现在主流的设计,比如React,React Native,Flutter,Swift UI等等,现在性能也逐渐在变得更好
2.还有一个原因compose 是KMM 是完整跨平台的UI基础
3.声明式UI 个人觉得是非常适合MVVM的设计的,比android databinding 实现的xml 里面绑定vm 更适合,声明式UI一般都是基于状态管理的,只需要处理状态,至于怎么组合,怎么刷新比对 是框架给处理好的,开发不需要关心,所以逻辑稍微简单些


2.前景?

1.RN官方放弃,Flutter 官方宣停,Flutter也是Google ,同样compose 和kmm也是google搞的,说明google 目前是把KMM放在第一梯队的,极大成为后期的主力推荐,现在最新的Android Studio 创建的模版工程就是compose的,而且还支持iOS;
2.我的建立认知是KMM>Flutter>RN;kotlin的的语言优势较大,和Java 无缝通用

hello word

下载最新的Android Studio,(具体是从哪个版本开始没必要深纠,我的版本是Android Studio Giraffe | 2022.3.1)

 

 

List列表组建(LazyColum)

  1. class LazyColumnActivity: ComponentActivity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. setContent {
  5. Surface(
  6. modifier = Modifier.fillMaxSize(),
  7. color = MaterialTheme.colorScheme.background
  8. ) {
  9. MyLazyList()
  10. }
  11. }
  12. }
  13. @Composable
  14. fun MyLazyList(){
  15. val state= rememberLazyListState();
  16. LazyColumn(state=state){
  17. items(100){
  18. Text(text="item $it")
  19. }
  20. }
  21. }
  22. }

 确实比写Adapter,和CollectionViewDelegate简单

Compose函数


"Jetpack Compose 是围绕可组合函数构建的。这些函数可让您以程序化方式定义应用的界面,只需描述应用界面的外观并提供数据依赖项,而不必关注界面的构建过程(初始化元素、将其附加到父项等)。如需创建可组合函数,只需将 @Composable 注解添加到函数名称中即可。" 官话

  1. @Composable
  2. fun MyText(){
  3. Text(text = "00000");
  4. return Text(text = "xfdft");
  5. }

上面这段代码 执行结果显示 两个重叠的文字, 其实这个return 是无效的,内嵌的两个text函数都会执行,@Composable函数的返回值是UNIT

  1. @Composable
  2. fun MyText():Int{
  3. Text(text = "00000FFF");
  4. return 1;
  5. }

这样改造成返回值int 类型 在实际的结果中依旧是展示了这个text 也不报错,这尼玛就有点神奇了?

Kotlin 中间代码(intermediate representation, IR),
这个是kotlin插件,是编译时的,比较深奥,参考
 

预览函数


基于xml的布局都提供预览,Android layout ios storeboard 等,同样compose 也具备这个特性

  1. @Preview(name = "第一个预览区域")
  2. @Composable
  3. fun preview(){
  4. Text(text="Hello,my name is jack,What's your name");
  5. }
  6. @Preview(name = "第二个预览区域")
  7. @Composable
  8. fun preview2(){
  9. Text(text="停车坐爱枫林晚,窗前明月光");
  10. }

在android studio 的预览区域就会显示出来了,可以支持多个,但是在编辑的时候不是很流畅,官方还有很大的优化空间

Compose 组件清单大全

Text:用于显示文本内容。
Image:用于显示图片。
Button:用于创建按钮。
TextField:用于接收用户输入的文本。
Column:用于垂直排列多个组件。
Row:用于水平排列多个组件。
Box:用于在屏幕上创建一个矩形的区域。
Surface:用于绘制一块可交互的区域。
Card:用于显示一个卡片式的 UI 元素。
Divider:用于在 UI 中添加分隔线。

Spacer:间距组件

例子:结合行列间距来实现简单的列表样式

  1. class LazyColumnActivity2: ComponentActivity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. setContent {
  5. Surface(
  6. modifier = Modifier.fillMaxSize(),
  7. color = MaterialTheme.colorScheme.background
  8. ) {
  9. MyLazyList()
  10. }
  11. }
  12. }
  13. @Composable
  14. fun MyLazyList(){
  15. val state= rememberLazyListState();
  16. val items= listOf<Item>(Item("张三","我是中国的"),
  17. Item("李四","我是中国的"),
  18. Item("王武","我是中国的"))
  19. LazyColumn(state=state){
  20. items(items){
  21. MyItem(item = it)
  22. }
  23. }
  24. }
  25. @Composable
  26. @Preview
  27. fun MyItemPreview(){
  28. MyItem(item = Item("张三","我是中国的"))
  29. }
  30. @Composable
  31. fun MyItem(item:Item){
  32. return Row(modifier = Modifier.padding(10.dp)) {
  33. Image(painter = painterResource(id = R.drawable.ic_launcher_background), contentDescription ="这是头显",
  34. modifier = Modifier
  35. .size(40.dp)
  36. .clip(CircleShape))
  37. Spacer(modifier = Modifier.width(8.dp))
  38. Column {
  39. Text(text = item.name);
  40. Spacer(modifier = Modifier.height(8.dp))
  41. Text(text = item.desc);
  42. }
  43. }
  44. }
  45. class Item(val name:String,val desc:String){
  46. }
  47. }

例子:自定义线性布局cloumn

  1. /**
  2. * @ProjectName: Jetpack_Compose_Study
  3. * @Package: com.xxf.jetpack.compose.study.ui.theme
  4. * @ClassName: MyColumnActivity
  5. * @Description:
  6. * @Author: xuanyouwu@163.com 17611639080
  7. * @Date: 2023/9/4 10:25
  8. */
  9. class MyColumnActivity: ComponentActivity() {
  10. override fun onCreate(savedInstanceState: Bundle?) {
  11. super.onCreate(savedInstanceState)
  12. setContent {
  13. Jetpack_Compose_StudyTheme {
  14. MyColumnWidget(modifier = Modifier
  15. .padding(10.dp)
  16. .background(Color.Yellow)) {
  17. Text("第一行",color = Color.Black)
  18. Text("第二行",color= Color.Red)
  19. Text("第三行",color= Color.Green)
  20. Text("第四行",color= Color.Blue)
  21. }
  22. }
  23. }
  24. }
  25. @Composable
  26. fun MyColumnWidget(modifier: Modifier=Modifier,
  27. content:@Composable ()->Unit){
  28. Layout(modifier=modifier,content=content){ measurables, constraints->
  29. //测量元素
  30. val placeables = measurables.map {
  31. it.measure(constraints);
  32. }
  33. //布局
  34. var yPostion=0;
  35. layout(constraints.maxWidth,constraints.maxHeight) {
  36. placeables.forEach {
  37. it.placeRelative(x=0,y=yPostion);
  38. yPostion+=it.height;
  39. }
  40. }
  41. }
  42. }
  43. }

这个很像android 自定义组件的步骤,measure->layout

例子:用ConstraintLayout来实现相对布局

需要引入 

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"

大致步骤
1.使用createRefs()或者createRefFor()为ConstraintLayout中的每个组合项创建引用
2.建立绑定关系,是用modifer 中constrainAs来建立 引用绑定
3.通过约束方法linkto等 可以建立createRefs创建的引用之间的布局依赖

  1. class ConstraintLayoutActivity: ComponentActivity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. setContent {
  5. MyConstraintLayout()
  6. }
  7. }
  8. @Composable
  9. fun MyConstraintLayout(){
  10. ConstraintLayout {
  11. //用createRefs 创建组件的引用
  12. //用Modifier.constrainAs(xxx)进行连接赋值
  13. val (button,text)=createRefs();
  14. Button(onClick = { }, modifier = Modifier.constrainAs(button){
  15. this.top.linkTo(parent.top, margin = 10.dp);
  16. }) {
  17. Text(text = "Button")
  18. }
  19. Text(text = "文本", modifier = Modifier.constrainAs(text){
  20. this.top.linkTo(button.bottom, margin = 10.dp);
  21. })
  22. }
  23. }
  24. }

createRefs是强引用关系,我们可以通过类似android:id        这样的方式解耦
createRefFor(id) 参数id类似于android:id 取id的方法
如下:ConstraintLayout参数形式指定约束,实现横竖屏间距不等问题
 

  1. @Composable
  2. fun DecoupledConstraintLayout(){
  3. BoxWithConstraints {
  4. //横竖屏设置不一样的间距
  5. val constraints=if(this.maxWidth<this.maxHeight){
  6. decoupledConstraints(10.dp)
  7. }else{
  8. decoupledConstraints(60.dp)
  9. }
  10. ConstraintLayout(constraints) {
  11. Button(onClick = { }, modifier = Modifier.layoutId("button")) {
  12. Text(text = "Button")
  13. }
  14. Text(text = "文本", modifier = Modifier.layoutId("text"))
  15. }
  16. }
  17. }
  18. private fun decoupledConstraints(margin:Dp):ConstraintSet{
  19. return ConstraintSet{
  20. val button=createRefFor("button");
  21. val text=createRefFor("text");
  22. constrain(button){
  23. this.top.linkTo(this.parent.top,margin=margin);
  24. }
  25. constrain(text){
  26. this.top.linkTo(button.bottom,margin);
  27. }
  28. }
  29. }

状态管理


状态管理的常见三个函数,remember、mutableStateOf、rememberSaveable的区别
mutableStateOf:标识这个data是有状态的,如果状态发生改变,所有引用这个状态的view都将重绘;
remember:存储值,当界面重新绘制,会读取之前的值,相当于在mutableStateOf之上包了一层,把这个变量存储脱离函数,那么即使这个函数再次执行这个值并不会变成初始值,但是如果页面切换就会失效
rememberSaveable:在remember上保证了可以在页面切换的过程中保存数据,rememberSaveable==remember+onSaveInstaneState+onCreate中的read savedInstanceState,当configChanges的时候,将remember的值写入bundle中,然后重新构建activity的时候,从bundle中读取数据

  1. class StateActivity: ComponentActivity() {
  2. val vm:MyViewModel by viewModels<MyViewModel>();
  3. val s= androidx.compose.runtime.mutableStateOf("");
  4. @OptIn(ExperimentalMaterial3Api::class)
  5. override fun onCreate(savedInstanceState: Bundle?) {
  6. super.onCreate(savedInstanceState)
  7. setContent {
  8. Column {
  9. //对于输入框如果不记录 就会一直输入不了,所以采取提升状态 方式将mutableStateOf升级为activity的成员
  10. test2(s.value) {
  11. s.value = it;
  12. };
  13. //提升状态采用remember函数记录
  14. test();
  15. }
  16. }
  17. }
  18. @OptIn(ExperimentalMaterial3Api::class)
  19. @Composable
  20. fun test(){
  21. val (text,setText)= remember {
  22. mutableStateOf("");
  23. }
  24. Row {
  25. TextField(value =text , onValueChange ={
  26. setText(it)
  27. },
  28. modifier = Modifier
  29. .background(Color.Green))
  30. Button(onClick = {
  31. setText("");
  32. }, enabled = text.isNotBlank()) {
  33. Text(text = "搜索")
  34. }
  35. }
  36. }
  37. @OptIn(ExperimentalMaterial3Api::class)
  38. @Composable
  39. fun test2(value:String,onTextChange:(String)->Unit){
  40. Row {
  41. TextField(value =value , onValueChange =onTextChange,
  42. modifier = Modifier
  43. .background(Color.Green))
  44. Button(onClick = {
  45. onTextChange("");
  46. }, enabled = value.isNotBlank()) {
  47. Text(text = "搜索")
  48. }
  49. }
  50. }
  51. class MyViewModel: ViewModel() {
  52. val state= MutableLiveData<Boolean>(true);
  53. }
  54. }

下面将对博客进行分篇,点击下面的链接

Text组件

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/254120
推荐阅读
相关标签
  

闽ICP备14008679号