Skip to content

Commit

Permalink
简单的自定义modifier开始
Browse files Browse the repository at this point in the history
  • Loading branch information
iOrchid committed Apr 20, 2024
1 parent f7bef68 commit 66ac1f0
Show file tree
Hide file tree
Showing 4 changed files with 430 additions and 10 deletions.
20 changes: 14 additions & 6 deletions compose/src/main/java/org/zhiwei/compose/model/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,23 @@ import org.zhiwei.compose.screen.basic.material3.TextField_Screen
import org.zhiwei.compose.screen.basic.material3.Text_Screen
import org.zhiwei.compose.screen.basic.material3.TopAppbarTabs_Screen
import org.zhiwei.compose.screen.basic.material3.Widget_Screen
import org.zhiwei.compose.screen.layout.UI_CustomModifier

/**
* 用于配置整个Compose模块内所有可跳转的页面UI,用于Navigation导航
*/
internal fun configPageRoute(modifier: Modifier, onBack: (() -> Unit) = {}): List<CourseItemModel> {
val list = mutableListOf<CourseItemModel>()
list.addAll(BasicScreenUIs.basicCourses(modifier, onBack))
list.addAll(LayoutScreenUIs.layoutCourses(modifier))
return list
}


//region basicScreen基础控件

internal object BasicScreenUIs {
//所有基础内容的list
//所有基础内容的list,⚠️todo 除了要用于填充页面,还要在上面添加到list中,注册页面导航route
internal fun basicCourses(modifier: Modifier = Modifier, onBack: (() -> Unit) = {}) = listOf(
CourseItemModel(
"Column,Rom,Box,Modifiers",
Expand Down Expand Up @@ -94,12 +102,12 @@ internal object BasicScreenUIs {

//region LayoutScreen布局相关
internal object LayoutScreenUIs {
//所有基础内容的list
internal fun layoutCourses(modifier: Modifier = Modifier, onBack: (() -> Unit) = {}) = listOf(
//所有基础内容的list ⚠️todo 除了要用于填充页面,还要在上面添加到list中,注册页面导航route
internal fun layoutCourses(modifier: Modifier = Modifier) = listOf(
CourseItemModel(
"Column,Rom,Box,Modifiers",
"列,行,箱,都是容器,顾名思义就是成列,成行和层叠摆放内部子控件;及修饰符Modifier内外边距等基本使用"
) { Box_Column_Row_Screen(modifier) },
"Custom Modifier",
"创建自定义的modifier,来处理布局layout,测量measurable,约束constraint,占位等"
) { UI_CustomModifier(modifier) },
)
}
//endregion
7 changes: 3 additions & 4 deletions compose/src/main/java/org/zhiwei/compose/screen/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import kotlinx.coroutines.launch
import org.zhiwei.compose.model.BasicScreenUIs
import org.zhiwei.compose.model.TabPagerModel
import org.zhiwei.compose.model.configPageRoute
import org.zhiwei.compose.screen.basic.Basic_Screen
import org.zhiwei.compose.screen.gesture.GestureScreen
import org.zhiwei.compose.screen.graphics.GraphicsScreen
Expand All @@ -54,9 +54,8 @@ internal fun Home_Screen(modifier: Modifier = Modifier) {
composable(route = "HomeScreen") {
HomeScreenContent(modifier, navController = navController)
}

//基础组件下的 每个可导航的页面,需要使用composable来设置
BasicScreenUIs.basicCourses(modifier) { navController.navigateUp() }.forEach { model ->
//配置所有pager下的页面,每个item对应页面 可导航的页面,需要使用composable来设置
configPageRoute(modifier) { navController.navigateUp() }.forEach { model ->
composable(route = model.title) {
//model中ui的属性字段是个函数,需要invoke来调用
model.ui()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package org.zhiwei.compose.screen.layout

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
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.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.AlignmentLine
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.layout
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import org.zhiwei.compose.ui.widget.Title_Desc_Text
import org.zhiwei.compose.ui.widget.Title_Sub_Text
import org.zhiwei.compose.ui.widget.Title_Text

@Composable
internal fun UI_CustomModifier(modifier: Modifier = Modifier) {
LazyColumn(modifier.fillMaxSize()) {
item {
Title_Text("Custom Modifier")
Title_Sub_Text(title = "1、使用compose的layout库中的Modifier的扩展函数,来获取一个可用于测量尺寸,宽高及布局相关的Modifier对象")
Title_Desc_Text(desc = "custom Align modifier")
//下面使用了自定义的扩展函数customAlign,给内部的控件一个定植边距,以及添加对齐方式
val modifier = Modifier
.padding(8.dp)
.fillMaxWidth()
.background(Color.LightGray)
Column(modifier.wrapContentHeight()) {
Text(
text = "Align Start with space",
modifier = Modifier
.background(Color(0xFF8BC34A))
.customAlign(align = HorizontalAlign.START)
)

Text(
text = "Align Center with space",
modifier = Modifier
.background(Color(0xFF8BC34A))
.customAlign(align = HorizontalAlign.CENTER)
)

Text(
text = "Align End with space",
modifier = Modifier
.background(Color(0xFF8BC34A))
.customAlign(align = HorizontalAlign.END)
)
}
Title_Desc_Text(desc = "firstBaselineToTop Modifier")
//对比两个text,因为属性不同,padding 32dp和baseLine top 32dp的效果;
//padding 是从Text文本的top开始计算。而baseLine是绘制基线
Row(modifier.wrapContentHeight()) {
Text(
text = "Padding 32dp",
modifier = Modifier
.background(Color(0xFF8BC34A))
.padding(top = 32.dp)
)
Spacer(modifier = Modifier.width(20.dp))
Text(
text = "Baseline 32dp",
modifier = Modifier
.background(Color(0xFF8BC34A))
.firstBaselineToTop(32.dp)
)
}
Title_Sub_Text(title = "2、LayoutModifier对可测量对象布局,添加内边距")
Title_Desc_Text(desc = "custom padding modifier")
//实现LayoutModifier来自定义内边距函数
Text(
text = "Custom Padding",
modifier = Modifier
.background(Color(0xFF8BC34A))
.paddingNoOffsetNoConstrain(all = 4.dp)
)
}
}
}


//region 通过layout的自定义扩展函数


//自定义的水平对其方式
enum class HorizontalAlign {
START, CENTER, END
}

/**
* 自定义的Modifier的扩展函数,基于原modifier对象,继续作用效果;
* 给内部可测量[Measurable]的对象两边都加上一定值的空白空间,并实现自定义布局对齐方式
* 尤其注意,是作用于[Measurable]对象,Text是。
*/
private fun Modifier.customAlign(
space: Int = 60,
align: HorizontalAlign = HorizontalAlign.CENTER,
//todo 注意⚠️这里的then函数,暂时未详细学习,简单理解就是字面意思,基于上个modifier对象的作用效果,继续后续操作
) = this.then(

layout { measurable: Measurable, constraints: Constraints ->

val placeable = measurable.measure(constraints)
val width = placeable.measuredWidth + 2 * space

layout(width, placeable.measuredHeight) {
when (align) {
HorizontalAlign.START -> {
placeable.placeRelative(0, 0)
}

HorizontalAlign.CENTER -> {
placeable.placeRelative(space, 0)
}

HorizontalAlign.END -> {
placeable.placeRelative(2 * space, 0)
}
}
}
}
)


/**
* 自定义的modifier扩展函数,实现对layout中的首行text的绘制基线baseline添加上边距
*/
private fun Modifier.firstBaselineToTop(firstBaselineToTop: Dp) = this.then(
layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
//判断 composable 控件 是否有首行基线FirstBaseline
check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
val firstBaseline = placeable[FirstBaseline]
// 高度计算
val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
val height = placeable.height + placeableY
layout(placeable.width, height) {
// 布局摆放
placeable.placeRelative(0, placeableY)
}
}
)

//endregion

//region 预览效果

@Preview(showBackground = true, backgroundColor = 0XFFFFFFFF)
@Composable
private fun CustomModifierPreview() {
UI_CustomModifier()
}

//endregion
Loading

0 comments on commit 66ac1f0

Please sign in to comment.