赞
踩
参考文档:
1、只定义一个FA卡片
首先通过DevEco Studio创建一个工程,创建完成之后,找到src/main/config.json文件,
在config.json配置文件中,在module--->abilities--->forms节点下,只有一条数据。
forms节点下的isDefault字段值为true,表示该卡片为默认卡片,每个Ability有且只有一个默认卡片。
备注:forms节点的数据结构是数组,这里的要求是内部只有一个{}对象数据。
2、提供多种尺寸
在forms节点下的supportDimensions字段中配置多种尺寸,比如这里配置了1*2和2*2两种尺寸:
3、对应卡片的js相关资源
“js”模块中的name字段要与“forms”模块中的jsComponentName字段的值一致,为js资源的实例名。
4、添加相应权限
例如:卡片需要请求网络数据,需要添加相应的网络权限,打开config.json文件,在module节点下添加reqPermissions节点,如下图所示:
5、快照
需要在元服务开发态默认将快照图定义成和2*2卡片相同的内容,用于对新用户展示。
基于景区模板开发可以跳过此步骤,低码模板中已经有低码SDK。
在项目工程的根目录下build.gradle文件中的dependencies闭包中添加如下依赖:
在entry的根目录下的build.gradle文件的头部添加以下内容:
同时在dependencies闭包中添加低码SDK的依赖:
在entry/src/main/java/包名/MyApplication.java文件中进行SDK初始化:
基于景区模板开发可以跳过此步骤,此步骤主要介绍如何在云侧创建数据模型。
登录AppGallery Connect控制台,找到对应的项目,然后选中低代码平台中的数据模型,点击新建数据模型:
之后点击编辑,为该数据模型添加所需的字段:
所需的数据字段创建完成之后,点击保存。
回到数据模型列表所在页面,点击管理数据,之后点击新建,创建以上数据模型所需的数据:
在所需的数据全部添加完成之后,数据模型就创建完成了。
第一种:负一屏通过AGC自定义参数
在云侧数据模型中创建了extraParam这个预留参数字段(注意:此处可以创建多个字段,需要和AGC管理台位置感应服务中创建的字段保持一致),通过在AGC管理台---位置感应服务---服务申请中创建相应的字段,端侧获取该字段值,通过对不同值进行判断处理,控制端侧卡片展示不同样式内容。
第二种:小艺建议通过不同POI ID
在云侧数据模型中创建了poi_id字段(字段名称需要根据实际创建),端侧获取该字段值,通过对不同值进行判断处理,小艺建议通过不同POI ID实现控制端侧卡片展示不同的样式内容。
卡片的典型开发目录结构如下图所示,详细介绍参见文件组织。
目录中主要文件夹如下:
目录中文件分类如下:
在index.hml文件中实现卡片的页面布局。最外层使用div组件和stack组件。stack组件内部使用了两个div组件分别布局1x2和2x2两种不同大小的卡片样式,并且绑定click事件。1x2格式卡片为左右结构,左侧text组件显示标题,右侧Image组件显示播放按钮,绑定消息事件。2x2格式卡片为上下结构,上方text组件显示标题,下方Image组件显示播放按钮,并且绑定消息事件。
- <div class="container">
- <stack style="height: 100%;width: 100%;">
- <div class="item-container-small" show="{{smallCard}}" "routerEvent">
- <text class="title-small">{{title}}</text>
- <image src="{{btnSrc}}" class="btn-img-small" "messageEvent"></image>
- </div>
- <div class="item-container-normal" show="{{normalCard}}" "routerEvent">
- <text class="title-normal">{{title}}</text>
- <image src="{{btnSrc}}" class="btn-img-normal" "messageEvent"></image>
- </div>
- </stack>
- </div>
在index.css文件中定义页面样式,除通用样式外,各组件还可以定义自己特有的样式。例如:text组件设置font-size。组件样式的设置参见各组件的详细介绍。
- .container {
- flex-direction: column;
- justify-content: center;
- align-items: center;
- }
- .title-small {
- font-size: 12fp;
- margin-start: 15px;
- }
- .title-normal {
- margin-top: 30px;
- font-size: 20fp;
- }
- .item-container-small {
- width: 100%;
- height: 100%;
- align-items: center;
- }
- .item-container-normal {
- width: 100%;
- height: 100%;
- align-items: center;
- flex-direction: column;
- }
- .btn-img-small {
- margin-start: 25px;
- width: 32px;
- height: 32px;
- }
- .btn-img-normal {
- margin-top: 20px;
- width: 64px;
- height: 64px;
- }
在index.json文件中配置卡片使用的变量和事件,在data字段中声明变量,在actions字段中声明事件。
本示例在action中定义了名为“routerEvent”的事件,事件类型为“router”,用于跳转到MainAbility。更多用户自定义事件可以使用action:"message"实现。
- {
- "data": {
- "smallCard": false,
- "normalCard": true,
- "type": "",
- "title": "",
- "btnSrc": ""
- },
- "actions": {
- "routerEvent": {
- "action": "router",
- "bundleName": "com.lowcode.scenicarea",
- "abilityName": "com.lowcode.scenicarea.MainAbility",
- "params": {
- "message": "add detail"
- }
- },
- "messageEvent": {
- "action": "message",
- "params": {
- "message": "play"
- }
- }
- }
- }
除了通过页面主动触发事件,还可以通过卡片各生命周期的回调函数来实现业务处理。卡片生命周期回调在卡片对应的PageAbility中,本示例对应的pageAbility为com.lowcode.scenicarea.MainAbility。在MainAbility的卡片创建回调函数onCreateForm中通过Intent获取卡片的ID、name等信息:
- public class MainAbility extends AceAbility {
- public static final int DEFAULT_DIMENSION_2X2 = 2;
- private static final int INVALID_FORM_ID = -1;
- private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, MainAbility.class.getName());
- private String topWidgetSlice;
- @Override
- protected ProviderFormInfo onCreateForm(Intent intent) {
- HiLog.info(TAG, "onCreateForm");
- 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;
- }
- return formController.bindFormData(formId);
- }
- ...
- }
创建数据模型端侧数据实体CardInfo.java:
- public class CardInfo {
- private String id;
- private String type;
- private String title;
- private String btnSrc;
- private String extraParam;
- private String poi_id;
- setter(); // 定义各个变量的setter方法
- getter(); // 定义各个变量的getter方法
- }
创建获取数据模型端侧数据工具类DataUtil.java:
- public class DataUtil {
- private static final HiLogLabel TAG = new HiLogLabel(HiLog.INFO, 0x00201, "jscard");
-
- public static List<CardInfo> getData() {
- List<CardInfo> mCardInfos = new ArrayList<>();
- DataModelRequest request = new DataModelRequest();
- request.setModelId("1179644081647666113");
- request.setStatus(0);
- request.setMethodName("list");
- DataModelReqParams params = new DataModelReqParams();
- params.setOrderBy("id");
- params.setOrderType("asc");
- request.setParams(params);
- HarmonyTask<DataModelResponse> task = AGConnectLowCode.getInstance().callDataModel(request);
- task.addOnCompleteListener(new OnHarmonyCompleteListener<DataModelResponse>() {
- @Override
- public void onComplete(HarmonyTask<DataModelResponse> harmonyTask) {
- if (harmonyTask.isSuccessful()) {
- DataModelResponse response = harmonyTask.getResult();
- List<Map<String, Object>> list = response.getData().getRecords();
- mCardInfos.clear();
- for (Map<String, Object> map : list) {
- CardInfo cardInfo = new CardInfo();
- cardInfo.setId(map.get("id").toString());
- cardInfo.setType(map.get("type").toString());
- cardInfo.setTitle(map.get("title").toString());
- cardInfo.setBtnSrc(map.get("btnSrc").toString());
- cardInfo.setExtraParam(map.get("extraParam").toString());
- cardInfo.setPoi_id(map.get("poi_id").toString());
- mCardInfos.add(cardInfo);
- }
- HiLog.info(TAG, "success");
- } else {
- HiLog.info(TAG, "fail");
- }
- }
- });
- return mCardInfos;
- }
- }
创建单例管理类DataInstance.java用来管理数据和Player播放器:
- public class DataInstance {
- private static class SingletonHolder {
- private static final DataInstance INSTANCE = new DataInstance();
- }
-
- private DataInstance () {}
-
- public static final DataInstance getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- private List<CardInfo> list;
- private Player player;
-
- private boolean isPlay= false;
-
- public boolean isPlay() {
- return isPlay;
- }
-
- public void setPlay(boolean play) {
- isPlay = play;
- }
-
- public Player getPlayer() {
- return player;
- }
-
- public void setPlayer(Player player) {
- this.player = player;
- }
-
- public List<CardInfo> getList() {
- return list;
- }
-
- public void setList(List<CardInfo> list) {
- this.list = list;
- }
- }
首先在MainAbility.java类的onStart()方法中初始化数据和播放器:
- public class MainAbility extends AceAbility {
- public static final int DEFAULT_DIMENSION_2X2 = 2; //System-defined constant. Do not change its value.
- private static final int INVALID_FORM_ID = -1;
- private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, "jscard");
- private String topWidgetSlice;
- private Player mPlayer;
-
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- DataInstance.getInstance().setList(DataUtil.getData());
- initPlayer();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- }
-
- private void initPlayer() {
- if (mPlayer == null) {
- mPlayer = new Player(this);
- }
- DataInstance.getInstance().setPlayer(mPlayer);
- Source source = new Source("https://www.cambridgeenglish.org/images/153149-movers-sample-listening-test-vol2.mp3");
- DataInstance.getInstance().getPlayer().setSource(source);
- DataInstance.getInstance().getPlayer().prepare();
- }
-
- @Override
- protected ProviderFormInfo onCreateForm(Intent intent) {
- HiLog.info(TAG, "onCreateForm");
- 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;
- }
- if (DataInstance.getInstance().getList()==null || DataInstance.getInstance().getList().size()==0){
- DataInstance.getInstance().setList(DataUtil.getData());
- initPlayer();
- }
- return formController.bindFormData(formId);
- }
- ……
- }
在WidgetImpl.java类的bindFormData()方法中初始化卡片展示:
- private Context mContext;
- public WidgetImpl(Context context, String formName, Integer dimension) {
- super(context, formName, dimension);
- HiLog.info(TAG, "WidgetImpl");
- this.mContext = context;
- }
-
- @Override
- public ProviderFormInfo bindFormData(long formId) {
- HiLog.info(TAG, "bind form data");
- ZSONObject object = new ZSONObject();
- if (dimension == DIMENSION_1X2) {
- object.put("smallCard", true);
- object.put("normalCard", false);
- object.put("type", DataInstance.getInstance().getList().get(0).getType());
- object.put("title", DataInstance.getInstance().getList().get(0).getTitle());
- if (!DataInstance.getInstance().isPlay()){
- object.put("btnSrc", DataInstance.getInstance().getList().get(0).getBtnSrc());
- }else {
- object.put("btnSrc", DataInstance.getInstance().getList().get(1).getBtnSrc());
- }
- } else if (dimension == DIMENSION_2X2) {
- object.put("smallCard", false);
- object.put("normalCard", true);
- object.put("type", DataInstance.getInstance().getList().get(2).getType());
- object.put("title", DataInstance.getInstance().getList().get(2).getTitle());
- if (!DataInstance.getInstance().isPlay()){
- object.put("btnSrc", DataInstance.getInstance().getList().get(2).getBtnSrc());
- }else {
- object.put("btnSrc", DataInstance.getInstance().getList().get(3).getBtnSrc());
- }
- }
- FormBindingData bindingData = new FormBindingData(object);
- ProviderFormInfo formInfo = new ProviderFormInfo();
- formInfo.setJsBindingData(bindingData);
- return formInfo;
- }
此部分功能同样在WidgetImpl.java类中实现:
创建音乐播放/暂停的方法:
- // 暂停音乐
- private void pause() {
- DataInstance.getInstance().getPlayer().pause();
- }
-
- // 播放音乐
- private void play() {
- DataInstance.getInstance().getPlayer().play();
- }
音乐播放/暂停时更新播放按钮的图片资源:
- // 更新数据
- private void updateForm(long formId, String btnSrc) {
- ZSONObject object = new ZSONObject();
- object.put("btnSrc", btnSrc);
- try {
- if (mContext instanceof Ability) {
- ((Ability) mContext).updateForm(formId, new FormBindingData(object));
- }
- } catch (FormException e) {
- HiLog.error(TAG, e.getMessage());
- }
- }
在2.4中配置了卡片的消息事件,通过消息事件触发音乐播放,在onTriggerFormEvent()方法中接收事件并处理播放/暂停及按钮的样式更新逻辑:
- @Override
- public void onTriggerFormEvent(long formId, String message) {
- HiLog.info(TAG, "onTriggerFormEvent");
- if (!TextUtils.isEmpty(message)){
- ZSONObject zsonObject = ZSONObject.stringToZSON(message);
- String msg = zsonObject.getString("message");
- if (!TextUtils.isEmpty(msg) && "play".equals(msg)){
- if (!DataInstance.getInstance().isPlay()){
- DataInstance.getInstance().setPlay(true);
- if (dimension==DIMENSION_1X2){
- updateForm(formId,DataInstance.getInstance().getList().get(1).getBtnSrc());
- }else if (dimension==DIMENSION_2X2){
- updateForm(formId,DataInstance.getInstance().getList().get(3).getBtnSrc());
- }
- play();
- }else {
- DataInstance.getInstance().setPlay(false);
- if (dimension == DIMENSION_1X2){
- updateForm(formId,DataInstance.getInstance().getList().get(0).getBtnSrc());
- }else if (dimension==DIMENSION_2X2){
- updateForm(formId,DataInstance.getInstance().getList().get(2).getBtnSrc());
- }
- pause();
- }
- }
- }
- }
最后来看一下播放的效果:
在实际应用中,有时我们希望服务卡片能随用户所处的场景展示不同的内容,比如:当用户身处景点A时,卡片展示景点A的服务信息;当用户游玩到景点B时,卡片能更新展示景点B的服务信息。
针对此需求,我们可以结合“位置感应服务”来实现,当用户靠近注册的Beacon设备位置区域时,在负一屏的卡片中展示相应的内容。
在申请位置感应服务时,我们定义一个参数extFaParamTitle来设置不同区域展示的内容,然后在卡片侧获取extFaParamTitle的值,最后根据extFaParamTitle配置的不同值,来实现不同场景下展示不同内容。具体实现方式如下。
1. 开通“位置感应服务”后,申请服务时,通过“自定义参数”处参数extFaParamTitle来设置不同地方展示的标题内容。
2.在DataInstance.java中定义extFaParamTitle变量。
- private String extFaParamTilte;
-
- public String getExtFaParamTilte() {
-
- return extFaParamTilte;
-
- }
-
- public void setExtFaParamTilte(String extFaParamTilte) {
-
- this.extFaParamTilte = extFaParamTilte;
-
- }
3. 在MainAbility.java中的onCreateForm()方法中获取extFaParamTitle字段的值。
- @Override
-
- protected ProviderFormInfo onCreateForm(Intent intent) {
-
- HiLog.info(TAG, "onCreateForm");
-
- // ......此处省略部分代码
-
- // 1、从intent中获取IntentParams
-
- IntentParams intentParams = intent.getParam(AbilitySlice.PARAM_FORM_CUSTOMIZE_KEY);
-
- if (intentParams!=null){
-
- // 2、从IntentParams中获取使用方法传递的参数
-
- String extFaParam = (String) intentParams.getParam("extFaParam");
-
- HiLog.info(TAG,"extFaParam"+extFaParam);
-
- ZSONObject extraParamJson = ZSONObject.stringToZSON(extFaParam);
-
- // "{"extFaParamTilte":"xxxxs"}"
-
- String extFaParamTilte = extraParamJson.getString("extFaParamTilte");
-
- HiLog.info(TAG,"extFaParamTilte"+extFaParamTilte);
-
- DataInstance.getInstance().setExtFaParamTilte(extFaParamTilte);
-
- }
-
- // ......此处省略部分代码
-
- return formController.bindFormData(formId);
-
- }
4. 在WidgetImpl.java的bindFormData()方法中通过判断extFaParamTitle字段的值,让卡片展示不同的标题。
- @Override
-
- public ProviderFormInfo bindFormData(long formId) {
-
- HiLog.info(TAG, "bind form data");
-
- ZSONObject object = new ZSONObject();
-
- if (dimension == DIMENSION_1X2) {
-
- // ......此处省略部分代码
-
- // 根据动态获取的配置项里的字段值,动态修改标题内容
-
- if (!TextUtils.isEmpty(DataInstance.getInstance().getExtFaParamTilte())){
-
- object.put("title",DataInstance.getInstance().getExtFaParamTilte());
-
- }
-
- // ......此处省略部分代码
-
- } else if (dimension == DIMENSION_2X2) {
-
- // ......此处省略部分代码
-
- // 根据动态获取的配置项里的字段值,动态修改标题内容
-
- if (!TextUtils.isEmpty(DataInstance.getInstance().getExtFaParamTilte())){
-
- object.put("title",DataInstance.getInstance().getExtFaParamTilte());
-
- }
-
- // ......此处省略部分代码
-
- }
-
- FormBindingData bindingData = new FormBindingData(object);
-
- ProviderFormInfo formInfo = new ProviderFormInfo();
-
- formInfo.setJsBindingData(bindingData);
-
- return formInfo;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。