# 设备屏幕适配

# 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 的方式且内容水平居中的方式进行了兜底适配。

生效前提:

  1. 该设备被认为是5寸屏设备;
  2. 未主动设置 viewport 属性;
  3. 未主动设置 stylesheet 属性;

注意:对于需要设置后两者属性的应该考虑通过 class && mediaquery 的方式来实现适配

优点:以七寸屏设备作为参考,可以很好的保证完整内容的呈现与七寸屏保持一致; 缺点:基于562的高度设定,宽度会自动缩放到 2*562 = 1124 > 960(基于原本设计的宽度),会造成左右两边的留白区域,(开发者)无法直接利用到;