屏幕适配
不同屏幕简介
可以在 设备基本信息 中查到各设备的屏幕形状和尺寸。
圆形屏幕的整个区域都供开发者绘制,而方形屏幕设备上则预先绘制了一个状态栏,以达到应用的统一性,如下图所示:
状态栏的高度为 64 px,左侧显示的是文本,右侧显示的是当前时间。文本默认为 app.json
中的 appName
字段,如果在 i18n
中配置了 appName
字段,则优先使用 i18n
中的配置。
有以下与状态栏相关的 API
- setStatusBarVisible
- 可用于控制状态栏的隐藏和显示
- updateStatusBarTitle
- 可用于设置状态栏左侧的文本显示内容
适配方案
对开发者来说,希望是一份代码能够跑在各个设备上,在现阶段我们给出了这样的两条方案:
px
函数:对相同形状的屏幕使用px
函数实现按屏幕进行比例大小缩放- 样式代码按形状区分组织:不同形状屏幕建议样式分屏幕形状分开组织,在运行时判断屏幕形状,读取相应的样式
px
全局函数
在 utils
模块实现了一个工具函数 utils - px
。
会以 小程序配置 中 targets
对象中各机型配置的 designWidth
为基准进行等比例缩放。
举一个例子,某一应用 app.json
中的 targets
配置如下:
{
...
"targets": {
"gtr-3-pro": {
"designWidth": 480
},
"gtr-3": {
"designWidth": 480
},
}
}
在上文我们可以知道,GTR 3 PRO 机型的宽度为 480
,GTR 3 机型的的宽度为 454
在下文中我们用 DEVICE_WIDTH
来指代设备的真实尺寸,那么 px(x)
函数运算的结果就是 Math.ceil(x / designWidth * DEVICE_WIDTH)
在 GTR 3 PRO 上,designWidth
的值在 app.json
中进行配置,为 480
,查询本文档上方机型尺寸,找到 DEVICE_WIDTH
值为 480
,px(100)
的执行结果就是 Math.ceil(100 / 480 * 480) = 100
在 GTR 3 上,designWidth
的值在 app.json
中进行配置,为 480
,查询本文档上方机型尺寸,找到 DEVICE_WIDTH
值为 454
,px(100)
的执行结果就是 Math.ceil(100 / 480 * 454) = 95
import { px } from '@zos/utils'
// 在 GTR 3 PRO 真机执行
console.log(px(100)) // 100
// 在 GTR 3 真机执行
console.log(px(100)) // 95
建议在进行 UI 设计时,圆屏统一以 480px
为基准,其余圆屏设备进行等比例缩放即可。
在编码层面,只需要在 app.json
中配置上缩放基准 designWidth
字段,在代码中适当的地方包裹 px
函数,就可以做到布局自适应。
import { createWidget, widget, text_style, align } from '@zos/ui'
import { px } from '@zos/utils'
const textStyle = {
x: px(96),
y: px(40),
w: px(288),
h: px(46),
color: 0xffffff,
text_size: px(36),
align_h: align.CENTER_H,
align_v: align.CENTER_V,
text_style: text_style.WRAP
}
const text = createWidget(widget.TEXT, textStyle)
样式代码按屏幕形状区分组织
与圆屏比起来,方屏在 UI 排版上发挥的空间更大一些,允许一款应用的 UI 在方屏和圆屏上会有部分不同,对于这种需求,给出一种代码组织思路:
核心思想是样式文件独立于逻辑存放,有单独的 styles.js
,在运行时获取设备的形状和尺寸,根据不同的屏幕形状,导出不同的样式变量
通过 getDeviceInfo
API 获取屏幕相关
import { getDeviceInfo, SCREEN_SHAPE_SQUARE, SCREEN_SHAPE_ROUND } from '@zos/device'
import { align, text_style } from '@zos/ui'
import { px } from '@zos/utils'
const deviceInfo = getDeviceInfo()
const { width, height, screenShape } = deviceInfo
const processStyles = (styleObj = {}) => {
return styleObj[screenShape]
}
const HOME_TITLE = {
[SCREEN_SHAPE_ROUND]: {
attrs: {
text: 'Hello World Round'
},
x: px(96),
y: px(40),
w: px(288),
h: px(46),
color: 0xffffff,
text_size: px(36),
align_h: align.CENTER_H,
align_v: align.CENTER_V,
text_style: text_style.WRAP
},
[SCREEN_SHAPE_SQUARE]: {
attrs: {
text: 'Hello World Square',
x: 32,
y: 11,
w: 232,
h: 42,
color: 0x666666,
text_size: 32,
align_h: align.CENTER_H,
align_v: align.CENTER_V,
text_style: text_style.NONE
}
}
}
export default {
HOME_TITLE: processStyles(HOME_TITLE)
}