赞
踩
1.命令式和声明式 UI大战,个人认为命令式UI自定义程度较高,能更深入到性能,内存优化方面,而申明式UI 是现在主流的设计,比如React,React Native,Flutter,Swift UI等等,现在性能也逐渐在变得更好
2.还有一个原因compose 是KMM 是完整跨平台的UI基础
3.声明式UI 个人觉得是非常适合MVVM的设计的,比android databinding 实现的xml 里面绑定vm 更适合,声明式UI一般都是基于状态管理的,只需要处理状态,至于怎么组合,怎么刷新比对 是框架给处理好的,开发不需要关心,所以逻辑稍微简单些
1.RN官方放弃,Flutter 官方宣停,Flutter也是Google ,同样compose 和kmm也是google搞的,说明google 目前是把KMM放在第一梯队的,极大成为后期的主力推荐,现在最新的Android Studio 创建的模版工程就是compose的,而且还支持iOS;
2.我的建立认知是KMM>Flutter>RN;kotlin的的语言优势较大,和Java 无缝通用
下载最新的Android Studio,(具体是从哪个版本开始没必要深纠,我的版本是Android Studio Giraffe | 2022.3.1)
List列表组建(LazyColum)
- class LazyColumnActivity: ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = MaterialTheme.colorScheme.background
- ) {
- MyLazyList()
- }
- }
- }
-
- @Composable
- fun MyLazyList(){
- val state= rememberLazyListState();
- LazyColumn(state=state){
- items(100){
- Text(text="item $it")
- }
- }
- }
- }

确实比写Adapter,和CollectionViewDelegate简单
"Jetpack Compose 是围绕可组合函数构建的。这些函数可让您以程序化方式定义应用的界面,只需描述应用界面的外观并提供数据依赖项,而不必关注界面的构建过程(初始化元素、将其附加到父项等)。如需创建可组合函数,只需将 @Composable 注解添加到函数名称中即可。" 官话
- @Composable
- fun MyText(){
- Text(text = "00000");
- return Text(text = "xfdft");
- }
上面这段代码 执行结果显示 两个重叠的文字, 其实这个return 是无效的,内嵌的两个text函数都会执行,@Composable函数的返回值是UNIT
- @Composable
- fun MyText():Int{
- Text(text = "00000FFF");
- return 1;
- }
这样改造成返回值int 类型 在实际的结果中依旧是展示了这个text 也不报错,这尼玛就有点神奇了?
Kotlin 中间代码(intermediate representation, IR),
这个是kotlin插件,是编译时的,比较深奥,参考
基于xml的布局都提供预览,Android layout ios storeboard 等,同样compose 也具备这个特性
-
- @Preview(name = "第一个预览区域")
- @Composable
- fun preview(){
- Text(text="Hello,my name is jack,What's your name");
- }
-
- @Preview(name = "第二个预览区域")
- @Composable
- fun preview2(){
- Text(text="停车坐爱枫林晚,窗前明月光");
- }
在android studio 的预览区域就会显示出来了,可以支持多个,但是在编辑的时候不是很流畅,官方还有很大的优化空间
Text:用于显示文本内容。
Image:用于显示图片。
Button:用于创建按钮。
TextField:用于接收用户输入的文本。
Column:用于垂直排列多个组件。
Row:用于水平排列多个组件。
Box:用于在屏幕上创建一个矩形的区域。
Surface:用于绘制一块可交互的区域。
Card:用于显示一个卡片式的 UI 元素。
Divider:用于在 UI 中添加分隔线。
Spacer:间距组件
- class LazyColumnActivity2: ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = MaterialTheme.colorScheme.background
- ) {
- MyLazyList()
- }
- }
- }
-
- @Composable
- fun MyLazyList(){
- val state= rememberLazyListState();
- val items= listOf<Item>(Item("张三","我是中国的"),
- Item("李四","我是中国的"),
- Item("王武","我是中国的"))
- LazyColumn(state=state){
- items(items){
- MyItem(item = it)
- }
- }
- }
-
- @Composable
- @Preview
- fun MyItemPreview(){
- MyItem(item = Item("张三","我是中国的"))
- }
-
- @Composable
- fun MyItem(item:Item){
- return Row(modifier = Modifier.padding(10.dp)) {
- Image(painter = painterResource(id = R.drawable.ic_launcher_background), contentDescription ="这是头显",
- modifier = Modifier
- .size(40.dp)
- .clip(CircleShape))
- Spacer(modifier = Modifier.width(8.dp))
- Column {
- Text(text = item.name);
- Spacer(modifier = Modifier.height(8.dp))
- Text(text = item.desc);
- }
- }
- }
-
- class Item(val name:String,val desc:String){
- }
-
- }

- /**
- * @ProjectName: Jetpack_Compose_Study
- * @Package: com.xxf.jetpack.compose.study.ui.theme
- * @ClassName: MyColumnActivity
- * @Description:
- * @Author: xuanyouwu@163.com 17611639080
- * @Date: 2023/9/4 10:25
- */
- class MyColumnActivity: ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- Jetpack_Compose_StudyTheme {
- MyColumnWidget(modifier = Modifier
- .padding(10.dp)
- .background(Color.Yellow)) {
- Text("第一行",color = Color.Black)
- Text("第二行",color= Color.Red)
- Text("第三行",color= Color.Green)
- Text("第四行",color= Color.Blue)
- }
- }
- }
- }
-
- @Composable
- fun MyColumnWidget(modifier: Modifier=Modifier,
- content:@Composable ()->Unit){
- Layout(modifier=modifier,content=content){ measurables, constraints->
- //测量元素
- val placeables = measurables.map {
- it.measure(constraints);
- }
-
- //布局
- var yPostion=0;
- layout(constraints.maxWidth,constraints.maxHeight) {
- placeables.forEach {
- it.placeRelative(x=0,y=yPostion);
- yPostion+=it.height;
- }
- }
- }
- }
- }

这个很像android 自定义组件的步骤,measure->layout
需要引入
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
大致步骤
1.使用createRefs()或者createRefFor()为ConstraintLayout中的每个组合项创建引用
2.建立绑定关系,是用modifer 中constrainAs来建立 引用绑定
3.通过约束方法linkto等 可以建立createRefs创建的引用之间的布局依赖
- class ConstraintLayoutActivity: ComponentActivity() {
-
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- MyConstraintLayout()
- }
- }
- @Composable
- fun MyConstraintLayout(){
- ConstraintLayout {
- //用createRefs 创建组件的引用
-
- //用Modifier.constrainAs(xxx)进行连接赋值
- val (button,text)=createRefs();
- Button(onClick = { }, modifier = Modifier.constrainAs(button){
- this.top.linkTo(parent.top, margin = 10.dp);
- }) {
- Text(text = "Button")
- }
-
- Text(text = "文本", modifier = Modifier.constrainAs(text){
- this.top.linkTo(button.bottom, margin = 10.dp);
- })
- }
- }
-
- }

createRefs是强引用关系,我们可以通过类似android:id 这样的方式解耦
createRefFor(id) 参数id类似于android:id 取id的方法
如下:ConstraintLayout参数形式指定约束,实现横竖屏间距不等问题
- @Composable
- fun DecoupledConstraintLayout(){
- BoxWithConstraints {
- //横竖屏设置不一样的间距
- val constraints=if(this.maxWidth<this.maxHeight){
- decoupledConstraints(10.dp)
- }else{
- decoupledConstraints(60.dp)
- }
- ConstraintLayout(constraints) {
- Button(onClick = { }, modifier = Modifier.layoutId("button")) {
- Text(text = "Button")
- }
- Text(text = "文本", modifier = Modifier.layoutId("text"))
- }
- }
- }
-
- private fun decoupledConstraints(margin:Dp):ConstraintSet{
- return ConstraintSet{
- val button=createRefFor("button");
- val text=createRefFor("text");
- constrain(button){
- this.top.linkTo(this.parent.top,margin=margin);
- }
- constrain(text){
- this.top.linkTo(button.bottom,margin);
- }
- }
- }

状态管理的常见三个函数,remember、mutableStateOf、rememberSaveable的区别
mutableStateOf:标识这个data是有状态的,如果状态发生改变,所有引用这个状态的view都将重绘;
remember:存储值,当界面重新绘制,会读取之前的值,相当于在mutableStateOf之上包了一层,把这个变量存储脱离函数,那么即使这个函数再次执行这个值并不会变成初始值,但是如果页面切换就会失效
rememberSaveable:在remember上保证了可以在页面切换的过程中保存数据,rememberSaveable==remember+onSaveInstaneState+onCreate中的read savedInstanceState,当configChanges的时候,将remember的值写入bundle中,然后重新构建activity的时候,从bundle中读取数据
- class StateActivity: ComponentActivity() {
- val vm:MyViewModel by viewModels<MyViewModel>();
- val s= androidx.compose.runtime.mutableStateOf("");
- @OptIn(ExperimentalMaterial3Api::class)
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- Column {
- //对于输入框如果不记录 就会一直输入不了,所以采取提升状态 方式将mutableStateOf升级为activity的成员
- test2(s.value) {
- s.value = it;
- };
-
- //提升状态采用remember函数记录
- test();
- }
- }
- }
-
- @OptIn(ExperimentalMaterial3Api::class)
- @Composable
- fun test(){
- val (text,setText)= remember {
- mutableStateOf("");
- }
- Row {
- TextField(value =text , onValueChange ={
- setText(it)
- },
- modifier = Modifier
- .background(Color.Green))
- Button(onClick = {
- setText("");
- }, enabled = text.isNotBlank()) {
- Text(text = "搜索")
- }
- }
- }
-
-
- @OptIn(ExperimentalMaterial3Api::class)
- @Composable
- fun test2(value:String,onTextChange:(String)->Unit){
- Row {
- TextField(value =value , onValueChange =onTextChange,
- modifier = Modifier
- .background(Color.Green))
- Button(onClick = {
- onTextChange("");
- }, enabled = value.isNotBlank()) {
- Text(text = "搜索")
- }
- }
- }
-
- class MyViewModel: ViewModel() {
- val state= MutableLiveData<Boolean>(true);
- }
- }

下面将对博客进行分篇,点击下面的链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。