电子说
本示例展示一个天气应用界面,包括首页、城市管理、添加城市、更新时间弹窗,体现一次开发,多端部署的能力。
1.本示例参考一次开发,多端部署的指导,主要使用响应式布局的栅格断点系统实现在不同尺寸窗口界面上不同的显示效果。
2.使用[SideBarContainer]实现侧边栏功能。
3.使用[栅格容器组件]实现界面内容的分割和展示。
4.使用Canvas和CanvasRenderingContext2D完成空气质量和日出月落图的曲线绘制。
开发前请熟悉鸿蒙开发指导文档 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
使用说明:
1.启动应用后,首页展示已添加城市的天气信息,默认展示2个城市,左右滑动可以切换城市,在LG设备上,默认显示侧边栏,侧边栏显示时,右侧内容区占2/3,侧边栏隐藏时,内容区自动铺满界面。
2.在支持窗口自由拖拽的设备上,拖拽窗口大小,可以分别实现拖动到最大窗口侧边栏显示(点击侧边栏控制按钮可以隐藏和显示侧边栏),拖动窗口缩小到MD大小时侧边栏和侧边栏控制按钮隐藏。
3.在支持窗口自由拖拽的设备上,拖拽窗口大小,天气内容区跟随窗口大小会自动换行显示。
4.点击右上角菜单按钮,在菜单中点击 更新时间 ,弹出更新时间弹窗,没有功能,此处只做展示,在平板设备上显示2列,在小屏设备上显示一列。
5.点击右上角菜单按钮,在菜单中点击 管理城市 ,进入管理城市界面,展示已添加的城市,在平板设备上显示2列,在小屏设备上显示一列。
6.点击管理城市界面的 添加城市 ,进入添加城市界面,已添加的城市不可点击,未添加的城市点击可以添加并返回管理城市界面显示。
/code/SuperFeature/MultiDeviceAppDev/Weather/product/default
└─src
├─main
│ │
│ ├─ets
│ │ ├─Application
│ │ │ MyAbilityStage.ts //自定义ability
│ │ │
│ │ ├─common //公共资源库
│ │ ├─feature
│ │ │ AirQualityFeature.ts //空气绘画
│ │ │ SunCanvasFeature.ts //晴天绘画
│ │ │
│ │ ├─MainAbility
│ │ │ MainAbility.ts //主窗口
│ │ │
│ │ └─pages
│ │ │ AddCity.ets //添加城市
│ │ │ CityList.ets //城市列表
│ │ │ Home.ets //入口
│ │ │
│ │ └─home
│ │ AirQuality.ets //空气质量
│ │ HomeContent.ets //主页面
│ │ HoursWeather.ets //每小时天气组件
│ │ IndexEnd.ets //首页尾
│ │ IndexHeader.ets //首页头
│ │ IndexTitleBar.ets //首页标题
│ │ LifeIndex.ets //生活建议
│ │ MultidayWeather.ets //天气组件
│ │ SideContent.ets //侧边栏
│ │ SunCanvas.ets //晴天样式
│ │ UpdateTimeDialog.ets //时间更新弹窗
│ │
│ └─resources //资源包
1、home.ets中引入SideContent()和homeContent()。
2、定义showSideBar来判断是否展示侧边栏,定义mediaquery.MediaQueryListener媒体监听器smListener、mdListener、lgListener。
3、在aboutToAppear调用mediaquery对界面进行监听,[源码参考]。
/*
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mediaquery from '@ohos.mediaquery';
import HomeContent from './home/HomeContent';
import IndexTitleBar from './home/IndexTitleBar';
import SideContent from './home/SideContent';
import { CityListData, Style, getBg, getCityListWeatherData, Logger } from '@ohos/common';
const TAG: string = 'Home';
@Entry
@Component
struct Home {
@StorageLink('isRefresh') @Watch('refreshChange') isRefresh: boolean = false;
@StorageLink('swiperIndex') swiperIndex: number = 0;
@State curBp: string = 'md';
@State cityListWeatherData: CityListData[] = getCityListWeatherData();
@State popupState: boolean = false;
@State showSideBar: boolean = false;
private smListener: mediaquery.MediaQueryListener;
private mdListener: mediaquery.MediaQueryListener;
private lgListener: mediaquery.MediaQueryListener;
build() {
SideBarContainer(SideBarContainerType.Embed) {
SideContent({ showSideBar: $showSideBar })
.height('100%')
Column() {
IndexTitleBar({ showSideBar: $showSideBar })
.height(56)
Swiper() {
ForEach(this.cityListWeatherData, (item, index) = > {
HomeContent({ showSideBar: this.showSideBar, cityListData: item, index: index })
}, item = > item.city)
}
.id('swiper')
.padding({ left: Style.NORMAL_PADDING, right: Style.NORMAL_PADDING })
.indicatorStyle({
selectedColor: Color.White
})
.onChange(index = > {
this.swiperIndex = index;
AppStorage.SetOrCreate('swiperIndex', this.swiperIndex);
})
.indicator(this.curBp !== 'lg')
.index(this.swiperIndex)
.loop(false)
.width('100%')
.layoutWeight(1)
}
.height('100%')
}
.height('100%')
.sideBarWidth('33.3%')
.minSideBarWidth('33.3%')
.maxSideBarWidth('33.3%')
.showControlButton(false)
.showSideBar(this.showSideBar)
.backgroundImageSize(ImageSize.Cover)
.backgroundImage(getBg(this.cityListWeatherData[this.swiperIndex].header.weatherType))
}
aboutToAppear() {
this.smListener = mediaquery.matchMediaSync('(320vp< width<=600vp)');
this.smListener.on("change", this.isBreakpointSM);
this.mdListener = mediaquery.matchMediaSync('(600vp< width<=840vp)');
this.mdListener.on("change", this.isBreakpointMD);
this.lgListener = mediaquery.matchMediaSync('(840vp< width)');
this.lgListener.on("change", this.isBreakpointLG);
}
aboutToDisappear() {
this.smListener.off("change", this.isBreakpointSM);
this.mdListener.off("change", this.isBreakpointMD);
this.lgListener.off("change", this.isBreakpointLG);
}
isBreakpointSM = (mediaQueryResult) = > {
if (mediaQueryResult.matches) {
this.curBp = 'sm';
this.showSideBar = false;
AppStorage.SetOrCreate('curBp', this.curBp);
}
Logger.info(TAG, `this.curBp = ${this.curBp}`);
}
isBreakpointMD = (mediaQueryResult) = > {
if (mediaQueryResult.matches) {
this.curBp = 'md';
this.showSideBar = false;
AppStorage.SetOrCreate('curBp', this.curBp);
}
Logger.info(TAG, `this.curBp = ${this.curBp}`);
}
isBreakpointLG = (mediaQueryResult) = > {
if (mediaQueryResult.matches) {
if (this.curBp !== 'lg') {
this.showSideBar = true;
}
this.curBp = 'lg';
AppStorage.SetOrCreate('curBp', this.curBp);
}
Logger.info(TAG, `this.curBp = ${this.curBp}`);
}
refreshChange() {
Logger.info(TAG, `refreshChange}`);
if (this.isRefresh) {
this.cityListWeatherData = getCityListWeatherData();
AppStorage.SetOrCreate('isRefresh', false);
}
Logger.info(TAG, `refreshChange, this.cityListWeatherData.length = ${this.cityListWeatherData.length}`);
}
}
`HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿`
4、监听到当前屏幕大小,调用this.isBreakpoint断点,对curBp、showSideBar进行赋值,[源码参考]。
/*
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mediaquery from '@ohos.mediaquery';
import HomeContent from './home/HomeContent';
import IndexTitleBar from './home/IndexTitleBar';
import SideContent from './home/SideContent';
import { CityListData, Style, getBg, getCityListWeatherData, Logger } from '@ohos/common';
const TAG: string = 'Home';
@Entry
@Component
struct Home {
@StorageLink('isRefresh') @Watch('refreshChange') isRefresh: boolean = false;
@StorageLink('swiperIndex') swiperIndex: number = 0;
@State curBp: string = 'md';
@State cityListWeatherData: CityListData[] = getCityListWeatherData();
@State popupState: boolean = false;
@State showSideBar: boolean = false;
private smListener: mediaquery.MediaQueryListener;
private mdListener: mediaquery.MediaQueryListener;
private lgListener: mediaquery.MediaQueryListener;
build() {
SideBarContainer(SideBarContainerType.Embed) {
SideContent({ showSideBar: $showSideBar })
.height('100%')
Column() {
IndexTitleBar({ showSideBar: $showSideBar })
.height(56)
Swiper() {
ForEach(this.cityListWeatherData, (item, index) = > {
HomeContent({ showSideBar: this.showSideBar, cityListData: item, index: index })
}, item = > item.city)
}
.id('swiper')
.padding({ left: Style.NORMAL_PADDING, right: Style.NORMAL_PADDING })
.indicatorStyle({
selectedColor: Color.White
})
.onChange(index = > {
this.swiperIndex = index;
AppStorage.SetOrCreate('swiperIndex', this.swiperIndex);
})
.indicator(this.curBp !== 'lg')
.index(this.swiperIndex)
.loop(false)
.width('100%')
.layoutWeight(1)
}
.height('100%')
}
.height('100%')
.sideBarWidth('33.3%')
.minSideBarWidth('33.3%')
.maxSideBarWidth('33.3%')
.showControlButton(false)
.showSideBar(this.showSideBar)
.backgroundImageSize(ImageSize.Cover)
.backgroundImage(getBg(this.cityListWeatherData[this.swiperIndex].header.weatherType))
}
aboutToAppear() {
this.smListener = mediaquery.matchMediaSync('(320vp< width<=600vp)');
this.smListener.on("change", this.isBreakpointSM);
this.mdListener = mediaquery.matchMediaSync('(600vp< width<=840vp)');
this.mdListener.on("change", this.isBreakpointMD);
this.lgListener = mediaquery.matchMediaSync('(840vp< width)');
this.lgListener.on("change", this.isBreakpointLG);
}
aboutToDisappear() {
this.smListener.off("change", this.isBreakpointSM);
this.mdListener.off("change", this.isBreakpointMD);
this.lgListener.off("change", this.isBreakpointLG);
}
isBreakpointSM = (mediaQueryResult) = > {
if (mediaQueryResult.matches) {
this.curBp = 'sm';
this.showSideBar = false;
AppStorage.SetOrCreate('curBp', this.curBp);
}
Logger.info(TAG, `this.curBp = ${this.curBp}`);
}
isBreakpointMD = (mediaQueryResult) = > {
if (mediaQueryResult.matches) {
this.curBp = 'md';
this.showSideBar = false;
AppStorage.SetOrCreate('curBp', this.curBp);
}
Logger.info(TAG, `this.curBp = ${this.curBp}`);
}
isBreakpointLG = (mediaQueryResult) = > {
if (mediaQueryResult.matches) {
if (this.curBp !== 'lg') {
this.showSideBar = true;
}
this.curBp = 'lg';
AppStorage.SetOrCreate('curBp', this.curBp);
}
Logger.info(TAG, `this.curBp = ${this.curBp}`);
}
refreshChange() {
Logger.info(TAG, `refreshChange}`);
if (this.isRefresh) {
this.cityListWeatherData = getCityListWeatherData();
AppStorage.SetOrCreate('isRefresh', false);
}
Logger.info(TAG, `refreshChange, this.cityListWeatherData.length = ${this.cityListWeatherData.length}`);
}
}
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !