荣耀开发者服务平台(HONOR Developers)是荣耀面向开发者的统一生态入口,通过聚合周边内外部系统,分全球多站点部署,为全球开发者提供业务全生命周期的商业支撑服务。
平台可为软硬件合作伙伴带来三大应用场景服务,包括主动服务的场景化体验智慧服务,智能协同的跨设备互联的智慧生态以及应用与游戏出海服务。同时,荣耀帐号服务、推送服务、运动健康等开放能力和业务也提供了多样化的合作选择。
当前荣耀智慧服务百亿级曝光扶持计划正火热进行中~
一、 接入流程
荣耀智慧服务为开发者提供一站式接入服务能力,和全场景、多终端、多入口的 AI 分发能力,为开发者提高业务推广效率,同时给用户提供便捷、贴心、智能的服务体验。
目前包含四种接入类型:快捷服务、快应用卡片、安卓应用卡片、内容接口卡片,呈现显示包括卡片和图标等,本文将提供快应用卡片(JS 卡片)接入相关指南。
二、快应用卡片适配开发指南
1. 卡片 ux 设计规范
1.1 卡片 UI 设计图
1.2 卡片布局相关技术
卡片可分为 title 区(标题区)、content 区(内容区)、footer 区(底部区)。
快应用卡片采用 flex 自适应布局技术,学习参考:
2. 卡片布局开发指导
注意:卡片布局采用 flex 布局(官方 IDE 默认 flex 布局);卡片不支持 position 定位,背景图标可使用 stack 标签,stack 标签支持子组件,子组件排列方式为层叠排列,每个直接子组件按照先后顺序依次堆叠,覆盖前一个子组件,从而达到背景图效果。
2.1 卡片高度调试适配规格
注意:在用调试器调试阶段,各卡片规格要确保适配以下不同状态下相应的尺寸规格(调试完成后要去掉卡片最外层宽高,因为负一屏、桌面会给出宽高)
(1)负一屏卡片尺寸(宽 x 高)
折叠屏折叠状态(相当于直板机):
152 x 152dp(卡片规格 2 x 2)
320 x 152dp(卡片规格 4 x 2)
320 x 336dp(卡片规格 4 x 4)
折叠屏展开状态竖屏:
148 x 148dp(卡片规格 2 x 2)
476 x 148dp(卡片规格 4 x 2)
476 x 311dp(卡片规格 4 x 4)
折叠屏展开状态横屏:
164 x 164dp(卡片规格 2 x 2)
529 x 164dp(卡片规格 4 x 2)
529 x 344dp(卡片规格 4 x 4)
(2) 桌面卡片尺寸(宽 x 高)
折叠屏折叠状态(相当于直板机):
129 x 176dp(卡片规格 2 x 2)
339 x 176dp(卡片规格 4 x 2)
339 x 410dp(卡片规格 4 x 4)
折叠屏展开状态竖屏:
173 x 158dp(卡片规格 2 x 2)
503 x 158dp(卡片规格 4 x 2)
503 x 354dp(卡片规格 4 x 4)
折叠屏展开状态横屏:
187 x 140dp(卡片规格 2 x 2)
565 x 140dp(卡片规格 4 x 2)
565 x 306dp(卡片规格 4 x 4)
2.2 卡片页面布局
注意:
最外层容器,由于 flex 从此容器开始,不要设置宽高,可以实现正确的卡片尺寸变化。
Flex 内部所有组件 使用 dp 或者百分比来设置宽高,不要使用 px(px,因为默认机制是跟随屏幕的像素尺寸缩放,会导致卡片会因为旋转屏幕后宽度不同进行缩放)。
文字尺寸(font-size)要使用 dp 单位,可以解决大字体大显示字体出现截断现象。
使用 dp 单位在 IDE 会提示语法错误,实际是支持 dp 单位的。为避免语法错误提示,卡片可以使用 less 语法。
2.2.1 卡片容器的结构布局(代码示例)
(1) HTML 部分
<template> <div class="card"> <stack class="stack"> <!-- 背景图图标布局,若无背景图需求则无需stack标签,直接来到<div class="layer"></div>结构布局 --> <div class="bg-img"></div> <!-- 卡片所有内容分布区(包含标题区,内容区和底部区) --> <div class="layer"> <!-- 标题区域 --> <div class="title"></div> <!-- 内容区域 --> <div class="content"></div> <!-- 底部区域 --> <div class="footer"></div> </div> </stack> </div></template>
复制代码
(2) JS 部分
<script>export default {}</script>
复制代码
(3) CSS 部分
<style>/* 卡片最外层 */.card { /* 最外层容器无需给宽高 */ padding: 12dp; border-radius: 16dp;/* 按照最新深色模式规范需要给卡片设置背景色,映衬规范需要#ffffff作为背景色; 若自定义背景色,要满足深色模式则需要通过媒体查询来实现,详见深色模式开发文档 */ background-color: #ffffff;}/* 卡片布局容器 设置百分百宽度,不要设置高度*/.stack { width: 100%;}
/* 卡片stack标签第二个元素,设置百分百宽高铺满父元素 */.layer { width: 100%; height: 100%; justify-content: space-between; flex-direction: column;}/* 背景图标容器设置100%宽高,使其与父元素等比例覆盖,它是stack标签堆叠的第一个元素,做成背景图效果 */.bg-img { width: 100%; height: 100%; flex-direction: column-reverse; align-items: flex-end;}/* 卡片标题区域 */.title { display: flex; height: 16dp; flex-direction: row;}/*/卡片内容区域 */.content { height: 60dp; flex-direction: column; justify-content: center;}/* 卡片底部区域 */.footer { height: 40dp; flex-direction: row; justify-content: space-between; align-items: flex-end;}</style>
复制代码
2.3 卡片 stack 标签的使用说明
stack 是快应用基本容器,子组件排列方式为层叠排列,每个直接子组件按照先后顺序依次堆叠,覆盖前一个子组件。
2.3.1 stack 标签在卡片容器的布局结构
布局结构解析
<template> <div class="card"> <stack class="stack"> <!-- 背景图图标布局 --> <div class="bg-img"> <!-- 此处背景图标要用image标签 --> <image class="icon" forcedark="false" src="../Common/res/img_pic.png"></image> </div> <!-- 卡片所有内容分布区(包含标题区,内容区和底部区) --> <div class="layer"> <!-- 标题区域 --> <div class="title"></div> <!-- 内容区域 --> <div class="content"></div> <!-- 底部区域 --> <div class="footer"></div> </div> </stack> </div></template>
复制代码
(1)卡片最外层容器 card,根据设计图卡片整体内容边距 12dp,最外层结构样式如下:
.card { padding: 12dp; border-radius: 16dp;/* 此处给宽高是为了让调试器devtools显示内容方便测试效果,实际开发需要去掉宽高 */ width: 160dp; height: 160dp; background-color: #ddd;}
复制代码
代码实现效果(颜色背景为 #ddd 的卡片)如图:
<template> <div class="card"> <stack class="stack"> <!-- 背景图图标布局 --> <div class="bg-img"> <!-- 此处背景图标要用image标签 --> <image class="icon" forcedark="false" src="../Common/res/img_pic.png"></image> </div> <!-- 卡片所有内容分布区(包含标题区,内容区和底部区) --> <div class="layer"> <!-- 标题区域 --> <div class="title"></div> <!-- 内容区域 --> <div class="content"></div> <!-- 底部区域 --> <div class="footer"></div> </div> </stack> </div></template>
复制代码
(1)卡片最外层容器 card,根据设计图卡片整体内容边距 12dp,最外层结构样式如下:
.card { padding: 12dp; border-radius: 16dp;/* 此处给宽高是为了让调试器devtools显示内容方便测试效果,实际开发需要去掉宽高 */ width: 160dp; height: 160dp; background-color: #ddd;}
复制代码
代码实现效果(颜色背景为 #ddd 的卡片)如图:
(2) stack 标签层,使其宽度设为 100%,让它铺满父元素 card,给个背景色值 #00ffff,样式:
.stack { width: 100%; background-color: #00ffff;}
复制代码
代码实现效果(由于 card 给了 12dp 边距,所以 stack 又来 12dp 边距)如图:
(3)背景图标布局 bg-img 是 stack 标签的第一个元素,设置 100%宽高,使其与父元素等比例覆盖,给个粉色色值 #ffc0cb 区分效果,样式如下:
.bg-img { width: 100%; height: 100%; background-color: #ffc0cb;}
复制代码
代码实现效果(设置 100%宽高把父元素的色值覆盖了)如图:
按照 flex 布局规范可以在背景图标区域按照设计规范进行排布图标,例如:
(1)将背景图标分布在右上角
样式:
.bg-img { width: 100%; height: 100%; background-color: #ffc0cb; flex-direction: row-reverse;}.icon { width: 40dp; height: 40dp; object-fit: contain;}
复制代码
效果如图:
(2)将背景图标分布在正中间
样式:
.bg-img { width: 100%; height: 100%; background-color: #ffc0cb; justify-content: center; align-items: center;}.icon { width: 40dp; height: 40dp; object-fit: contain;}
复制代码
代码实现效果如图:
(3)将背景图标分布在右下角
样式:
.bg-img { width: 100%; height: 100%; background-color: #ffc0cb; flex-direction: column-reverse; align-items: flex-end;}.icon { width: 40dp; height: 40dp; object-fit: contain;}
复制代码
代码实现效果如图:
(4)卡片整体内容布局区域 layer(包含标题区、内容区和底部区),它是 stack 标签第二个子元素,将来布局的内容会堆叠第一个子元素,从而使的第一个子元素变成背景的效果,宽高要设置 100%,使得铺满父元素达到适配。
示例代码:
(1) HTML 部分
<template> <div class="card"> <stack class="stack"> <!-- 背景图图标布局 --> <div class="bg-img"> <!-- 此处背景图标要用image标签 --> <image class="icon" forcedark="false" src="../Common/res/img_pic.png" ></image> </div> <!-- 卡片所有内容分布区(包含标题区,内容区和底部区) --> <div class="layer"> <!-- 标题区域 --> <div class="title"> <text class="title-text">{{ title }}</text> </div> <!-- 内容区域 --> <div class="content"> <text class="content-text">{{ content }}</text> </div> <!-- 底部区域 --> <div class="footer"> <text class="footer-text">{{ fooderName }}</text> </div> </div> </stack> </div></template>
复制代码
(2) CSS 部分
<style lang="less">.card { border-radius: 16dp; width: 152dp; height: 152dp; background-color: #ddd;}/* 基本容器,子组件排列方式为层叠排列,每个直接子组件按照先后顺序依次堆叠,覆盖前一个子组件 */.stack { width: 100%; background-color: #00ffff;}/* 背景图标容器设置100%宽高,使其与父元素等比例覆盖,它是stack标签堆叠的第一个元素,做成背景图效果 */.bg-img { width: 100%; height: 100%; background-color: #ffc0cb; flex-direction: column-reverse; align-items: flex-end;}.icon { width: 40dp; height: 40dp; object-fit: contain;}/* 卡片stack标签第二个元素,设置百分百宽高铺满父元素 */.layer { width: 100%; height: 100%; justify-content: space-between; flex-direction: column;}
/* 卡片标题区域 */.title { display: flex; height: 16dp; flex-direction: row; background-color: #9acd32;}.title-text { font-size: 12dp; color: rgba(0, 0, 0, 0.9);}
/*/卡片内容区域 */.content { height: 60dp; flex-direction: column; justify-content: center; background-color: #87ceeb;}.content-text { font-size: 14dp; color: rgba(0, 0, 0, 0.9); font-weight: 400; lines: 2; text-overflow: ellipsis;}
/* 卡片底部区域 */.footer { height: 40dp; flex-direction: row; justify-content: space-between; align-items: flex-end; border: 1dp solid #000000;}.footer-text { font-size: 10dp; color: rgba(0,0,0,0.6);}</style>
复制代码
(3) JS 部分
<script>export default { private: { title: '标题区', content: '内容区', fooderName: '底部区', },}</script>
复制代码
代码实现效果如图:
2.4 卡片 UI 设计完整代码示例
卡片常见问题:
卡片最外层圆角出现白边。解决方案是:去掉 manifest 文件里的 display 配置项。
卡片出现内容滑动现象。解决方案是:stack 不能设置高度 100%;只能设置宽度 100%。
深色模式下,图片出现暗色蒙层。解决方案是:在 image 标签里设置 forcedark="false"。
长按卡片字体变大。解决方案是:样式不能用 opacity 属性,用 rgba 设置字体透明度。
(1) HTML 部分
<template> <!-- 卡片最外层容器 --> <div class="card"> <!-- stack标签用于有需要插入背景图的卡片需求,若无背景图需求无需用stack标签 --> <stack class="stack"> <!-- 卡片stack标签第一个元素,设置百分百宽高,做成背景图效果 --> <div class="bg-img"> <!-- 此处背景图标要用image标签 --> <image forcedark="false" class="icon" src="../Common/res/img_pic.png" ></image> </div> <!-- 卡片stack标签第二个元素,卡片布局容器,设置百分百宽高铺满父元素,若无背景图需求,直接来到此处布局容器 --> <div class="layer"> <!-- 标题区域 --> <div class="title-wrap"> <div class="title-logo"> <image class="logo" forcedark="false" src="../Common/res/icon_icon.png"></image> </div> <text class="title-text">{{ title }}</text> </div> <!-- 内容区域 --> <div class="content"> <text class="content-title">内容区</text> <text class="content-text">{{ content }}</text> </div> <!-- 底部区域 --> <div class="footer"> <div class="footer-box"> <text class="footer-text">{{ fooderName }}</text> </div> </div> </div> </stack> </div></template>
复制代码
(2) CSS 部分
<style lang="less">/* 卡片最外层 最外层容器无需给宽高,由负一屏或桌面设定宽高 */.card { padding: 12dp; border-radius: 16dp; /* 此处给宽高是为了让调试器devtools显示内容方便测试效果,实际开发需要去掉宽高 */ height: 152dp; width: 152dp; /* 按照最新深色模式规范需要给卡片设置背景色,映衬规范需要#ffffff作为背景色; 若自定义背景色,要满足深色模式则需要通过媒体查询来实现,详见深色模式开发文档 */ background-color: #ffffff;}/* stack标签用于有需要插入背景图的卡片需求,若无背景图需求无需用stack标签*/.stack { width: 100%;}
/*卡片布局容器,设置百分百宽高铺满父元素,若无背景图需求,不需要stack标签结构直接来到此处布局容器*/.layer { width: 100%; height: 100%; justify-content: space-between; flex-direction: column;}
/* 卡片标题区域 */.title-wrap { flex-direction: row;}.title-logo { width: 16dp; height: 16dp; justify-content: center; align-items: center; flex-shrink: 0;}.logo { width: 100%; height: 100%; object-fit: contain; border-radius: 50%;}.title-text { font-size: 12dp; color: rgba(0,0,0,0.9); margin-left: 8dp;}
/*/卡片内容区域 */.content { flex: 1; flex-direction: column; justify-content: center;}.content-title { font-size: 16dp; color: rgba(0,0,0,0.9); font-weight: 500;}.content-text { font-size: 14dp; color: rgba(0,0,0,0.6); font-weight: 400; /* 注意:卡片内容区域给定高度,内容展示要注意字数限制内容过长采用省略方式,避免导致内容缺失问题 */ lines: 2; text-overflow: ellipsis;}/* 卡片底部区域 */.footer { height: 40dp; flex-direction: row; justify-content: space-between; align-items: flex-end;}.footer-box { height: 16dp; flex-direction: row;}.footer-text { font-size: 10dp; color: rgba(0,0,0,0.6);}/* 背景图标 */.bg-img { width: 100%; height: 100%; flex-direction: column-reverse; align-items: flex-end;}.icon { width: 40dp; height: 40dp; object-fit: contain;}</style>
复制代码
(3) JS 部分
<script>export default { private: { title: '标题(dp版本08)', content: '离开[北京航站],下一站[北京新顺处理中转站]', fooderName: '来自顺丰速运', },}</script>
复制代码
2.5 卡片完整代码实现效果
2.5.1 竖屏显示效果
2.5.2、横屏显示效果
3. 深色模式指导适配
深色模式实现有两种方案,一种是随系统变化,引擎对背景色,字体颜色等元素做了映衬关系,只需按照映衬设计规范对 css 进行配置日间的色值,切换夜间就会映衬的夜间的色值从而实现深色模式效果;另一种方案可以通过媒体查询接口进行自定义背景颜色,字体颜色;两种方案可以一起用,媒体查询优先级比映衬方式高。
3.1 深色模式跟随系统变化
3.1.1 深色模式 UX 规范
引擎对卡片背景色,文本颜色,标签以及按钮等元素做了日、夜间颜色映衬关系(日间模式色值对应夜间模式色值,如 #000000 对应 #ffffff,详见下面表格);卡片开发按照此映衬规范给样式进行设置日间模式色值,在切换到夜间模式时就会自动改变成夜间模式色值。
卡片开发要按照日间模式的元素颜色来设计,如下图:
按照日间模式色值设置,切换到夜间模式时,效果转换为夜间模式色值,如图下:
3.1.2 卡片 demo 示例
(1) Html 部分
<div> <div class="color1"> <text>#3F56EA(日间)</text> </div> <text style="color:#000000;">=> </text> <div class="color1-dark"> <text>#3F56EA(夜间)</text> </div> </div> <div> <div class="color3"> <text>#00BFC9(日间)</text> </div> <text style="color:#000000;">=> </text> <div class="color3-dark"> <text>#00777E(夜间)</text> </div> </div> <div> <div class="color6"> <text>#8A2BE2(日间)</text> </div> <text style="color:#000000;">=> </text> <div class="color6-dark"> <text>#6044AB(夜间)</text> </div> </div> <div> <div class="color8"> <text>#FA2A2D(日间)</text> </div> <text style="color:#000000;">=> </text> <div class="color8-dark"> <text>#E64548(夜间)</text> </div> </div> <div> <div class="color12"> <text>#808080(日间)</text> </div> <text style="color:#000000;">=> </text> <div class="color12-dark"> <text>#4D4D4D(夜间)</text> </div> </div> </div> <!-- 底部区域 --> <div class="footer"> <div class="footer-box"> <div class="bg-div"> <text class="footer-btn1">#256FFF</text> <text class="footer-btn2">#3F97E9</text> </div> <div class="bg-div"> <text class="footer-btn3">#41BA41</text> <text class="footer-btn4">#007900</text> </div> <div class="bg-div"> <text class="footer-btn5">#FF7500</text> <text class="footer-btn6">#BA5500</text> </div> </div> </div></div></div></template>
复制代码
(2) Css 部分
<style lang="less">/* 卡片最外层 最外层容器无需给宽高,由负一屏或桌面设定宽高 */.card { padding: 12dp; border-radius: 16dp; /* 最外层要给卡片背景色 */ background-color: #ffffff;}
.layer { width: 100%; height: 100%; justify-content: space-between; flex-direction: column;}
/* 卡片标题区域 */.title { display: flex; height: 16dp; flex-direction: row;}.logo { width: 16dp; height: 16dp; border-radius: 50%; margin-right: 8dp;}.title-text { font-size: 12dp; color: rgba(0, 0, 0, 0.9);}
/*/卡片内容区域 */.content { flex-direction: column; justify-content: center;}.content-title { font-size: 16dp; color: rgba(0, 0, 0, 0.9); font-weight: 500;}
/* 按照色值映衬规范给文本颜色设置日间模式色值 */.color-text1 { font-size: 14dp; color: rgba(0, 0, 0, 0.9); font-weight: 400; /* 注意:卡片内容区域给定高度,内容展示要注意字数限制内容过长采用省略方式,避免导致内容缺失问题 */ lines: 2; text-overflow: ellipsis;}.color-text2 { font-size: 14dp; color: rgba(0, 0, 0, 0.6); font-weight: 400;}.color-text3 { font-size: 14dp; color: rgba(0, 0, 0, 0.38); font-weight: 400;}/* 按照色值映衬规范给标签背景色设置日间模式色值 */.color1 { background-color: #3f56ea; text { color: #000000; }}/* dark部分色值是测试日间转换到夜间颜色是否一致的验证,卡片正式开发无需填写夜间模式色值 */.color1-dark { background-color: #3f56ea; text { color: #000000; }}
.color3 { background-color: #00bfc9; text { color: #000000; }}.color3-dark { background-color: #00777e; text{ color: #000000; }}
.color6 { background-color: #8a2be2; text { color: #000000; }}.color6-dark { background-color: #6044ab; text { color: #000000; }}
.color8 { background-color: #fa2a2d; text { color: #000000; }}.color8-dark { background-color: #e64548; text { color: #000000; }}
.color12 { background-color: #808080; text { color: #000000; }}.color12-dark { background-color: #4d4d4d; text { color: #000000; }}/* 卡片底部区域 */.footer { flex-direction: row;}.footer-box { flex-direction: row; justify-content: space-between;}.bg-div { flex-direction: column; width: 100%;}.footer-btn1 { width: 80dp; height: 40dp; border-radius: 5dp; background-color: #256fff; text-align: center; color: rgba(0, 0, 0, 0.9);}.footer-btn2 { width: 80dp; height: 40dp; border-radius: 5dp; background-color: #006cde; text-align: center; color: rgba(0, 0, 0, 0.9);}.footer-btn3 { width: 80dp; height: 40dp; border-radius: 5dp; background-color: #41ba41; text-align: center; color: rgba(0, 0, 0, 0.9);}.footer-btn4 { width: 80dp; height: 40dp; border-radius: 5dp; background-color: #007900; text-align: center; color: rgba(0, 0, 0, 0.9);}.footer-btn5 { width: 80dp; height: 40dp; border-radius: 5dp; background-color: #ff7500; text-align: center; color: rgba(0, 0, 0, 0.9);}.footer-btn6 { width: 80dp; height: 40dp; border-radius: 5dp; background-color: #ba5500; text-align: center; color: rgba(0, 0, 0, 0.9);}</style>3、Js部分<script>export default { private: { title: '标题(色值#000000,90%不透明度)' },}</script>
复制代码
(3) Js 部分
<script>export default { private: { title: '标题(色值#000000,90%不透明度)' },}</script>
复制代码
3.2 媒体查询功能实现深色模式
荣耀卡片实现了跟随系统切换深色模式的时候媒体查询,只需要如下配置,便可以让卡片 CP 可以自主适配深色模式的显示样式,媒体查询的显示效果优先级高于自动映射。
@media (prefers-color-scheme: dark) { .layer{ background-color: #666666; } }
3.2.1 卡片 demo 示例
(1) Html 部分
<template> <div class="card"> <div class="layout"> <div class="title"> <div class="logo"> <!-- 解决logo图标在大字体大显示出现的截断问题即image标签里使用src引入图片 --> <image forcedark="false" src="../Common/logo.png" class="logo-img" ></image> </div> <text class="title-txt">{{ title }}</text> </div> <div class="content"> <div class="content-bg"> <text style="color:#000000;">内容</text> </div> </div> <div class="footer"> <div class="btn"> <text style="color:#000000;">按钮</text> </div> </div> </div> </div></template>
复制代码
(2) Css 部分
<style lang="less">/* 例如日间常规卡片背景色为黄色 #ffff00*/.card { border-radius: 16dp; padding: 12dp; background-color: #ffff00;}
/* 使用媒体查询,切换深色模式,卡片背景色变成红色,当切换回日间模式时,卡片背景色又变成常规设置的黄色背景色 */@media (prefers-color-scheme: dark) { .card { background-color: #ff0000; }}
.layout { width: 100%; height: 100%; flex-direction: column;}.title { height: 16dp;}
.logo { height: 16dp; width: 16dp; border-radius: 50%;}
/* 解决logo图标在大字体大显示出现的截断问题 */.logo-img { width: 100%; height: 100%; /* object-fit: contain保持宽高比,缩小或者放大,使得图片完全显示在显示边界内,居中显示 */ object-fit: contain;}
.content { height: 100dp;}/* 标题文本颜色可以按照ux映衬色值规范进行设置 */.title-txt { font-size: 12dp; color: rgba(0, 0, 0, 0.9);}
.footer { height: 40dp;}/* 常规日间给按钮自定义背景色为蓝色#0000ff */.btn { width: 80dp; height: 30dp; background-color: #0000ff;}/* 使用媒体查询,夜间模式下,更换按钮背景色为红色#ff0000 */@media (prefers-color-scheme: dark) { .btn { background-color: #ff0000; }}</style>
复制代码
(3) Js 部分
<script>export default { private: { title: '标题' },}</script>
复制代码
评论