HarmonyOS实战—天气类卡片设计
Posted 一天一篇Python库
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS实战—天气类卡片设计相关的知识,希望对你有一定的参考价值。
HarmonyOS实战
前言
对于日常的天气类App来说,我们用户应该很少与其进行交互,毕竟都是一些简单的数据,偶尔用到查看即可。
但是,查看7日天气必须打开App非常不方便,如果开发中能够提供一个7日天气卡片到桌面,肯定能获得用户的好感。
所以,今天的内容就是实现一个7日天气的原子化服务。
7日天气的布局
首先,我们肯定需要完善7日天气的布局。
众所周知,7日的天气往往都比较长,那么2*2的卡片肯定是无法满足的。这时候,选择长卡片来实现7日天气往往效果更好。
这里,我们选择2*4的卡片,其index.hml布局代码如下所示:
<div class="card_root_layout">
<image src="common/refresh.png" class="refresh_image" onclick="refresh"/>
<list class="weather_list">
<list-item for="{{weatherList}}" class="list_item">
<div class="list_div" onclick="routerEvent">
<text class="list_text">{{$item.wea_day}}</text>
<image class="list_image" src="{{$item.image}}"/>
<text class="list_text">{{$item.week}}</text>
</div>
</list-item>
</list>
</div>
从上面的布局,我们很容易分析出布局的样式,肯定有一个横向的List,以及一个主动提供给用户的天气刷新按钮。
卡片的事件定义
除此之外,还有2个点击事件,一个是当用户点击卡片刷新按钮时,会调用refresh方法。当用户点击每天天气时,会直接跳转到应用。
具体的方法定义如下所示(index.json):
{
"data": {
"weatherList":""
},
"actions": {
"refresh": {
"action": "message",
"params": {
"mAction": "refresh"
}
},
"routerEvent": {
"action": "router",
"bundleName": "com.liyuanjinglyj.jsweather",
"abilityName": "com.liyuanjinglyj.jsweather.MainAbility",
"params": {
"message": "router"
}
}
}
}
其中,action取值为message表示是一个消息事件,取值为router表示为一个路由跳转事件。至于params是参数,用于在Java中区分事件类别与跳转到哪个路由。
获取基础的天气数据
这里,我们是通过天气API网站的接口进行天气的Json数据获取,具体的网址为:https://yiketianqi.com/,注册之后,每个用户有2000次免费的天气获取次数。
其中接口如下所示:
https://yiketianqi.com/api?version=v9&appid=&appsecret=&city=
这里,appid与appsecret在注册之后,网站会提供给用户,至于city表示城市。比如获取北京市天气,这里只需要city=北京即可。
特别注意,这里city的赋值,必须去掉城市最后一个市,洲,县等。比如你输入宜昌市,那么默认都会返回北京的天气,而输入宜昌才能返回宜昌的天气。
返回的Json数据如下图所示:
如上图所示,这里data之上的数据城市以及天气获取时间的基本信息,而data之内数组才是每日的天气,返回的7日天气。
解析Json数据
既然,我们已经知道了json的接口,那么通过程序进行网络请求之后,我们需要解析我们的Json数据为应用所用。
而鸿蒙给我们提供了ZSONObject以及ZSONArray进行Json数据的解析,具体的代码如下所示(WidgetImpl):
public class WidgetImpl extends FormController {
private String url="https://yiketianqi.com/api?version=v9&appid=(你的appid)&appsecret=(appsecret)&city=";
private ZSONArray getData(String cityStr){
LYJUtils http = new LYJUtils();
String response = http.doGet(url+cityStr);
ZSONObject res = ZSONObject.stringToZSON(response);
ZSONArray data = res.getZSONArray("data");
WeatherImageMap weatherImageMap=new WeatherImageMap();
Map<String,String> map= weatherImageMap.getMap();
ZSONArray weatherList=new ZSONArray();
for(int i=0;i<data.size();i++){
ZSONObject zsonObject = (ZSONObject)data.get(i);
zsonObject.put("image",map.get(zsonObject.getString("wea_day")));
weatherList.add(zsonObject);
}
ZSONObject list_data = (ZSONObject)data.get(0);
String content=list_data.getString("date");
return weatherList;
}
}
如上面代码所示,因为默认天气数据没有提供对应的天气图片,所以这里我们通过WeatherImageMap指定了指定了天气对应图片地址的键值对。
然后,将ZSONArray的7日天气json数据作为返回值。
卡片初始化
对于创建的Js卡片,其卡片初始化的一些数据是在Java类中进行的,这里是在WidgetImpl.java类中,对应的初始化方法为bindFormData()方法。
代码如下:
public class WidgetImpl extends FormController {
//卡片初始化时方法
@Override
public ProviderFormInfo bindFormData() {
HiLog.info(TAG, "开始");
ZSONObject object = new ZSONObject();
object.put("weatherList", getData("北京"));
FormBindingData bindingData = new FormBindingData(object);
ProviderFormInfo formInfo = new ProviderFormInfo();
formInfo.setJsBindingData(bindingData);
return formInfo;
}
}
如上面代码所示,我们这里将刚才获取的7日json数据设置到ZSONObject中,并指定其在js的变量名为weatherList,对应index.json文件中data中的数据。
刷新天气功能实现
其次,我们不仅需要展示天气数据,而且需要提供给用户一个自己手动更新天气的按钮进行交互。
交互的功能也在WidgetImpl类中,由onTriggerFormEvent()方法进行处理。代码如下所示:
public class WidgetImpl extends FormController {
// 卡片消息事件时方法
@Override
public void onTriggerFormEvent(long formId, String message) {
ZSONObject zsonObject = ZSONObject.stringToZSON(message);
HiLog.info(TAG, "onTriggerFormEvent");
ZSONObject result = new ZSONObject();
switch (zsonObject.getString("mAction")) {
case "refresh":
result.put("weatherList",getData("宜昌"));
break;
default:
break;
}
// Update js card
try {
if (mContext instanceof Ability) {
((Ability) mContext).updateForm(formId, new FormBindingData(result));
}
} catch (FormException e) {
HiLog.error(TAG, e.getMessage());
}
}
}
如上面代码所示,这里通过mAction机型判断,需要处理的是哪个时间。当然,这里的天气卡片,我们只提供了一个刷新功能,所以只有一个事件。
但在实际的项目中,卡片的交互功能往往很多,比如说音乐类App提供一个卡片进行音乐的播放交互,那么就会提供播放,暂停,下一首,上一首等很多功能。
那么就可以直接通过swicth进行事件字符串的判断,区分其进行的处理方式。
这里,为了用户能看到真正的交互效果,我们将城市进行了切换,毕竟7日天气同一城市,短时间是没有任何变化的。
到这里,基本的交互功能以及界面就全部完成了,实现的效果如首图所示。
卡片界面的样式
在前面我们只介绍了卡片的布局index.hml,以及卡片的交互基本数据的定义index.json。但之所以卡片的界面如首图一样显示,是因为样式index.css:
.card_root_layout {
flex-direction: column;
width: 100%;
height: 100%;
background-image: url("common/cardbg.jpg");
}
.refresh_image {
width: 30px;
height: 30px;
margin-left: 10px;
margin-top: 10px;
object-fit: contain;
}
.weather_list{
margin-top: 2px;
margin-left: 10px;
margin-right: 10px;
margin-bottom: 10px;
flex-direction: row;
height: 100%;
width: 100%;
align-content: center;
align-items: center;
justify-content: center;
}
.list_item{
margin-right: 10px;
}
.list_div{
flex-direction: column;
align-items: center;
}
.list_text{
font-size: 15px;
margin-top: 15px;
}
.list_image{
height: 30px;
object-fit: contain;
margin-top: 20px;
}
网络请求
在上面,我们是通过自己定义的网络请求,获取json数据字符串的。这里,博主直接给出定义的网络请求类(LYJUtils.java)的代码:
public class LYJUtils {
public static String doGet(String httpUrl) {
HttpsURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;// 返回结果字符串
try {
// 创建远程url连接对象
URL url = new URL(httpUrl);
// 通过远程url连接对象打开一个连接,强转成httpURLConnection类
connection = (HttpsURLConnection) url.openConnection();
// 设置连接方式:get
connection.setRequestMethod("GET");
// 设置连接主机服务器的超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取远程返回的数据时间:60000毫秒
connection.setReadTimeout(60000);
// 发送请求
connection.connect();
// 通过connection连接,获取输入流
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
// 存放数据
StringBuffer sbf = new StringBuffer();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\\r\\n");
}
result = sbf.toString();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();// 关闭远程连接
}
return result;
}
}
定义权限
这里,因为我们获取了网络数据。所以,我们需要赋予应用网络权限,具体权限的定义在config.json文件中,代码如下所示:
"module": {
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
"package": "com.liyuanjinglyj.jsweather",
源代码下载地址:https://gitee.com/liyuanjinglyj/JsWeather
本文正在参与“有奖征文 | HarmonyOS征文大赛”活动:
活动链接:https://marketing.csdn.net/p/ad3879b53f4b8b31db27382b5fc65bbc
以上是关于HarmonyOS实战—天气类卡片设计的主要内容,如果未能解决你的问题,请参考以下文章
我的HarmonyOS实战 — 一篇文章讲明白什么是鸿蒙2.0服务卡片