赞
踩
本篇Codelab基于栅格布局、设备管理和多端协同,实现一次开发,多端部署的分布式新闻客户端页面。主要包含以下功能:
最终效果图如下:
本篇Codelab使用了设备管理及跨设备实现多端协同能力,需要手动替换full-SDK,并在配置文件module.json5文件requestPermissions属性中添加如下权限:
鸿蒙HarmonyOS与OpenHarmony开发籽料mau123789是v直接拿
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
搭建烧录环境。
搭建开发环境。
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。
- ├──entry/src/main/ets // 代码区
- │ ├──common
- │ │ ├──constants
- │ │ │ └──CommonConstants.ets // 常量类
- │ │ └──utils
- │ │ └──Logger.ets // 日志工具类
- │ ├──entryability
- │ │ └──EntryAbility.ets // 程序入口类
- │ ├──model
- │ │ └──RemoteDeviceModel.ets // 设备管理类
- │ ├──pages
- │ │ ├──Index.ets // 新闻列表页
- │ │ └──NewsDetail.ets // 新闻详情页
- │ ├──view
- │ │ ├──DetailFooter.ets // 详情页页脚
- │ │ ├──DetailHeadContent.ets // 新闻详情
- │ │ ├──DeviceListDialog.ets // 设备列表弹窗
- │ │ ├──NewsList.ets // 新闻列表
- │ │ └──NewsTab.ets // 新闻页签
- │ └──viewmodel
- │ └──NewsDataModel.ets // 新闻数据处理
- └──entry/src/main/resources // 资源文件目录
新闻列表页由页签区域和新闻列表区域组成,页签区域为自定义布局TabBuilder,新闻列表区域为Tabs组件嵌套List组件,并适配不同尺寸设备对应的栅格。新闻列表页能够左右滑动或点击页签切换新闻Tab,并设置点击新闻跳转至新闻详情页。
- // NewsTab.ets
- @Component
- export default struct NewsTab {
- @State currentIndex: number = 0;
- @State currentBreakpoint: string = CommonConstants.BREAKPOINT_SM;
- private newsItems: NewsData[] = [];
-
- // 自定义页签栏
- @Builder TabBuilder(title: Resource, index: number) {
- Row() {
- Text(title)
- .fontSize(this.currentIndex === index ? $r('app.float.lager_font_size') : $r('app.float.middle_font_size'))
- .fontWeight(this.currentIndex === index ? CommonConstants.FONT_WEIGHT_500 : FontWeight.Normal)
- .fontColor(this.currentIndex === index ? $r('app.color.tab_font_select') : $r('app.color.font_color_gray'))
- }
- .layoutWeight(1)
- .margin({
- right: $r('app.float.news_tab_margin_right'),
- left: (this.currentBreakpoint === CommonConstants.BREAKPOINT_SM && index === 0) ?
- $r('app.float.news_tab_margin_left') : 0
- })
- .height(this.currentIndex === index ? $r('app.float.news_tab_current_height') : $r('app.float.news_tab_height'))
- }
-
- build() {
- ...
- Tabs() {
- ForEach(CommonConstants.ALL_TITLE, (title: string, index: number) => {
- TabContent() {
- // 新闻内容列表
- NewsList({ newsItems: NewsDataModel.getNewsByType(this.newsItems, title) })
- }
- .tabBar(this.TabBuilder(NewsDataModel.getTypeByStr(title), index))
- }, (title: string, index: number) => index + JSON.stringify(title))
- }
- .barHeight($r('app.float.news_tab_bar_height'))
- .barWidth(CommonConstants.FULL_COMPONENT)
- .barMode(this.currentBreakpoint === CommonConstants.BREAKPOINT_SM ? BarMode.Scrollable : BarMode.Fixed)
- .onChange((index: number) => {
- this.currentIndex = index;
- })
- ...
- }
- }
-
- // NewsList.ets
- @Component
- export default struct NewsList {
- private newsItems: NewsData[] = [];
-
- build() {
- List() {
- ForEach(this.newsItems, (item: NewsData, index: number) => {
- ListItem() {
- // 栅格布局
- GridRow({
- columns: {
- sm: CommonConstants.FOUR_COLUMN,
- md: CommonConstants.EIGHT_COLUMN,
- lg: CommonConstants.TWELVE_COLUMN
- },
- breakpoints: {
- value: [
- CommonConstants.SMALL_DEVICE_TYPE,
- CommonConstants.MIDDLE_DEVICE_TYPE,
- CommonConstants.LARGE_DEVICE_TYPE
- ]
- },
- gutter: { x: $r('app.float.grid_row_gutter') }
- }) {
- GridCol({
- span: {
- sm: CommonConstants.FOUR_COLUMN,
- md: CommonConstants.EIGHT_COLUMN,
- lg: CommonConstants.EIGHT_COLUMN
- },
- offset: {
- sm: CommonConstants.ZERO_COLUMN,
- md: CommonConstants.ZERO_COLUMN,
- lg: CommonConstants.TWO_COLUMN
- }
- }) {
- NewsItem({ newsItem: item, isLast: index === this.newsItems.length - 1 })
- }
- }
- }
- }, (item: NewsData, index: number) => index + JSON.stringify(item))
- }
- .height(CommonConstants.FULL_COMPONENT)
- }
- }
新闻详情页由新闻内容区域和页脚区域组成,其中新闻内容区域为Scroll组件嵌套栅格组件展示新闻详情,页脚区域为栅格布局,包含TextInput组件和三个按钮图标。
- // DetailHeadContent.ets
- build() {
- Column() {
- ...
- // 可滚动的容器组件
- Scroll() {
- // 栅格布局
- GridRow({
- columns: {
- sm: CommonConstants.FOUR_COLUMN,
- md: CommonConstants.EIGHT_COLUMN,
- lg: CommonConstants.TWELVE_COLUMN
- },
- breakpoints: {
- value: [
- CommonConstants.SMALL_DEVICE_TYPE,
- CommonConstants.MIDDLE_DEVICE_TYPE,
- CommonConstants.LARGE_DEVICE_TYPE
- ]
- },
- gutter: { x: $r('app.float.grid_row_gutter') }
- }) {
- GridCol({
- span: {
- sm: CommonConstants.FOUR_COLUMN,
- md: CommonConstants.EIGHT_COLUMN,
- lg: CommonConstants.EIGHT_COLUMN
- },
- offset: {
- sm: CommonConstants.ZERO_COLUMN,
- md: CommonConstants.ZERO_COLUMN,
- lg: CommonConstants.TWO_COLUMN
- }
- }) {
- ...
- }
- ...
- }
- }
- .padding({
- bottom: $r('app.float.news_detail_padding_bottom')
- })
- .scrollBar(BarState.Off)
- }
- .margin({
- left: $r('app.float.news_detail_margin'),
- right: $r('app.float.news_detail_margin')
- })
- .height(CommonConstants.FULL_COMPONENT)
- .alignItems(HorizontalAlign.Start)
- }
-
- // DetailFooter.ets
- build() {
- Column() {
- // 分割线
- Divider()
- .color($r('app.color.detail_divider_color'))
- .width(CommonConstants.FULL_COMPONENT)
-
- // 栅格布局
- GridRow({
- columns: {
- sm: CommonConstants.FOUR_COLUMN,
- md: CommonConstants.EIGHT_COLUMN,
- lg: CommonConstants.TWELVE_COLUMN
- },
- breakpoints: {
- value: [
- CommonConstants.SMALL_DEVICE_TYPE,
- CommonConstants.MIDDLE_DEVICE_TYPE,
- CommonConstants.LARGE_DEVICE_TYPE
- ]
- },
- gutter: { x: $r('app.float.grid_row_gutter') }
- }) {
- GridCol({
- span: {
- sm: CommonConstants.FOUR_COLUMN,
- md: CommonConstants.EIGHT_COLUMN,
- lg: CommonConstants.EIGHT_COLUMN
- },
- offset: {
- sm: CommonConstants.ZERO_COLUMN,
- md: CommonConstants.ZERO_COLUMN,
- lg: CommonConstants.TWO_COLUMN
- }
- }) {
- ...
- }
- .margin({
- left: this.currentBreakpoint === CommonConstants.BREAKPOINT_SM ? $r('app.float.footer_margin_sm') :
- $r('app.float.footer_margin_other'),
- right: this.currentBreakpoint === CommonConstants.BREAKPOINT_SM ? $r('app.float.footer_margin_sm') :
- $r('app.float.footer_margin_other')
- })
- }
- .backgroundColor($r('app.color.bg_color_gray'))
- .height($r('app.float.footer_height'))
- .width(CommonConstants.FULL_COMPONENT)
- .onBreakpointChange((breakpoints) => {
- ...
- })
- }
- }
页脚点击分享按钮,弹出自定义弹窗DeviceListDialog,用于多端协同拉起应用。DeviceListDialog由两个标题栏和两个List组件构成,其中List组件使用ForEach循环渲染设备数据。
- // DeviceListDialog.ets
- build() {
- Column() {
- Row() {
- ...
- }
- .height($r('app.float.choose_device_row_height'))
- .width(CommonConstants.FULL_COMPONENT)
- .padding({
- left: $r('app.float.dialog_padding'),
- right: $r('app.float.dialog_padding')
- })
-
- // 信任设备列表
- List() {
- ForEach(this.trustedDeviceList, (item: deviceManager.DeviceInfo, index: number) => {
- ListItem() {
- ...
- }
- }, (item: deviceManager.DeviceInfo) => JSON.stringify(item.deviceId))
- }
-
- Row() {
- ...
- }
- .height($r('app.float.choose_device_row_height'))
- .width(CommonConstants.FULL_COMPONENT)
- .padding({
- left: $r('app.float.dialog_padding'),
- right: $r('app.float.dialog_padding')
- })
-
- // 发现设备列表
- List() {
- ForEach(this.discoverDeviceList, (item: deviceManager.DeviceInfo, index: number) => {
- ListItem() {
- ...
- }
- }, (item: deviceManager.DeviceInfo) => JSON.stringify(item.deviceId))
- }
-
- Row() {
- ...
- }
- .height($r('app.float.dialog_button_row_height'))
- .padding({
- top: $r('app.float.dialog_button_padding_top'),
- bottom: $r('app.float.dialog_button_padding_bottom'),
- left: $r('app.float.dialog_padding'),
- right: $r('app.float.dialog_padding')
- })
- .width(CommonConstants.FULL_COMPONENT)
- }
- .borderRadius($r('app.float.dialog_border_radius'))
- .backgroundColor($r('app.color.device_dialog_background'))
- .width(CommonConstants.FULL_COMPONENT)
- }
应用创建时创建一个设备管理器实例,注册设备状态监听和获取信任的设备列表。其中deviceManager类需使用full-SDK。
- // EntryAbility.ets
- onCreate(want: Want) {
- ...
- // 创建设备管理器
- RemoteDeviceModel.createDeviceManager(this.context);
- }
-
- // RemoteDeviceModel.ets
- async createDeviceManager(context: common.UIAbilityContext): Promise<void> {
- if (this.deviceManager !== undefined) {
- return;
- }
- await new Promise((resolve: (value: Object | PromiseLike<Object>) => void, reject:
- ((reason?: RejectError) => void)) => {
- deviceManager.createDeviceManager(context.abilityInfo.bundleName, (err, value) => {
- if (err) {
- reject(err);
- logger.error('createDeviceManager failed.');
- return;
- }
- this.deviceManager = value;
- // 注册设备状态监听
- this.registerDeviceStateListener();
- // 获取信任设备列表
- this.getTrustedDeviceList();
- resolve(value);
- })
- })
- }
用户点击新闻详情页底部的分享按钮,调用startDeviceDiscovery()方法,发现周边处在同一无线网络下的设备并添加设备至已发现的设备列表。
- // RemoteDeviceModel.ets
- startDeviceDiscovery(): void {
- if (this.deviceManager === undefined) {
- logger.error('deviceManager has not initialized');
- this.showToast($r('app.string.no_device_manager'));
- return;
- }
- this.deviceManager.on('deviceFound', (data) => {
- if (data === null) {
- return;
- }
- // 监听设备发现
- this.deviceFound(data);
- })
- this.deviceManager.on('discoverFail', (data) => {
- logger.error(`discoverFail data = ${JSON.stringify(data)}`);
- })
- this.deviceManager.on('serviceDie', () => {
- logger.error('serviceDie');
- })
-
- let info: deviceManager.SubscribeInfo = {
- subscribeId: SUBSCRIBE_ID,
- mode: CommonConstants.INFO_MODE,
- medium: 0,
- freq: CommonConstants.INFO_FREQ,
- isSameAccount: false,
- isWakeRemote: true,
- capability: 0
- };
- // 添加设备至发现列表
- this.discoverList = [];
- AppStorage.setOrCreate(CommonConstants.DISCOVER_DEVICE_LIST, this.discoverList);
-
- try {
- this.deviceManager.startDeviceDiscovery(info);
- } catch (err) {
- logger.error(`startDeviceDiscovery failed error = ${JSON.stringify(err)}`);
- }
- }
在已发现的设备列表中选择设备,调用authenticateDevice()方法进行可信认证,输入PIN码,连接设备,将设备改为信任状态,添加至已信任设备列表。
- // RemoteDeviceModel.ets
- authenticateDevice(device: deviceManager.DeviceInfo, context: common.UIAbilityContext): void {
- if (this.deviceManager === undefined) {
- logger.error('deviceManager has not initialized');
- this.showToast($r('app.string.no_device_manager'));
- return;
- }
-
- for (let i: number = 0; i < this.discoverList.length; i++) {
- if (this.discoverList[i].deviceId !== device.deviceId) {
- continue;
- }
- let extraInfo: AuthExtraInfoInterface = {
- targetPkgName: context.abilityInfo.bundleName,
- appName: context.applicationInfo.name,
- appDescription: context.applicationInfo.description,
- business: CommonConstants.ZERO
- };
- let authParam: deviceManager.AuthParam = {
- 'authType': CommonConstants.ONE,
- 'extraInfo': extraInfo
- };
- try {
- // 可信认证
- this.deviceManager.authenticateDevice(device, authParam, (err) => {
- if (err) {
- logger.error(`authenticateDevice error. Code is ${err.code}, message is ${err.message}`);
- return;
- }
- })
- } catch (err) {
- logger.error(`authenticateDevice failed error = ${JSON.stringify(err)}`);
- }
- }
- }
可信认证后,用户再次点击分享按钮,选择已信任设备列表中的设备,调用startAbilityContinuation()方法进行拉起应用,在另一设备中触发aboutToAppear()方法渲染当前的新闻详情页,实现跨设备启动UIAbility。
- // DeviceListDialog.ets
- function startAbilityContinuation(deviceId: string, newsId: string, context: common.UIAbilityContext): void {
- let want: Want = {
- deviceId: deviceId,
- bundleName: context.abilityInfo.bundleName,
- abilityName: CommonConstants.ABILITY_NAME,
- parameters: {
- newsId: newsId
- }
- };
- // 拉起应用
- context.startAbility(want).catch((err: Error) => {
- Logger.error(`startAbilityContinuation failed error = ${JSON.stringify(err)}`);
- prompt.showToast({
- message: $r('app.string.start_ability_continuation_error')
- });
- })
- }
-
- // NewsDetail.ets
- aboutToAppear() {
- let newsId: string | undefined = AppStorage.get<string>('wantNewsId');
- if (newsId === undefined) {
- this.newsData = (router.getParams() as Record<string, NewsData>)['newsItem'];
- return;
- }
- // 读取跨设备传递的参数信息
- this.newsData = this.newsItems.filter((item: NewsData) => (item.newsId === newsId))[0];
- }
而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点
如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。
高清完整版请点击→《鸿蒙NEXT星河版开发学习文档》
针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细资料鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,帮助大家在技术的道路上更进一步。
《鸿蒙 (OpenHarmony)开发学习视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
获取这份鸿蒙星河版学习资料,请点击→《鸿蒙NEXT星河版开发学习文档》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
ArkTS语言
安装DevEco Studio
运用你的第一个ArkTS应用
ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
Stage模型入门
网络管理
数据管理
电话服务
分布式应用开发
通知与窗口管理
多媒体技术
安全技能
任务管理
WebGL
国际化开发
应用测试
DFX面向未来设计
鸿蒙系统移植和裁剪定制
……
《鸿蒙开发实战》
ArkTS实践
UIAbility应用
网络案例
……
获取这份鸿蒙星河版学习资料,请点击→《鸿蒙NEXT星河版开发学习文档》
鸿蒙—作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。
并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。