前言
本文将深入解析华为开发者联盟 CodeLabs 上的优质一多开发示例项目——MultiShopping。该项目展示了鸿蒙应用开发中的最佳实践,特别是在响应式布局和工程级一多架构方面的实现。项目地址:developer.huawei.com/consumer/cn…
在开发跨设备应用时,响应式布局是确保应用在不同尺寸设备上都能提供良好用户体验的关键。MultiShopping 项目中实现了一套优雅的断点系统(Breakpoint System),用于检测设备屏幕尺寸并自动调整 UI 布局。
断点系统的核心代码位于common/src/main/ets/utils/BreakpointSystem.ets
文件中,主要包含两个关键类:
该类负责监听设备屏幕尺寸变化,并将当前断点信息存储到 AppStorage 中:
export class BreakpointSystem {
private currentBreakpoint: string = "";
private smListener?: mediaquery.MediaQueryListener;
private mdListener?: mediaquery.MediaQueryListener;
private lgListener?: mediaquery.MediaQueryListener;
private updateCurrentBreakpoint(breakpoint: string) {
if (this.currentBreakpoint !== breakpoint) {
this.currentBreakpoint = breakpoint;
AppStorage.set<string>(
BreakpointConstants.CURRENT_BREAKPOINT,
this.currentBreakpoint
);
}
}
public register() {
this.smListener = mediaquery.matchMediaSync(BreakpointConstants.RANGE_SM);
this.smListener.on("change", this.isBreakpointSM);
this.mdListener = mediaquery.matchMediaSync(BreakpointConstants.RANGE_MD);
this.mdListener.on("change", this.isBreakpointMD);
this.lgListener = mediaquery.matchMediaSync(BreakpointConstants.RANGE_LG);
this.lgListener.on("change", this.isBreakpointLG);
}
public unregister() {
this.smListener?.off("change", this.isBreakpointSM);
this.mdListener?.off("change", this.isBreakpointMD);
this.lgListener?.off("change", this.isBreakpointLG);
}
}
该类提供了一种便捷的方式,根据当前断点类型返回对应的 UI 配置值:
export class BreakPointType<T> {
options: BreakPointTypeOption<T>;
constructor(option: BreakPointTypeOption<T>) {
this.options = option;
}
getValue(currentBreakPoint: string): T {
if (this.options.sm !== undefined && currentBreakPoint === "sm") {
return this.options.sm as T;
}
if (this.options.md && currentBreakPoint === "md") {
return this.options.md as T;
} else {
return this.options.lg as T;
}
}
}
断点系统使用的常量定义在common/src/main/ets/constants/BreakpointConstants.ets
文件中:
export class BreakpointConstants {
/**
* 表示小型设备的断点
*/
static readonly BREAKPOINT_SM: string = "sm";
/**
* 表示中型设备的断点
*/
static readonly BREAKPOINT_MD: string = "md";
/**
* 表示大型设备的断点
*/
static readonly BREAKPOINT_LG: string = "lg";
/**
* 当前断点,用于查询设备类型
*/
static readonly CURRENT_BREAKPOINT: string = "currentBreakpoint";
/**
* 小型设备宽度范围
*/
static readonly RANGE_SM: string = "(320vp<=width<520vp)";
/**
* 中型设备宽度范围
*/
static readonly RANGE_MD: string = "(520vp<=width<840vp)";
/**
* 大型设备宽度范围
*/
static readonly RANGE_LG: string = "(840vp<=width)";
}
"(320vp<=width<520vp)"
表示屏幕宽度在 320vp 到 520vp 之间MediaQueryListener
对象,可用于监听媒体查询条件的变化window.matchMedia()
类似,但针对鸿蒙系统优化MediaQueryResult
对象,其中matches
属性表示当前是否匹配查询条件"currentBreakpoint"
作为键,确保全应用范围内可访问@StorageProp('currentBreakpoint')
的组件都会自动更新初始化与注册: 在应用启动时(通常在入口页面的aboutToAppear
生命周期函数中)初始化并注册断点系统:
// SplashPage.ets
@Entry
@Component
struct SplashPage {
@StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm';
private breakpointSystem = new BreakpointSystem();
aboutToAppear() {
this.breakpointSystem.register();
// ...其他代码
}
aboutToDisappear() {
this.breakpointSystem.unregister();
// ...其他代码
}
}
在组件中使用断点信息: 组件可以通过@StorageProp
装饰器访问当前断点信息:
@Component
struct MyComponent {
@StorageProp('currentBreakpoint') currentBreakpoint: string = 'md';
// ...组件代码
}
根据断点调整 UI: 使用BreakPointType
类根据当前断点返回对应的 UI 配置:
Image($r("app.media.ic_eshop")).width(
new BreakPointType({
sm: $r("app.float.splash_image_size"),
md: $r("app.float.splash_image_size"),
lg: $r("app.float.splash_image_size_lg"),
}).getValue(this.currentBreakpoint)
);
MultiShopping 项目采用了鸿蒙应用开发中常见的三层架构模式,实现了工程级的一多开发能力。
项目架构分为三层:
common/
目录features/
目录,包含多个子目录如home/
、personal/
等product/
目录,目前包含phone/
子目录MultiShopping/
├── common/ # 公共能力层
│ ├── src/main/ets/
│ │ ├── components/ # 公共UI组件
│ │ ├── constants/ # 公共常量定义
│ │ ├── utils/ # 公共工具类
│ │ └── viewmodel/ # 公共数据模型
│ └── ...
├── features/ # 基础特性层
│ ├── home/ # 首页功能模块
│ ├── personal/ # 个人中心功能模块
│ ├── shopcart/ # 购物车功能模块
│ ├── commoditydetail/ # 商品详情功能模块
│ └── ...
└── product/ # 产品定制层
└── phone/ # 手机产品
├── src/main/ets/
│ ├── pages/ # 页面定义
│ ├── entryability/ # 应用入口
│ └── ...
└── ...
oh-package.json5
文件管理模块间依赖MultiShopping 项目通过断点系统实现了优雅的响应式布局,通过三层架构实现了工程级的一多开发能力。这些设计不仅提高了开发效率,也确保了应用在不同设备上的一致性和良好体验。
对于鸿蒙应用开发者而言,这些设计模式和实践经验具有很高的参考价值,可以帮助开发者构建高质量的跨设备应用。通过学习和借鉴 MultiShopping 项目的实现,开发者可以更好地掌握鸿蒙应用开发的最佳实践。