JetPack Compose 实战 Jetchat(4)
我们继续官方Jetchat这个项目讲解
MainActivity 的入口最后一部分代码
JetchatScaffold(
scaffoldState,
onChatClicked = {
findNavController(R.id.nav_host_fragment)
.popBackStack(R.id.nav_home, true)
scaffoldState.drawerState.close()
},
onProfileClicked = {
val bundle = bundleOf("userId" to it)
findNavController(R.id.nav_host_fragment).navigate(
R.id.nav_profile,
bundle
)
scaffoldState.drawerState.close()
}
) {
// Workaround for https://issuetracker.google.com/178174718
// and https://issuetracker.google.com/179181757
// Inflate the XML layout using View Binding:
val bindingRef = remember { Ref<ViewBinding>() }
val currentView = LocalView.current
AndroidViewBinding({ inflater, parent, attachToParent ->
if (bindingRef.value == null) {
val binding: ViewBinding =
ContentMainBinding.inflate(inflater, parent, attachToParent)
bindingRef.value = binding
binding.root.compositionContext =
currentView.findViewTreeCompositionContext()
}
bindingRef.value as ViewBinding
})
// End of workaround
// AndroidViewBinding(ContentMainBinding::inflate)
}
JetchatScaffold
封装了自己的脚手架或者页面主题和布局
@Composable
fun JetchatScaffold(
scaffoldState: ScaffoldState = rememberScaffoldState(),
onProfileClicked: (String) -> Unit,
onChatClicked: (String) -> Unit,
content: @Composable (PaddingValues) -> Unit
) {
JetchatTheme {
Scaffold(
scaffoldState = scaffoldState,
drawerContent = {
JetchatDrawer(
onProfileClicked = onProfileClicked,
onChatClicked = onChatClicked
)
},
bodyContent = content
)
}
}
利用组合思想内部封装了JetchatTheme 自定义主题
@Composable
fun JetchatTheme(
isDarkTheme: Boolean = isSystemInDarkTheme(),
colors: Colors? = null,
content: @Composable () -> Unit
) {
val myColors = colors ?: if (isDarkTheme) JetchatDarkPalette else JetchatLightPalette
MaterialTheme(
colors = myColors,
content = content,
typography = JetchatTypography,
shapes = JetchatShapes
)
}
我们看到这里就要回顾主题相关知识。isDarkTheme 判断是否是深色主题,那么MaterialDesign方式封装了两套主题。深色和浅色
JetchatDarkPalette 和 JetchatLightPalette
private val JetchatDarkPalette = darkColors(
primary = Blue200,
primaryVariant = Blue400,
onPrimary = Color.Black,
secondary = Yellow400,
onSecondary = Color.Black,
onSurface = Color.White,
onBackground = Color.White,
error = Red300,
onError = Color.Black
)
private val JetchatLightPalette = lightColors(
primary = Blue500,
primaryVariant = Blue800,
onPrimary = Color.White,
secondary = Yellow700,
secondaryVariant = Yellow800,
onSecondary = Color.Black,
onSurface = Color.Black,
onBackground = Color.Black,
error = Red800,
onError = Color.White
)
使用看来很简单,特别想C++里面的结构提,其实就是两个全局变量
封装自己的字体等样式排版,val JetchatTypography---Typography
特别接近CSS 有这个感觉没,好像高级CSS也是面向对象,本人对网页不是很熟。
学习到定义形状,三个Shapes
val JetchatShapes = Shapes(
small = RoundedCornerShape(50),
medium = RoundedCornerShape(8.dp),
large = RoundedCornerShape(0.dp)
)
看似有电生疏,我们没有做东西而已。
系统MaterialTheme
定义好了参数,我们自定义传入就好
接下来,我们要到过来,向上层看。
JetchatTheme 组合传入的就是JetchatDrawer
上篇文章提到过。
封装的就是这个布局和点击事件 onProfileClicked,onChatClicked
-
粗略的看 Spacer 定义了layout布局传入Modifier
-
类似Android传统,定义Header DawerHeader()---组合Row两个Image
-
运行项目会看到一个分割线 Divider(),
-
DrawerItemHeader 定义标题头 Chats
-
接下来定义两个ChatItem,包括点击事件,就不看封装源码。
-
DrawerItemHeader 标题头
-
接下来定义两个ProfileItem 组合控件。
继续向上层回溯看。
JetchatScoffold里面 定义跳转用的Navigation,NavController
内容,用View Binding结合inflate出XML布局
// Inflate the XML layout using View Binding:
val bindingRef = remember { Ref<ViewBinding>() }
val currentView = LocalView.current
AndroidViewBinding({ inflater, parent, attachToParent ->
if (bindingRef.value == null) {
val binding: ViewBinding =
ContentMainBinding.inflate(inflater, parent, attachToParent)
bindingRef.value = binding
binding.root.compositionContext =
currentView.findViewTreeCompositionContext()
}
bindingRef.value as ViewBinding
})
我们注意到remember
记录值用的,可以理解缓存。
还有很多地方,看的不是很清晰,整体来看,大致整个小项目,还是很简单。