一个简单的日程提醒鸿蒙卡片开发!

奋斗的疯子 2021-08-04 13:46:28 5657

效果图展示:

项目介绍

项目为一个简单的在日历上添加日程的应用,我们可以将当日的日程生成卡片到桌面,便于直观查看当日要做事项。

此项目旨在帮助开发者快速掌握如下技术点:

Js 卡片的布局、初始化、更新、事件处理。

Java 卡片的布局、初始化、更新、事件处理。

代码结构解读

本教程我们只是对核心代码进行讲解,您可以在最后的参考中下载完整代码,首先来介绍下整个工程的代码结构:

项目介绍

项目为一个简单的在日历上添加日程的应用,我们可以将当日的日程生成卡片到桌面,便于直观查看当日要做事项。

此项目旨在帮助开发者快速掌握如下技术点:

Js 卡片的布局、初始化、更新、事件处理。

Java 卡片的布局、初始化、更新、事件处理。

代码结构解读

本教程我们只是对核心代码进行讲解,您可以在最后的参考中下载完整代码,首先来介绍下整个工程的代码结构:

选择模板→下一步:

输入卡片名称、选择卡片类型(单选)、卡片大小(多选),点击 finish 即可。

②默认卡片页面

js-widget-pages-index-index.json 默认卡片页面的数据:

data:默认数据。

actions:routerEvent 为 router 事件,用于应用跳转

js-widget-pages-index-index.css 卡片的样式:同 js 页面样式开发。

js-widget-pages-index-index.html 卡片的页面:

同 js 页面开发,不过要使用卡片支持组件。

click 事件关联 json 文件中的 actions 下的应用跳转事件,此处关联的是点击跳转应用的页面,页面代码:on:click=“routerEvent”(不可以传参)。

③初始化卡片页面

在 WidgetImpl.java 文件中 bindFromData 方法中,进行页面展示数据的初始化:
public ProviderFormInfo bindFormData() {
ZSONObject zsonObject = new ZSONObject();
ProviderFormInfo providerFormInfo = new ProviderFormInfo();
String scheduleData = StorageUtil.initPreferences(context).getSchedule();
if(!"".equals(scheduleData)) {
ZSONArray array = ZSONArray.stringToZSONArray(scheduleData);
if(array.size()>0) {
ZSONArray result = StorageUtil.getSwiperCardSchedule(array);
CardConstant.SWIPER_CARD_LENGTH = result.size();
zsonObject.put("schedule", result);
zsonObject.put("count", array.size());
}
}
zsonObject.put("index", 0);
providerFormInfo.setJsBindingData(new FormBindingData(zsonObject));
return providerFormInfo;
}

④更新卡片页面

config.json 配置定时或周期性刷新:定时或周期性刷新均会调用 WidgetImpl.java 文件中 updateFormData 方法,因本卡片未实现此方法,所以不支持此功能。

在下面 js2x2 与 2x4 卡片中介绍周期性刷新;在下面 java2x2 与 2x4 卡片中介绍定时刷新。

添加当日日程导致数据变化 ,对日程进行更新介绍:数据变化时,触发数据监听方法,代码在 StorageUtil.java 工具类,这里开启 CardServiceAbility 服务。

代码如下:

private class PreferencesChangeCounter implements Preferences.PreferencesObserver {
private Context mContext;
public PreferencesChangeCounter(Context context){
this.mContext = context;
}
@Override
public void onChange(Preferences preferences, String key) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("com.example.myohoscard")
.withAbilityName("com.example.myohoscard.CardServiceAbility")
.build();
intent.setOperation(operation);
mContext.startAbility(intent,0);
}
}

CardServiceAbility 服务的 onCommand 方法中进行卡片更新,其更新代码如下:

public void swiperData(ZSONArray array){
ZSONArray result = StorageUtil.getSwiperCardSchedule(array);

   CardConstant.SWIPER_CARD_LENGTH = result.size();

   ZSONObject zsonObject = new ZSONObject();
   zsonObject.put("schedule", result);
   zsonObject.put("count", array.size());

   FormBindingData formBindingData = new FormBindingData(zsonObject);
   FormControllerManager formControllerManager = FormControllerManager.getInstance(this);

   for(long id:formControllerManager.getAllFormIdFromSharePreference(CardConstant.SWIPER_CARD_FORMS_NAME)) {
       try {
           updateForm(id, formBindingData);
       } catch (FormException e) {
           e.printStackTrace();
       }
   }

}

⑤卡片的轮播

CardServiceAbility 服务的 onCommand 方法中调用卡片轮播,其代码如下:

public void swiperLoop(){
ZSONObject data = new ZSONObject();
if(CardConstant.SWIPER_CARD_THREAD != null) {
CardConstant.SWIPER_CARD_THREAD.interrupt();
}
CardConstant.SWIPER_CARD_THREAD = new Thread(() -> {
while (true) {
try {
if(Thread.currentThread().isInterrupted()){
//处理中断逻辑
break;
}
Thread.sleep(2000);

               data.put("index", index % CardConstant.SWIPER_CARD_LENGTH);
               FormBindingData bindingData = new FormBindingData(data);
               FormControllerManager formControllerManager = FormControllerManager.getInstance(this);

               for(long formid:formControllerManager.getAllFormIdFromSharePreference(CardConstant.SWIPER_CARD_FORMS_NAME)) {
                   updateForm(formid, bindingData);
               }

               index++;
               if(index == CardConstant.SWIPER_CARD_LENGTH){
                   index = 0;
               }
           } catch (Exception e) {
               break;
           }
       }
   });
   CardConstant.SWIPER_CARD_THREAD.start();

}

缺点:此处退出应用程序时,service 不再运行导致轮播线程结束,轮播失效。

JS 2x2 与 2x4 卡片

①新建卡片页面

同 js 轮播卡片的新建卡片页面操作步骤,勾选 2x2、2x4 卡片。

②默认卡片页面

js-card2x4-pages-index-index.json 默认卡片页面的数据:
data:默认数据。

actions:routerEvent 为 router 事件,用于应用跳转;sendMessageEvent1 与 sendMessageEvent2 为 message 事件,用于卡片开发人员自定义点击事件。

js-card2x4-pages-index-index.css 卡片的样式:同 js 页面样式开发。

js-card2x4-pages-index-index.html 卡片的页面:
同 js 页面开发,不过要使用卡片支持组件。

2x2 或 2x4 的卡片公用一个 html 页面,利用 dim2X4 变量 true 或者 false,来展示 2x2 或 2x4 的布局。

click 事件关联 json 文件中的 actions 下的操作事件,此处关联的是点击跳转应用的页面。

代码:on:click="routerEvent"或on:click=“sendMessageEvent1”、on:click=“sendMessageEvent2”(不支持参数传递)。

③初始化卡片页面

在 Jscard2x4Impl.java 文件中 bindFromData 方法中,进行页面展示数据的初始化:

public ProviderFormInfo bindFormData() {
HiLog.info(TAG, "bind form data");
ZSONObject zsonObject = new ZSONObject();
ProviderFormInfo providerFormInfo = new ProviderFormInfo();
if (dimension == DIMENSION_1X2) {
zsonObject.put("mini", true);
}
if (dimension == DIMENSION_2X4) {
zsonObject.put("dim2X4", true);
}
String scheduleData = StorageUtil.initPreferences(context).getSchedule();
if(!"".equals(scheduleData)) {
ZSONArray array = ZSONArray.stringToZSONArray(scheduleData);
if(array.size()>0) {
zsonObject = getObject(array,zsonObject);
}
}
providerFormInfo.setJsBindingData(new FormBindingData(zsonObject));
return providerFormInfo;
}

/**

  • 当天日程存在时,卡片数据展示
  • @param array
  • @param zsonObject
  • @return
    */
    public static ZSONObject getObject(ZSONArray array,ZSONObject zsonObject){
    ZSONArray result = StorageUtil.getCurrentCardSchedule(array);
    ZSONObject schedule_current = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(0)));
    if(schedule_current != null){
    zsonObject.put("schedule_current", schedule_current);
    }
    ZSONObject schedule_1 = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(1)));
    ZSONObject schedule_2 = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(2)));
    if(schedule_1 != null){
    zsonObject.put("noSchedule", false);
    zsonObject.put("hasSchedule1", true);
    zsonObject.put("schedule_1", schedule_1);
    }
    if(schedule_2 != null){
    zsonObject.put("hasSchedule2", true);
    zsonObject.put("schedule_2", schedule_2);
    }
    zsonObject.put("count", array.size());
    return zsonObject;
    }

④更新卡片页面

config.json 配置周期性刷新:config.json 中 jscard2X4 卡片配置"updateEnabled": true 与"updateDuration": 1。

其中 updateDuration 配置参数为 30 分钟倍数,此处 1 即 30 分钟主动刷新一次卡片。

周期性刷新调用 Jscard2x4Impl.java 文件中 updateFormData 方法,代码如下:

public void updateFormData(long formId, Object... vars) {
HiLog.info(TAG, "update form data timing, default 30 minutes");
String scheduleData = StorageUtil.initPreferences(context).getSchedule();
if(!"".equals(scheduleData)) {
ZSONArray array = ZSONArray.stringToZSONArray(scheduleData);
if(array.size()>0) {
FormBindingData formBindingData = new FormBindingData(getObject(array,new ZSONObject()));//上一步中有getObject()方法代码
try {
((MainAbility)context).updateForm(formId, formBindingData);
} catch (FormException e) {
e.printStackTrace();
}
}
}

}

添加当日日程导致数据变化 ,对日程进行更新介绍:数据变化时,触发数据监听方法,代码在 StorageUtil.java 工具类中,这里开启 CardServiceAbility 服务。

CardServiceAbility 服务的 onCommand 方法中调用 cardData 进行卡片更新,其更新代码如下:

FormBindingData formBindingData = new FormBindingData(Jscard2X4Impl.getObject(array,new ZSONObject()));//上一步中有getObject()方法代码
FormControllerManager formControllerManager = FormControllerManager.getInstance(this);

   try {
       for(long id:formControllerManager.getAllFormIdFromSharePreference(CardConstant.JS_CARD_FORMS_NAME)) {
           updateForm(id, formBindingData);
       }
   } catch (FormException e) {
       e.printStackTrace();
   }

⑤router 事件与 message 事件处理

router 事件:在跳转后的页面,接收参数并进行处理,这里请看 MainAbility.java 下的 onStart 方法。

代码如下:

String strParams = intent.getStringParam("params");
if(strParams != null) {
ZSONObject data = ZSONObject.stringToZSON(strParams);
String message = data.getString("message");
//此处可以根据message判断点击了某个按钮,从而做相应的处理
new ToastDialog(this).setText(message)
.setAlignment(LayoutAlignment.CENTER).show();
}

message 事件:在 Jscard2x4Impl.java 文件中 onTriggerFormEvent 方法中进行处理。

代码如下:

public void onTriggerFormEvent(long formId, String message) {
HiLog.info(TAG, "handle card click event.");
ZSONObject data = ZSONObject.stringToZSON(message);
String msg = data.getString("msg");

   Intent intent = new Intent();
   intent.setParam("params","{\"message\":\""+msg+"\"}");
   Operation operation = new Intent.OperationBuilder()
           .withDeviceId("")
           .withBundleName("com.example.myohoscard")
           .withAbilityName("com.example.myohoscard.MainAbility")
           .build();
   intent.setOperation(operation);
   ((MainAbility)context).startAbility(intent);

}

Java 2x2 与 2x4 卡片

①新建卡片页面

同 js 轮播卡片的新建卡片页面操作步骤,勾选 type—java、Dimensions—2x2 与 2x4 卡片。

②默认卡片页面

resources-base-layout 下:
java2x2 卡片布局页面—form_grid_pattern_javacard2x4_2_2.xml
java2x2 卡片布局页面—form_grid_pattern_javacard2x4_2_4.xml
其开发模式同应用 java 模式页面布局开发

③初始化卡片页面

在 Javacard2x4Impl.java 文件中 bindFromData 方法中,进行页面展示数据的初始化:

public ProviderFormInfo bindFormData() {
HiLog.info(TAG, "bind form data when create form");
ProviderFormInfo providerFormInfo = new ProviderFormInfo(RESOURCE_ID_MAP.get(dimension), context);
String scheduleData = StorageUtil.initPreferences(context).getSchedule();
if(!"".equals(scheduleData)) {
ZSONArray array = ZSONArray.stringToZSONArray(scheduleData);
if(array.size()>0) {
// ComponentProvider表示Java卡片
ComponentProvider componentProvider = new ComponentProvider();
providerFormInfo.mergeActions(getFormDataCreate(array,context,dimension,componentProvider));

       }
   }

   return providerFormInfo;

}
public static ComponentProvider getFormDataCreate(ZSONArray array,Context context,int dimension,ComponentProvider componentProvider){
componentProvider.setVisibility(ResourceTable.Id_count, Text.VISIBLE);
componentProvider.setText(ResourceTable.Id_count, array.size()+"");

   ZSONArray result = StorageUtil.getCurrentCardSchedule(array);
   ZSONObject schedule_current = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(0)));
   if(schedule_current != null){
       componentProvider.setText(ResourceTable.Id_time, schedule_current.getString("startCardShow")+"-"+schedule_current.getString("endCardShow"));
       componentProvider.setText(ResourceTable.Id_schedule, schedule_current.getString("title"));
   }
   if (dimension == DEFAULT_DIMENSION_2X2) {
       componentProvider.setIntentAgent(ResourceTable.Id_layout, getStartAbilityIntentAgent(context));
   }

   if (dimension == DIMENSION_2X4) {
       componentProvider.setVisibility(ResourceTable.Id_noschedule, Text.HIDE);
       ZSONObject schedule_1 = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(1)));
       if(schedule_1 != null){

// componentProvider.setText(ResourceTable.Id_time1, schedule_1.getString("startCardShow")+"-"+schedule_1.getString("endCardShow"));
componentProvider.setText(ResourceTable.Id_schedule1, schedule_1.getString("title"));
}

       ZSONObject schedule_2 = null;
       if(result.get(2) != null){
           schedule_2 = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(2)));
       }
       if(schedule_2 != null){
           componentProvider.setVisibility(ResourceTable.Id_line, Text.VISIBLE);

// componentProvider.setText(ResourceTable.Id_time2, schedule_2.getString("startCardShow")+"-"+schedule_2.getString("endCardShow"));
componentProvider.setText(ResourceTable.Id_schedule2, schedule_2.getString("title"));
}
}

   if (dimension == DIMENSION_2X4) {
       componentProvider.setIntentAgent(ResourceTable.Id_more, getStartAbilityIntentAgent(context));
   }
   return componentProvider;

}

④更新卡片页面

config.json 配置定时刷新:config.json 中 jscard2X4 卡片配置"scheduledUpdateTime":“10:42"与"updateDuration”:0。

其中 scheduledUpdateTime 配置参数为 24 小时制,可以在当天指定时间对卡片进行刷新。

定时刷新调用 Javacard2x4Impl.java 文件中 updateFormData 方法,代码如下:

public void updateFormData(long formId, Object... vars) {
HiLog.info(TAG, "update form data timing, default 30 minutes");

   String scheduleData = StorageUtil.initPreferences(context).getSchedule();
   if(!"".equals(scheduleData)) {
       ZSONArray array = ZSONArray.stringToZSONArray(scheduleData);
       if(array.size()>0) {
           ComponentProvider componentProvider =
                   new ComponentProvider(RESOURCE_ID_MAP.get(dimension), context);
           try {
               ((MainAbility)context).updateForm(formId, getFormDataUpdate(array,context,dimension,componentProvider));
           } catch (FormException e) {
               HiLog.error(TAG, e.toString());
           }

       }
   }

}
public static ComponentProvider getFormDataUpdate(ZSONArray array,Context context,int dimension,ComponentProvider componentProvider){

   componentProvider.setVisibility(ResourceTable.Id_count, Text.VISIBLE);
   componentProvider.setText(ResourceTable.Id_count, array.size()+"");

   ZSONArray result = StorageUtil.getCurrentCardSchedule(array);
   ZSONObject schedule_current = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(0)));
   if(schedule_current != null){
       componentProvider.setText(ResourceTable.Id_time, schedule_current.getString("startCardShow")+"-"+schedule_current.getString("endCardShow"));
       componentProvider.setText(ResourceTable.Id_schedule, schedule_current.getString("title"));
   }

   if (dimension == DIMENSION_2X4) {
       componentProvider.setVisibility(ResourceTable.Id_noschedule, Text.HIDE);
       ZSONObject schedule_1 = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(1)));
       if(schedule_1 != null){

// componentProvider.setText(ResourceTable.Id_time1, schedule_1.getString("startCardShow")+"-"+schedule_1.getString("endCardShow"));
componentProvider.setText(ResourceTable.Id_schedule1, schedule_1.getString("title"));
}

       ZSONObject schedule_2 = null;
       if(result.get(2) != null){
           schedule_2 = ZSONObject.stringToZSON(ZSONObject.toZSONString(result.get(2)));
       }
       if(schedule_2 != null){
           componentProvider.setVisibility(ResourceTable.Id_line, Text.VISIBLE);

// componentProvider.setText(ResourceTable.Id_time2, schedule_2.getString("startCardShow")+"-"+schedule_2.getString("endCardShow"));
componentProvider.setText(ResourceTable.Id_schedule2, schedule_2.getString("title"));
}
}

   return componentProvider;

}

添加当日日程导致数据变化 ,对日程进行更新介绍:数据变化时,触发数据监听方法,代码在 StorageUtil.java 工具类中,这里开启 CardServiceAbility 服务。

CardServiceAbility 服务的 onCommand 方法中调用 cardData 进行卡片更新,其更新代码如下:

try {
for(long id:formControllerManager.getAllFormIdFromSharePreference(CardConstant.JAVA_CARD_FORMS_NAME)) {
int dimension = formControllerManager.getDimension(id+"");

           ComponentProvider componentProvider =
               new ComponentProvider(Javacard2x4Impl.RESOURCE_ID_MAP.get(dimension), this);
           updateForm(id, Javacard2x4Impl.getFormDataUpdate(array,this,dimension,componentProvider));//上一步中有此方法代码
       }
   } catch (FormException e) {
       e.printStackTrace();
   }

⑤卡片点击事件添加

给控件点击点击事件,其代码为:

componentProvider.setIntentAgent(ResourceTable.Id_more, getStartAbilityIntentAgent(context))

其中 getStartAbilityIntentAgent 方法代码如下:

private static IntentAgent getStartAbilityIntentAgent(Context context) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("com.example.myohoscard")
.withAbilityName("com.example.myohoscard.MainAbility")
.build();
intent.setOperation(operation);
List intentList = new ArrayList<>();
intentList.add(intent);
List flags = new ArrayList<>();
flags.add(IntentAgentConstant.Flags.UPDATE_PRESENT_FLAG);
IntentAgentInfo paramsInfo =
new IntentAgentInfo(200, IntentAgentConstant.OperationType.START_ABILITY, flags, intentList, null);
return IntentAgentHelper.getIntentAgent(context, paramsInfo);
}

代码参考:
https://gitee.com/chinasoft6_ohos/my-ohos-card

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 93 收藏 评论 打赏
评论
1个
内容存在敏感词
手气红包
  • david 2021-08-04 18:28:42
    回复

    这是手机平台上的么?

相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
奋斗的疯子
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区