系统运维

HarmonyOS JS卡片之“星座运势”卡片开发

时间:2010-12-5 17:23:32  作者:人工智能   来源:IT科技类资讯  查看:  评论:0
内容摘要:想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com前言本人是JS攻城狮,java属于初学状态,写的不好的地方还请多多指教!为什么决定开发一个

想了解更多内容,星座运势请访问:

和华为官方合作共建的卡卡片开鸿蒙技术社区

https://harmonyos.51cto.com

前言

本人是JS攻城狮,java属于初学状态,星座运势写的卡卡片开不好的地方还请多多指教!

为什么决定开发一个星座运势服务卡片?

主要有以下几点:

老年人和女性都比较关心运势,卡片类型刚好能够清晰展示运势,星座运势同时也不需要太多操作,卡卡片开与服务卡片理念契合(弱交互、星座运势强服务)。卡卡片开 聚合api上刚好有相应接口,星座运势可以直接调用,卡卡片开比较方便。星座运势

实现效果

实现了三个卡片(2X2、卡卡片开2X4、星座运势4X4)和一个内容页,卡卡片开基于api6开发(API 6目前只支持运行在Phone设备的星座运势模拟器上,其它设备暂不支持运行),如何使用API 6点击查看?

卡片使用原子化布局实现,根据卡片规格自适应。

内容页可查询关注的星座,调用接口来获取运势。

创建项目

搭建环境,下载开发工具并安装。下载和安装官方文档

打开安装好的DevEco Studio软件,创建项目。官方文档

填写创建的工程信息 官方文档

Project Type:工程的类型。服务器租用 Service:原子化服务。原子化服务调试、运行时,在设备桌面上没有应用图标、免安装的。 Application:传统方式需要安装的应用。 Compatible API Version:兼容的SDK最低版本。 Show in Service Center:是否在服务中心露出。如果Project Type为Service,则会同步创建一个2*2的服务卡片模板。 创建好的模板,我们主要会用到以下目录:

卡片JSUI部分

hml部分

布局

代码

<div class="normal_container" > <!--    2X2 2X4 布局-->     <div class="container_top" @click="clickToApp" > <!--    2X2 布局-->         <div class="top_left">             <div class="left_item">                 <text class="left_item_text conName">                     { {  conName }}                 </text>             </div>             <div class="left_item">                 <text class="left_item_text conDate">                     { {  conDate }}                 </text>             </div>             <div class="conAll left_item">                 <div class="s_score">                     <text class="left_item_text label_2X2">                         综合                     </text>                     <image class="s_star_2X2" for="{ {  conAllStarY }}" src="/common/starY.png"></image>                     <image class="s_star" for="{ {  conAllStarN }}" src="/common/starN.png"></image>                 </div>             </div>             <div class="conPari left_item">                 <text class="left_item_text" >                     速配星座                 </text>                 <text class="left_item_text conPari_text">                     { {  conPari }}                 </text>             </div>         </div> <!--    2X4 布局-->         <div class="top_right">             <image src="{ {  imgSrc }}" class="con_image" ></image>         </div>     </div> <!--    4X4 布局半部分-->     <div class="container_bottom" @click="clickToApp" >         <div class="list_item item_line_top" >             <div class="s_score">                 <text class="label">                     爱情                 </text>                 <image class="s_star" for="{ {  conLoveStarY }}" src="/common/starY.png"></image>                 <image class="s_star" for="{ {  conLoveStarN }}" src="/common/starN.png"></image>             </div>             <div class="s_score" style="margin-left: 40px;" >                 <text class="label">                     理财                 </text>                 <image class="s_star" for="{ {  conMoneyStarY }}" src="/common/starY.png"></image>                 <image class="s_star" for="{ {  conMoneyStarN }}" src="/common/starN.png"></image>             </div>         </div>         <div class="list_item">             <div class="s_score">                 <text class="label">                     工作                 </text>                 <image class="s_star" for="{ {  conWorkStarY }}" src="/common/starY.png"></image>                 <image class="s_star" for="{ {  conWorkStarN }}" src="/common/starN.png"></image>             </div>             <div class="s_score" style="margin-left: 40px;" >                 <text class="label">                     健康                 </text>                 <image class="s_star" for="{ {  conHealthStarY }}" src="/common/starY.png"></image>                 <image class="s_star" for="{ {  conHealthStarN }}" src="/common/starN.png"></image>             </div>         </div>         <div class="item_line_bottom" >             <div class="s_score">                 <text class="label">                     幸运数字                 </text>                 <text class="score_text">                     { {  conNumber }}                 </text>             </div>             <div class="s_score" style="margin-left: 78px;" >                 <text class="label">                     幸运颜色                 </text>                 <text class="score_text">                     { {  conColor }}                 </text>             </div>         </div>         <div class="list_item_more" >             <div class="list_item_box1">                 <text class="item_title_text">                     综合概述                 </text>             </div>             <div class="list_item_box2">                 <text class="item_sub_text">                     { {  conSummary }}                 </text>             </div>         </div>     </div> </div> 

开发过程的问题

hml文本文字必须写在text标签中 <text>文字</text>  hml 动态数据不可以一下 写两个 <text >// 只会渲染第一个     { {  conName }} { {  conData }}  </text> <text > // 不支持,直接当文本处理     { {  conName + conDate }} </text>  hml文件中的{ { }},动态数据不支持表达式,比如 5 - 1; <div if="{ {  flag - 1}}"> <div if="{ {  !flag}}">  list list-item 标签中无法触发点击事件 <list @click="handle"> // 无法触发     <list-item> </list> 

css部分

代码部分

.normal_container {      width: 100%;     height: 100%;     display: flex;     flex-wrap: wrap;     background: linear-gradient(to right, #6a11cb 0%, #667eea 100%); } .container_top{      display: flex; } /*2X2 布局样式 */ .top_left{      width: 165px;     height: 150px;     display-index: 3;     display: flex;     flex-direction: column;     padding: 12px 10px; } .left_item{      margin-top: 8px; } .left_item_text{      font-size: 16px;     color: #ffffff; } .conDate{      font-size: 14px; } .conPari_text{      font-size: 18px;     margin-left: 6px; } .s_star_2X2{      width: 16px;     height: 16px;     margin-left: 2px; } .label_2X2{      margin-right: 8px;     font-size: 16px;     color: #fff; } /*2X4 布局样式右 */ .top_right{      width: 150px;     height: 150px;     display-index: 2;     display: flex;     align-items: center;     justify-content: center; } .con_image{      width: 120px;     height: 120px;     border-radius: 70px;     border: 4px solid #fdfbfb; } /*4X4 布局样式下 */ .container_bottom{      width: 100%;     display-index: 1;     padding: 0px 10px;     display: flex;     flex-direction: column; } .list_item{      margin-bottom: 6px; } .list_item_more{      display: flex;     flex-direction: column; } .list_item_box2{      width: 100%;     height: 80px;     margin-top: -5px; } .item_title_text{      font-size: 18px;     color: #fff;     padding: 8px 0 0px; } .item_sub_text{      font-size: 14px;     color: #fff; /*配套使用*/     text-overflow: ellipsis;     max-lines: 3; /*配套使用*/     line-height: 22px; } .item_line_bottom{      border-bottom: 1px solid #eee;     padding-bottom: 8px; } .item_line_top{      border-top: 1px solid #eee;     padding-top: 8px; } /* 通用样式 */ /* 评分星 */ .s_score{      display: flex;     align-items: center; } .s_star{      width: 14px;     height: 14px;     margin-left: 2px; } .label{      margin-right: 8px;     font-size: 14px;     color: #fff; } .score_text{      font-size: 14px;     color: #fff;     margin-left: 6px; } 

遇到的问题

css boder-raduis 不支持百分比 css 不支持 嵌套 .divClass .text{ } // 不支持  css font-size color 不支持继承,font-size color等文本必须写在text标签内,写在父级就不会相应 css 不支持大部分伪类选择器(:nth-child(n)、:before、:after)

json部分

{    "data": {      "imgSrc": "/common/constellation/天蝎.jpg",     "conName": "天蝎座",     "conDate": "2021年07月27日",     "conPari": "金牛座",     "conNumber": 1,     "conColor": "古铜色",     "conSummary": "有些思考的小漩涡,可能让你忽然的放空,生活中许多的细节让你感触良多,亿华云五味杂陈,常常有时候就慢动作定格,想法在某处冻结停留,陷入一阵自我对话的沉思之中,这个时候你不喜欢被打扰或询问,也不想让某些想法曝光,个性变得有些隐晦。",     "conAllStarY": [],     "conAllStarN": [],     "conLoveStarY": [],     "conLoveStarN": [],     "conMoneyStarY": [],     "conMoneyStarN": [],     "conWorkStarY": [],     "conWorkStarN": [],     "conHealthStarY": [],     "conHealthStarN": []   },   "actions": {      "clickToApp": { // 跳转事件,跳转到相应内容页       "action": "router",       "abilityName": "com.example.fortune.MainAbility",       "params": {          "message": ""// 点击传递数据       }     }   } } 

遇到的问题

json中定义数组,如 “conAllStarY”: [“Y”, “Y”], 在java中动态修改它为[“Y”, “Y”, “Y”, “Y”],则实际渲染出来有问题。打印出来的数组正确,for循环出来的数组只有两位。最后将初始数组改为空数组才解决了这个bug。 <text>{ {  conWorkStarY }}</text> <text for="{ { conWorkStarY}}" >a</text> 

结果:

[“Y”, “Y”, “Y”, “Y”]aa

java代码逻辑

公共类

public class UpdataJSData {      private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, UpdataJSData.class.getName());     // 数据请求     public static void getJsonData(String constellation, ZZRCallBack.CallBackString callBackName ) {          String url = "http://web.juhe.cn:8080/constellation/getAll";         Map<String,String> map = new HashMap<>();         map.put("key", "9d075905a3e1c33224ac5bb42f4de458");         map.put("consName", constellation);         map.put("type", "today");         ZZRHttp.get(url, map, callBackName);     }     // 将请求到的数据更新到fortuneData中,并返回回去     public static ZSONObject setJson(String response) {          ZSONObject fortuneData = ZSONObject.stringToZSON(response);         int error_code = fortuneData.getIntValue("error_code");         if (error_code == 0) {              HiLog.info(TAG,"返回的数据正确,设置js中的json数据");             String[][] all = formatConversion(fortuneData.getString("all"));             String[][] love = formatConversion(fortuneData.getString("love"));             String[][] money = formatConversion(fortuneData.getString("money"));             String[][] work = formatConversion(fortuneData.getString("work"));             String[][] health = formatConversion(fortuneData.getString("health"));             HiLog.info(TAG,health.toString());             fortuneData.put("imgSrc", "/common/constellation/" + fortuneData.getString("name").toString().substring(0, 2) + ".jpg");             fortuneData.put("conName", fortuneData.getString("name"));// 星座名称             fortuneData.put("imgSrc", "/common/constellation/" + fortuneData.getString("name").toString().substring(0, 2) + ".jpg");// 星座图片路径拼接             fortuneData.put("conName", fortuneData.getString("name"));// 星座名称             fortuneData.put("conDate", fortuneData.getString("datetime"));// 当前事件             fortuneData.put("conPari", fortuneData.getString("QFriend"));// 速配星座             fortuneData.put("conNumber", fortuneData.getString("number"));// 幸运数组             fortuneData.put("conColor", fortuneData.getString("color"));// 幸运颜色             fortuneData.put("conSummary", fortuneData.getString("summary"));// 描述信息             fortuneData.put("conAllStarY", all[0]);// 综合评分 标记星             fortuneData.put("conAllStarN", all[1]);// 综合评分 未标记星             fortuneData.put("conLoveStarY", love[0]);// 爱情评分 标记星             fortuneData.put("conLoveStarN", love[1]);// 爱情评分 未标记星             fortuneData.put("conMoneyStarY", money[0]);// 理财评分 标记星             fortuneData.put("conMoneyStarN", money[1]);// 理财评分 未标记星             fortuneData.put("conWorkStarY", work[0]);// 工作评分 标记星             fortuneData.put("conWorkStarN", work[1]);// 工作评分 未标记星             fortuneData.put("conHealthStarY", health[0]);// 健康评分 标记星             fortuneData.put("conHealthStarN", health[1]);// 健康评分 未标记星         } else {              HiLog.info(TAG,"请求出错,code=" + error_code);         }         return fortuneData;     }     // 对分数数据进行封装,转换为二维数组     private static String[][] formatConversion(String star) {          int myData = Integer.parseInt(star);         int myDataY = myData / 20;         int myDataN = 5 - myDataY;         HiLog.info(TAG,"star=" + star + "myDataY=" + myDataY + "      myDataN=" + myDataN);         String myListY[] = new String[myDataY];         String myListN[] = new String[myDataN];         for(int i = 0; i < myDataY; i++) {              myListY[i] = "Y";         }         for(int i = 0; i < myDataN; i++) {              myListN[i] = "N";         }         String[][] myList = { myListY, myListN};         return myList;     } } 

数据初始化

创建卡片时,调用MainAbility中onCreateForm方法 实现代码 protected ProviderFormInfo onCreateForm(Intent intent) {          HiLog.info(TAG, "更新数据:onCreateForm");         ProviderFormInfo providerFormInfo = new ProviderFormInfo();         long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);         String formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);         int dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);         HiLog.info(TAG, "onCreateForm: formId=" + formId + ",formName=" + formName);         FormControllerManager formControllerManager = FormControllerManager.getInstance(this);         FormController formController = formControllerManager.getController(formId);         formController = (formController == null) ? formControllerManager.createFormController(formId,                 formName, dimension) : formController;         if (formController == null) {              HiLog.error(TAG, "Get null controller. formId: " + formId + ", formName: " + formName);             return null;         }         // 调用公共类中获取数据,传入一个callback方法         UpdataJSData.getJsonData("处女座", new ZZRCallBack.CallBackString() {              public void onFailure(int code, String errorMessage) {                  //http访问出错了,此部分内容在主线程中工作;                 //可以更新UI等操作,请不要执行阻塞操作。                 HiLog.info(TAG,"更新数据:数据请求失败"+code+","+errorMessage);             }             public void onResponse(String response) {                  //http访问成功,此部分内容在主线程中工作;                 //可以更新UI等操作,但请不要执行阻塞操作。                 HiLog.info(TAG,"更新数据:数据请求成功");                 ZSONObject fortuneData = setJson(response);                 try {                      HiLog.info(TAG,"更新数据");                     updateForm(formId, new FormBindingData(fortuneData));                 } catch (FormException e) {                      HiLog.info(TAG,"更新数据失败");                 }             }         });         return providerFormInfo; } 

采用定时刷新,源码库星座运势不需要周期性刷新

config.js 中设置定时刷新的时间 "forms": [     {      "scheduledUpdateTime": "10:12", // 定时刷新时间点     "updateEnabled": true, // 是否周期性刷新     "updateDuration": 0,     ...     } ]  定时刷新会触发widget->WidgetImpl文件的updateFormData方法 public void updateFormData(long formId, Object... vars) {       HiLog.info(TAG, "更新数据");      UpdataJSData.getJsonData("双鱼座", new ZZRCallBack.CallBackString() {           public void onFailure(int code, String errorMessage) {               //http访问出错了,此部分内容在主线程中工作;              //可以更新UI等操作,请不要执行阻塞操作。              HiLog.info(TAG,"数据请求失败"+code+","+errorMessage);          }          public void onResponse(String response) {               //http访问成功,此部分内容在主线程中工作;              //可以更新UI等操作,但请不要执行阻塞操作。              HiLog.info(TAG,"数据请求成功");              ZSONObject fortuneData = setJson(response);              try {                   HiLog.info(TAG,"更新数据");                  ((MainAbility)context).updateForm(formId, new FormBindingData(fortuneData)); //调用MainAbility的方法updateForm(),并将formBindingData作为第二个实参              } catch (FormException e) {                   HiLog.info(TAG,"更新数据失败");              }          }      });  } 

内容页部分

内容页布局比4X4的卡片多了个输入框,可进行星座搜索 内容页布局和css同卡片比较相似,这边就贴一下js代码 import http from @ohos.net.http;// 导入http export default {      data: {          conName: "天蝎座",         options: {              key: "9d075905a3e1c33224ac5bb42f4de458",             type: "today"         },         url: "",         conData: {              name: "天蝎座",             datetime: "2021年7月28号",             img: "/common/images/constellation/天蝎.jpg",             QFriend: "金牛",             number: "4",             color: "粉色",             summary: "有些思考的小漩涡,可能让你忽然的放空,生活中许多的细节让你感触良多,五味杂陈,常常有时候就慢动作定格,想法在某处冻结停留,陷入一阵自我对话的沉思之中,这个时候你不喜欢被打扰或询问,也不想让某些想法曝光,个性变得有些隐晦。"         },         responseData: { }     },     onInit() {          this.getHttp();// 发送请求     }, //    输入框改变触发     changeCon(v) {          this.conName = v.value;         console.log(v.value+ change conName);     },     getHttp() {          this.url = `http://web.juhe.cn:8080/constellation/getAll?key=${ this.options.key}&consName=${ this.conName}&type=${ this.options.type}`         let httpRequest = http.createHttp();         httpRequest.request(this.url, {            method: GET         },(err, data) => {            if (err == null) {              let conData = JSON.parse(data.result);             console.log(Result: + data.result);             if (conData.error_code == 0) {                  conData.img = `/common/images/constellation/${ (conData.name).slice(0, 2)}.jpg`                 conData.allY = this.getNewArr(conData.all, "Y");                 conData.allN = this.getNewArr(conData.all, "N");                 conData.healthY = this.getNewArr(conData.health, "Y");                 conData.healthN = this.getNewArr(conData.health, "N");                 conData.loveY = this.getNewArr(conData.love, "Y");                 conData.loveN = this.getNewArr(conData.love, "N");                 conData.moneyY = this.getNewArr(conData.money, "Y");                 conData.moneyN = this.getNewArr(conData.money, "N");                 conData.workY = this.getNewArr(conData.work, "Y");                 conData.workN = this.getNewArr(conData.work, "N");                 this.conData = conData;             } else {                  console.error("请求失败");             }           } else {              console.log(error: + JSON.stringify(err));           }         });     }, //    数字转化为数组不然for循环不出来     getNewArr(score, type){          score = parseInt(parseInt(score) / 20);         let arr = [];         if (type === "N") {              console.log(type + type)             score = 5 - score;             for (var i = 0; i < score; i++) {                  arr.push(type);             }         } else {              for (var i = 0; i < score; i++) {                  arr.push(type);             }         }         return arr;     } }  需要注意hml中for循环时,最好绑定tid,不然会复用。 搜索框的value不是双向绑定的,这边需要监听个change事件,来改变value。 js部分数据请求时,采用api6,需要自己更改配置设置为兼容api6 官方文档

总结

JSUI部分,主要是一些布局和样式类,是无法进行数据处理的。做一些弱交互的卡片是非常棒的。 Java部分主要也就是用到了三个函数。onStart:主要做一些js方事件处理。onCreateForm:创建卡片的时候需要。updateFormData:定时刷新和周期性刷新会走到这里 卡片开发目前来说bug还是挺多,限制也挺多的,期待做的越来越好。

源码地址

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap