本篇过于简陋,请移步第二版: Jetpack Compose屏幕适配(第二版)
学习Compose
最近鼓起勇气开始学习Compose,听说Compose可以提升开发效率、降低bug出现的概率,摆脱各种xml的束缚,所以打算丢弃所有和View相关的东西重构项目。
1.0版本发布的时候,那种风格和思维方式着实让我吓了一跳,以至于出来这么就都没有去学习。最近官方订阅号一直在强推Compose,再对比了一下如今的开发效率,作为跨界三流程序员,我是真的不想再深入研究View之类的东西了。这次花了一点时间学习了一下,探索出了一个比较简单的方式实现屏幕适配。用我的能力去理解,大概就是:在不同设备中,界面布局尽量与设计图保持一致。
开始
首先,阅读这篇文章,了解一下适配的思路 :一种极低成本的Android屏幕适配方式
当了解了各项重要的指标之后,整理下来无非就是三样东西:DP(密度无关像素)
、PX(像素)
、Density(像素密度)
在Compose中,从官方的介绍里面不难看出,定义尺寸需要用到以下两种方式:
- 组合函数(暂且叫控件吧)的尺寸
Box(
modifier = Modifier.size(100.dp, 100.dp)
) {
//Content
}
使用dp
扩展方法,将数字(Number
类)转化为DP
对象
- 文字尺寸
Text(
text = "Hello!!!",
fontSize = 12.sp
)
使用sp
扩展方法,将数字(Number
类)转化为TextUnit
对象
对于尺寸的定义,目前我知道的就这两种,如果以后探索的更多,我会一直学习并记录。
核心
如果要适配设计图,其实就和之前的文章提到的一样,需要修改Density
,但对于一个生手来说,修改底层的一些东西会不会碰到各种各样不好解决的问题?索性干脆不要改系统的density,直接把适配之后的尺寸换算出来,用作各个部件的宽高,应该能解决问题。
流程其实很简单:
- 获取设计图的
Density
- 根据设计图的
Density
将尺寸换算为PX
- 将设计图的
PX
换算成当前屏幕的DP
代码
适用于控件
const val designWidth = 360f //设计图屏幕的宽度,视为一倍的尺寸
const val designHeight= 640f //设计图屏幕的高度,视为一倍的尺寸
val Number.compatDP: Dp
get() {
val res = Resources.getSystem()
val displayMetrics = res.displayMetrics
val density = if (res.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
displayMetrics.widthPixels.toFloat() / designHeight
} else {
displayMetrics.widthPixels.toFloat() / designWidth
}
val pixel = toFloat() * density
return (pixel / displayMetrics.density).dp
}
适用于文字
const val designWidth = 360f //设计图屏幕的宽度,视为一倍的尺寸
const val designHeight= 640f //设计图屏幕的高度,视为一倍的尺寸
val Number.compatSP: TextUnit
get() {
val res = Resources.getSystem()
val displayMetrics = res.displayMetrics
val density = if (res.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
displayMetrics.widthPixels.toFloat() / designHeight
} else {
displayMetrics.widthPixels.toFloat() / designWidth
}
val pixel = toFloat() * density
return (pixel / displayMetrics.scaledDensity).sp
}
注意中间计算density
时,需要判断横竖屏,否则尺寸会有问题。
最后,只需要调用扩展方法compatDP
、compatSP
即可
特别注意!!!!
如果有使用纯 View
的界面跳转至 Compose
界面,尺寸会出现异常,因为 View
界面使用了修改 DisplayMetrics
的方式进行适配,这种方式是全局的,必须要在 Compose
界面中进行还原,基于项目紧急程度,暂时就不展开了。
结尾
这只是个人觉得最简单的一种方法,不需要导包写配置,如果有更好的办法请在评论区指导。
非科班出身,如有错误,欢迎指正。