HarmonyOS实战—欧洲杯还可以这么玩?

Posted 李元静

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS实战—欧洲杯还可以这么玩?相关的知识,希望对你有一定的参考价值。

HarmonyOS实战

前言

六月以来,欧洲杯正让国内的体育迷陷入狂欢。特别是今晚,欧洲杯1/4决赛正式开启大幕,相信观看的国人会越来越多。
欧洲杯卡片设计
那么在鸿蒙手机上,设计一个欧洲杯卡片,用于在桌面提醒各位球迷可谓相得益彰,毕竟实时球讯,亮屏即达。

首先,我们需要分析一下欧洲杯赛事的卡片布局,如上图所示。

  1. 布局之中,有一张图片以及一段资讯文字
  2. 同时,卡片自动轮播实时的欧洲资讯内容。

对于布局来说,很好理解,就是一个图片和一个文本内容。而卡片内容的自动轮播就是定时触发的内容替换。

创建卡片

当我们创建了一个鸿蒙App项目之后,我们需要在点击src右键进行卡片的创建,如下图所示:

卡片的创建
如首图所示,因为是一个22的卡片,这里我们可以随意选择一个22的布局即可,反正后面的所有样式以及交互都需要修改。

创建卡片
到这里,我们的卡片就创建完成了。

而在项目之中,会多2个widget文件,一个是java之中的,用于卡片与用户的交互与生成。另一个是js里面的widget,用于界面的设计。

卡片的文件

卡片的样式开发

布局设计

既然卡片已经创建完成,也知道了欧洲杯赛事的卡片设计需要分2个步骤,那么这里我们先来实现其样式与布局,至于功能代码,后续介绍。

index.hml

首先,我们需要通过index.hml文件实现一个图片以及文本的布局。代码如下:

<div class="card_root_layout" onclick="routerEvent1">
    <image class="div_image" src="{{imageUrl}}"/>
    <text class="div_text">{{titleName}}</text>
</div>

简单来说,就4行代码,毕竟布局很简单。

index.css

接着,设计我们欧洲杯赛事卡片的样式,代码如下:

.card_root_layout {
    flex-direction: column;
    align-items: center;
    width: 100%;
    margin: 10px;
    height: 100%;
}

.div_image{
    width: 200px;
    height: 112px;
    object-fit: fill;
}

.div_text{
    margin-top: 5px;
    font-size: 10px;
    color: black;
    font-family: sans-serif;
}

index.json

最后,就是我们的交互以及卡片的数据,index.json决定了交互的方式以及数据,但是实现代码在java文件中,index.json只用作定义。代码如下:

{
  "data": {
    "titleName": "",
    "imageUrl": ""
  },
  "actions": {
    "routerEvent1": {
      "action": "router",
      "abilityName": "com.liyuanjinglyj.europeancup.widget.WidgetAbility",
      "params": {
        "message": "button"
      }
    }
  }
}

如上面代码所示,这里定义了2个数据:titleName(欧洲杯赛事标题),imageUrl(欧洲杯赛事图片)。

还有一个路由跳转,毕竟点击资讯我们是为了查看详细的内容的。

卡片的交互

卡片数据的初始化

当用户添加或者查看卡片内容时,它是有一个基本的数据的。所以,我们需要在java中获取图片以及文本然后传递给卡片。代码如下(WidgetImpl):

public class WidgetImpl extends FormController {
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, WidgetImpl.class.getName());
    private static final int DEFAULT_DIMENSION_2X2 = 2;
    private String url = "https://harmony-1300376177.cos.ap-shanghai.myqcloud.com/europeancup.json";
    private int size=0;
    public WidgetImpl(Context context, String formName, Integer dimension) {
        super(context, formName, dimension);
    }
	//获取网络数据
    private ZSONArray getData() {
        LYJHttps lyjHttps = new LYJHttps();
        String response = lyjHttps.doGet(url);
        ZSONObject jsonStr = ZSONObject.stringToZSON(response);
        ZSONObject result = jsonStr.getZSONObject("result");
        ZSONArray data = result.getZSONArray("data");
        this.size=data.size();
        return data;
    }

	//卡片的初始化
    @Override
    public ProviderFormInfo bindFormData() {
        HiLog.info(TAG, "bind form data");
        ProviderFormInfo providerFormInfo = new ProviderFormInfo();
        if (dimension == DEFAULT_DIMENSION_2X2) {
            ZSONObject zsonObject = new ZSONObject();
            HiLog.info(TAG, "update form data: formId" + ((ZSONObject) (getData().get(0))).getString("img"));
            zsonObject.put("imageUrl", ((ZSONObject) (getData().get(0))).getString("img"));
            zsonObject.put("titleName", ((ZSONObject) (getData().get(0))).getString("title"));
            providerFormInfo.setJsBindingData(new FormBindingData(zsonObject));
        }
        return providerFormInfo;
    }

    //卡片的更新
    @Override
    public void updateFormData(long formId, Object... vars) {
        HiLog.info(TAG, "update form data: formId" + formId);

    }
	//卡片的事件处理
    @Override
    public void onTriggerFormEvent(long formId, String message) {
        HiLog.info(TAG, "onTriggerFormEvent.");
    }
    
	//卡片的界面跳转
    @Override
    public Class<? extends AbilitySlice> getRoutePageSlice(Intent intent) {
        HiLog.info(TAG, "set route page slice.");
        ZSONObject zsonObject = ZSONObject.stringToZSON(intent.getStringParam("params"));
        if (zsonObject.getString("message").equals("button")) {
            return WidgetSlice.class;
        }
        return null;
    }
}

这里就是获取数据,然后传递到js卡片当中。

通过providerFormInfo.setJsBindingData()方法进行数据的初始化,而基础数据在ZSONObject中进行添加。

到这一步,读者可以运行App添加卡片,其已经具有展示的效果了。但是卡片不会自动替换数据,因为我们没有设置定时替换数据的代码。

卡片的定时更新

所以,我们需要给卡片设置定时的数据替换,让其轮播当前的所有欧洲杯赛事资讯。这样,新鲜资讯就可以通过这么一个2*2卡片全部显示出来。

代码如下(WidgetAbility):

public class WidgetAbility extends Ability {
	private ZSONArray zsonArray;
	
	// 定时器,每秒执行一次
    private void startTimer(long formId) {
        this.zsonArray= LYJUtils.getData("https://harmony-1300376177.cos.ap-shanghai.myqcloud.com/europeancup.json");
        Timer timer = new Timer();
        timer.schedule(
                new TimerTask() {
                    @Override
                    public void run() {
                        updateForms(formId);
                    }
                },
                0,
                5000);
    }

    //更新卡片
    private void updateForms(long formId){
        int max=this.zsonArray.size()-1,min=0;
        int ran2 = (int) (Math.random()*(max-min)+min);
        ZSONObject zsonObject=new ZSONObject();
        zsonObject.put("imageUrl", ((ZSONObject) (zsonArray.get(ran2))).getString("img"));
        zsonObject.put("titleName", ((ZSONObject) (zsonArray.get(ran2))).getString("title"));
        FormBindingData bindingData=new FormBindingData(zsonObject);
        try {
            if(!updateForm(formId,bindingData)){
                HiLog.error(TAG,"updateForm error");
            }
        }catch (FormException e){
            HiLog.error(TAG,"updateForm error");
        }
    }
	
	@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;
        }
		
		//启动定时任务
        this.startTimer(formId);

        return formController.bindFormData();
    }

}

这里,我们通过定义定时器任务每5秒进行更新卡片,同时在onCreateForm()函数中,启动定时任务。至于卡片的数据,通过随机数自动获取。

权限设置

除此之外,我们还需要设置网络权限等基本的数据代码。

"module": {
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      },
    ],
}

到这里,我们卡片的交互以及卡片的布局都已经设计完成,运行之后的效果也与首图一摸一样。

源代码下载地址:https://gitee.com/liyuanjinglyj/EuropeanCup

本文正在参与“有奖征文 | HarmonyOS征文大赛”活动:

活动链接:https://marketing.csdn.net/p/ad3879b53f4b8b31db27382b5fc65bbc

以上是关于HarmonyOS实战—欧洲杯还可以这么玩?的主要内容,如果未能解决你的问题,请参考以下文章

Docker竟然还能这么玩?商业级4G代理搭建实战!

CT片居然可以这么玩:用头部CT断层扫描片复原三维头像

CT片居然可以这么玩:用头部CT断层扫描片复原三维头像

酸爽!原来IDEA还可以这么玩 MyBatis,让编码速度飞起

磁力片只会搭建?这些脑洞STEAM玩法比新玩具还香!

没想到 Hash 冲突还能这么玩,你的服务中招了吗?