# 设备屏幕适配
# 1. 现有设备类型
当前主流设备在端上的屏幕尺寸比例(dpl 模板中使用的 dp 单位和 px 单位是1:1的对应关系),UE提供的视觉稿标注应该以下面提供的屏幕逻辑宽高值来作为参考。
设备名称类型 | 屏幕逻辑宽度 | 屏幕逻辑高度 |
---|---|---|
小度在家7寸屏系列 | 960dp | 562dp |
小度在家5寸屏 | 960dp | 480dp |
小度在家8寸屏 | 960dp | 600dp |
可以看到,目前仅以原有设备上通用设计稿给定的 960dp X 562 设计稿实现,如果基于宽度960dp铺满来定义屏幕宽高的话(设备的高度会基于屏幕本身的宽高比进行对应的缩放),duershow设备完美契合(屏幕逻辑高度562dp),x8会因自身高度超出而产生上下间的留白(屏幕逻辑高度600dp);而x5,在填充自己满屏高度的480dp内容后,在本身内容不可纵向滑动的前提下,会导致剩余高度需要展现的内容被截断无法呈现在屏幕上(屏幕逻辑高度480dp),因此,目前提供给开发者使用更好的方案来实现各个端不同情况下内容的完整渲染呈现。
# 2. viewport
目前,dpl 模板中应用的默认自适应方式是以设定 viewport(具体含义可参考下面一小节中的描述)中宽为 960dp的方式,并以在document文档协议描述中,基于使用具体样式宽高属性数值对各个组件使用和布局使用,来实现各个设备上以宽度铺满情况下的默认渲染展现。
# 使用方式
// dpl 中使用 viewport 的方式
{
"type":"DPL",
"version":"2.0",
"duration": {{INTEGER}},
"renderConfig": {
"viewport": {
"width": 960,
"height": 562
}
}
...
}
端上渲染DPL 模板时,会通过判断是否存在viewport后,通过调用 defineWindow, 去设置当前的屏幕展示宽高(windowWidth = viewport.width || windowheight = viewport.height),注意,在viewport中,当同时存在 width 和 height 属性时,width 属性取值优先(端设定只能基于这两个属性中的其中一个来确定实际视图大小)。
# 3. stylesheet
通过class与mediaquery的组合使用,可以更好的支持基于不同尺寸的适配问题
stylesheet字段可以是一个单对象或者一个数组,其中每个对象以 key 表示 className 信息,可以使用,
来分割多个 className。基于实际需求的不同,可以是简单的通过stylesheet,设置模板所需要的class类,或者基于不同屏幕尺寸的设备适配需求,配合 mediaquery,来基于设备宽高区分配置不同的样式属性。
# class
通过将组件中频繁使用到的一些样式属性聚合起来形成 class 类,存放到 stylesheet 中,可供多个组件去申明使用该class,然后端上渲染对应组件时会将自己引用的 class 在 stylesheet 中检索、提取,以达到减少云端下发数据量和便于修改、复用的目的;
注意:如果组件通过class和styles声明了同一个样式属性,class中的该样式属性会失效(styles中的声明优先级更高)
# 使用示例(example)
class 使用方式1:
{
"type":"DPL",
"version":"2.0",
"stylesheet": [
{
"bubble_Hint": {
"height": "44dp",
"padding-left": "24dp",
"padding-right": "24dp",
"min-width": "120dp",
"max-width": "600dp",
"justify-content": "center",
"align-items": "center",
"background-color": "rgba(255, 255, 255, 0.1)",
"border-radius": "18dp 20dp 20dp 0dp"
},
"test-height": {
"height": "320dp"
}
},
...
]
}
# mediaquery
设置不同类型的设备屏幕分辨率条件,并根据对应的条件,给相应符合条件的设备端调用相对应的样式表,通过宽度和高度的表达式限制,允许内容的呈现针对一个特定范围的输出设备而进行裁剪,而不必改变内容本身。
在需要基于不同设备来区分使用不同的样式属性的时候,通过在 stylesheet 中设置 mediaQuery,同时把原本应该的class内容放到classList字段中。
1. mediaQuery: "(min-width: 500dp)":
标明该对象下对应 classList 的样式属性可以生效前提是设备的最小宽度必须大于等于 500dp;
2. mediaQuery: "(min-width: 500dp) and (max-width: 1000dp)":
标明该对象下对应 classList 的样式属性可以生效得到前提是设备的宽度范围必须在 500dp 到 1000dp之间;
3. mediaQuery: "(max-width: 500dp) , (min-hight: 400dp) ":
标明该对象下对应 classList 的样式属性可以生效得到前提是设备的宽高必须在最大不超过500dp 高度且高度不小于 100dp;
4. mediaQuery: "(500dp <= width <= 1000dp) ":
标明该对象下对应 classList 的样式属性可以生效得到前提是设备的宽度范围必须在 500dp 到 1000dp之间(与2 等价);
5. mediaQuery: ”x5":
目前专门为5寸设备(2:1宽高比)设定的名称描述方式,等价于 ”(max-height: 480dp)“
# 使用示例(example)
{
"type":"DPL",
"version":"2.0",
"stylesheet": [{
"bubble_Hint": {
"height": "44dp",
"padding-left": "24dp",
"padding-right": "24dp",
"min-width": "120dp",
"max-width": "600dp",
"justify-content": "center",
"align-items": "center",
"background-color": "rgba(255, 255, 255, 0.1)",
"border-radius": "18dp 20dp 20dp 0dp"
},
"test-height": {
"height": "320dp"
}
},
{
"mediaQuery": "x5",
"classList": {
"test-height": {
"height": "220dp"
}
}
}]
}
# 4. 适配方案
# 背景
目前,使用 DuerOS 且能支持 DPL 模板使用的设备和类型(不同宽高占比)越来越多,通过一套设计稿给定的模板样式无法完美的兼容各类宽高比例的设备(特别是部分布局场景下,某些宽高差异大的设备上展现内容被截断),因此,需要 stylesheet 通过使用 mediaquery 的方式,来配置在不同宽高范围内的样式属性,以达到基于不同设备端,进行不同样式渲染展现,更好呈现内容的目的。
# 使用样例(demo)
{
"type":"DPL",
"version":"2.0",
"stylesheet": [{
"bubble_Hint": {
"height": "44dp",
"padding-left": "24dp",
"padding-right": "24dp",
"min-width": "120dp",
"max-width": "600dp",
"justify-content": "center",
"align-items": "center",
"background-color": "rgba(255, 255, 255, 0.1)",
"border-radius": "18dp 20dp 20dp 0dp"
},
"test-height": {
"height": "320dp"
}
},
{
"mediaQuery": "x5",
"classList": {
"test-height": {
"height": "220dp"
}
}
}],
"dataSource": {
"pageData": [
{
"english": "Let life be beautiful like summer flowers and death like autumn leaves.",
"chinese": "使生如夏花之绚烂,死如秋叶之静美。",
"src": "https://iknow-pic.cdn.bcebos.com/fcfaaf51f3deb48fdac0bbb9fd1f3a292df5782f?x-bce-process=image/resize,m_lfit,w_600,h_800,limit_1"
},
{
"english": "If you shed tears when you miss the sun, you also miss the stars.",
"chinese": "如果你因失去了太阳而流泪,那么你也失去了群星。",
"src": "https://iknow-pic.cdn.bcebos.com/fcfaaf51f3deb48fdac0bbb9fd1f3a292df5782f?x-bce-process=image/resize,m_lfit,w_600,h_800,limit_1"
}
]
},
"mainTemplate": {
"parameters": [
"payload"
],
"items": [
{
"type": "Container",
"styles": {
"flex": 1,
"justify-content":"space-between"
},
"items": [
{
"type": "Image",
"styles": {
"position": "absolute",
"left": "0dp",
"top": "0dp",
"scale-type": "centerCrop",
"height": "100%",
"width": "100%"
},
"props": {
"src": "https://duerstatic.cdn.bcebos.com/swan%2Fdpl_demo%2Fcommon-bg.png"
}
},
{
"type": "Header",
"props": {
"title": "适配能力测试(mediaquery)",
"sideIcon": "https://d2o906d8ln7ui1.cloudfront.net/images/cheeseskillicon.png",
"sideText": "demo2.0"
}
},
{
"type": "Pager",
"componentId":"demo_pager_1",
"styles": {
"flex":"1",
"margin":"0dp 48dp"
},
"props":{
"initialPage":0,
"direction": "horizontal",
"userInteraction": true
},
"items":[
{
"type": "Container",
"styles": {
"justify-content": "flex-start",
"align-items": "flex-start"
},
"items": [
{
"type": "Container",
"styles": {
"height": "44dp",
"margin":"16dp 0dp"
},
"items": [
{
"type": "Container",
"class": "bubble_Hint",
"items": [
{
"type": "Text",
"props": {
"text": "测试1:左图右文展示"
}
}
]
}
]
},
{
"type":"Container",
"styles": {
"width":"100%",
"flex-direction": "row",
"justify-content":"space-between"
},
"items":[
{
"type": "Image",
"componentId":"demo_image_id",
"styles": {
"width": "280dp",
"scale-type": "centerCrop",
"border-radius": "10dp"
},
"props": {
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince1.jpeg"
}
},
{
"type": "Container",
"class": "test-height",
"styles": {
"width": "560dp",
"background": "rgba(255,25,1,0.2)",
"padding":"10dp",
"border-radius":"16dp",
"justify-content":"space-between"
},
"items": [
{
"type":"Text",
"componentId": "demo_text_id_1",
"props":{
"text":"title 展示"
},
"styles": {
"color": "blue",
"font-size":"35dp"
}
},
{
"type":"Text",
"props":{
"text":"小标题"
},
"styles":{
"font-size":"25dp",
"height": "80dp"
}
},
{
"type":"Text",
"props":{
"text":"In one of the stars I shall be living. In one of them I shall be laughing. And so it will be as if all the stars were laughing, when you look at the sky at night… You – only you – will have stars that can laugh…"
},
"styles":{
"margin-top": "8dp",
"font-size":"30dp",
"max-lines": "3",
"text-overflow": "ellipsis",
"line-spacing": "8dp"
}
}
]
}
]
}
]
},
{
"type": "Container",
"styles": {
"background": "transparent",
"justify-content": "flex-start",
"align-items": "flex-start",
"margin-bottom": "30dp"
},
"items": [
{
"type": "Container",
"styles": {
"height": "44dp",
"margin":"16dp 0dp"
},
"items": [
{
"type": "Container",
"class": "bubble_Hint",
"items": [
{
"type": "Text",
"props": {
"text": "测试2:横向列表展示"
}
}
]
}
]
},
{
"type": "List",
"styles": {
"flex":"1",
"background":"transparent"
},
"props":{
"direction": "horizontal",
"data": [
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince1.jpeg",
"desc": "第一个"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince2.jpeg",
"desc": "第二个"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince3.jpeg",
"desc": "第三个"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince4.jpeg",
"desc": "第四个"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince5.jpeg",
"desc": "第五个"
}
]
},
"firstItem": [
{
"type": "Container",
"styles": {
"flex": "1",
"padding": "20dp",
"align-items":"center"
},
"items": [
{
"type":"Image",
"styles": {
"width":"160dp",
"height":"220dp",
"border-radius":"16dp",
"scale-type":"centerCrop"
},
"props":{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince8.jpeg"
}
},
{
"type": "Text",
"styles": {
"font-size": "30dp",
"margin-top": "16dp"
},
"props":{
"text": "最前一个"
}
}
]
}
],
"lastItem": [
{
"type": "Container",
"styles": {
"flex": "1",
"padding": "20dp",
"align-items":"center"
},
"items": [
{
"type":"Image",
"styles": {
"width":"360dp",
"height":"220dp",
"border-radius":"16dp",
"scale-type":"centerCrop"
},
"props":{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince1.jpeg"
}
},
{
"type": "Text",
"styles": {
"font-size": "30dp",
"margin-top": "16dp"
},
"props":{
"text": "最后一个"
}
}
]
}
],
"items": [
{
"type": "Container",
"styles": {
"flex": "1",
"padding": "20dp",
"align-items":"center"
},
"items": [
{
"type":"Image",
"styles": {
"width":"220dp",
"height":"220dp",
"border-radius":"16dp",
"scale-type":"centerCrop"
},
"props":{
"src": "${data.src}"
}
},
{
"type": "Text",
"styles": {
"font-size": "30dp",
"margin-top": "16dp"
},
"props":{
"text": "${data.desc}"
}
}
]
}
]
}
]
},
{
"type": "Container",
"styles": {
"background": "transparent",
"justify-content": "flex-start",
"align-items": "flex-start",
"margin-bottom": "30dp"
},
"items": [
{
"type": "Container",
"styles": {
"height": "44dp",
"margin":"16dp 0dp"
},
"items": [
{
"type": "Container",
"class": "bubble_Hint",
"items": [
{
"type": "Text",
"props": {
"text": "测试3:纵向列表展示"
}
}
]
}
]
},
{
"type": "List",
"styles": {
"background":"transparent",
"flex":"1",
"padding-bottom":"0dp"
},
"props":{
"direction": "vertical",
"data": [
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince1.jpeg",
"english": "Never frown, even when you are sad, because you never know who is falling in love with your smile.",
"chinese": "纵然伤心,也不要愁眉不展,因为你不知是谁会爱上你的笑容。"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince2.jpeg",
"english": "Dark clouds becomes heaven's flowers when kissed by light.",
"chinese": "黑云受到光的接吻时,就变成了天上的花朵。"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince3.jpeg",
"english": "The pet dog suspects the universe for scheming to take its place.",
"chinese": "小狗怀疑大宇宙阴谋篡夺它的位置。"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince4.jpeg",
"english": "The great walks with the small without fear. The middling keeps aloof.",
"chinese": "大的不怕与小的同游,居中的却远避之。"
},
{
"src": "https://duerstatic.cdn.bcebos.com/swan/dpl_demo/little_prince5.jpeg",
"english": "Not hammer-strokes, but dance of the water sings the pebbles into perfection.",
"chinese": "不是锤的敲打,乃是水的载歌载舞,使鹅卵石臻於完美。"
}
]
},
"items": [
{
"type": "Container",
"styles": {
"width":"85%",
"height":"160dp",
"flex-direction":"row",
"padding": "20dp",
"margin":"10dp",
"align-items":"center"
},
"items": [
{
"type":"Image",
"styles": {
"width":"120dp",
"height":"120dp",
"border-radius":"16dp",
"scale-type":"centerCrop"
},
"props":{
"src": "${data.src}"
}
},
{
"type": "Container",
"styles": {
"margin-left":"30dp",
"justify-content":"space-around"
},
"props":{
},
"items":[
{
"type": "Text",
"styles": {
"font-size": "26dp"
},
"props":{
"text": "${data.english}"
}
},
{
"type": "Text",
"styles": {
"font-size": "26dp"
},
"props":{
"text": "${data.chinese}"
}
}
]
}
]
}
]
}
]
}
],
"events": {
"onPageChanged": [
{
"type": "SendEvent",
"componentId":"demo_pager_1_pageChanged"
}
]
}
}
]
}
]
}
}
# x5兜底适配
目前,因为5寸屏(屏幕宽高比为2:1)设备存在的较多展现中内容被截断的问题,我们针对5寸屏设备下 dpl 模板展现通过以 默认 viewport.height = 562 的方式且内容水平居中的方式进行了兜底适配。
生效前提:
- 该设备被认为是5寸屏设备;
- 未主动设置 viewport 属性;
- 未主动设置 stylesheet 属性;
注意:对于需要设置后两者属性的应该考虑通过 class && mediaquery 的方式来实现适配
优点:以七寸屏设备作为参考,可以很好的保证完整内容的呈现与七寸屏保持一致; 缺点:基于562的高度设定,宽度会自动缩放到 2*562 = 1124 > 960(基于原本设计的宽度),会造成左右两边的留白区域,(开发者)无法直接利用到;
← 支持使用的颜色关键词 设计 →