以下为 HarmonyOS 5一稿适配多端的设计规范与ArkTS实现方案,包含布局适配、交互统一和性能优化的完整代码示例:
1. 多端设计核心原则
2. 基础适配方案
2.1 设备能力检测
// device-adapt.ets
import { Device } from '@ohos.device';
export function getDeviceType() {
return Device.type; // phone | watch | tv | car
}
export function useResponsiveValue<T>(values: {
phone: T,
watch: T,
tv: T
}): T {
const type = getDeviceType();
return values[type] || values.phone;
}
2.2 通用组件基类
// base-component.ets
@Component
struct AdaptiveComponent {
@State deviceClass: 'small' | 'medium' | 'large' = 'medium';
aboutToAppear() {
this.deviceClass = Device.screenClass(); // 根据屏幕尺寸分类
}
@Builder
adaptiveContent() {
// 由子类实现
}
build() {
Column() {
this.adaptiveContent()
}
.padding(this.deviceClass === 'small' ? 10 : 20)
}
}
3. 布局响应式方案
3.1 网格系统
// responsive-grid.ets
@Component
struct SmartGrid {
@Prop items: any[];
@State columns: number = 2;
aboutToAppear() {
this.columns = useResponsiveValue({
phone: 2,
watch: 1,
tv: 4
});
}
build() {
Grid() {
ForEach(this.items, (item) => {
GridItem() {
ItemComponent(item)
}
.span(this.columns > 2 ? 1 : 2)
})
}
.columnsTemplate(Array(this.columns).fill('1fr').join(' '))
}
}
3.2 弹性间距
// spacing-system.ets
export function getSpacing(level: number) {
const base = useResponsiveValue({
phone: 8,
watch: 4,
tv: 16
});
return level * base;
}
4. 交互统一方案
4.1 跨端手势归一
// gesture-adapter.ets
export function registerGesture(component: Component, type: 'tap' | 'swipe') {
switch (type) {
case 'tap':
component.onClick(() => handleInteraction());
break;
case 'swipe':
if (getDeviceType() === 'watch') {
component.onRotaryEvent(() => handleInteraction());
} else {
component.onSwipe(() => handleInteraction());
}
break;
}
}
4.2 焦点控制(TV适配)
// focus-manager.ets
@Component
struct FocusableComponent {
@State focused: boolean = false;
build() {
Column()
.border(this.focused ? '2px solid #FFF' : 'none')
.onKeyEvent((e) => {
if (e.key === 'DPAD_CENTER') {
this.focused = !this.focused;
}
})
}
}
5. 资源弹性管理
5.1 多端资源目录
resources/
├── base/
│ ├── media/ # 通用资源
├── phone/
│ ├── media/ # 手机专属
├── watch/
│ ├── media/ # 手表专属
└── tv/
├── media/ # 智慧屏专属
5.2 动态资源加载
// asset-loader.ets
export function loadAdaptiveImage(name: string) {
const device = getDeviceType();
try {
return $r(`app.media.${device}_${name}`);
} catch {
return $r(`app.media.base_${name}`);
}
}
6. 典型组件实现
6.1 自适应按钮
// adaptive-button.ets
@Component
struct SmartButton extends AdaptiveComponent {
@Builder
adaptiveContent() {
const padding = getSpacing(2);
const fontSize = useResponsiveValue({
phone: 16,
watch: 12,
tv: 20
});
Button('确认')
.fontSize(fontSize)
.padding(padding)
.width(this.deviceClass === 'small' ? '100%' : 'auto')
}
}
6.2 多端导航栏
// nav-bar.ets
@Component
struct AdaptiveNav {
@State tabs: string[] = ['首页', '发现', '我的'];
build() {
if (getDeviceType() === 'watch') {
RotaryNav(this.tabs)
} else {
TabBar({
tabs: this.tabs,
direction: getDeviceType() === 'tv' ? 'vertical' : 'horizontal'
})
}
}
}
7. 性能优化方案
7.1 按需加载组件
// lazy-load.ets
export function lazyComponent(name: string) {
return lazy(() => {
switch (getDeviceType()) {
case 'watch': return import('./watch/' + name);
case 'tv': return import('./tv/' + name);
default: return import('./phone/' + name);
}
});
}
7.2 设备专属打包
// build-profile.json
{
"targets": {
"phone": {
"includes": ["src/phone/**"]
},
"watch": {
"includes": ["src/watch/**"]
}
}
}
8. 设计规范速查表
| 维度 | 手机 | 手表 | 智慧屏 |
|---|---|---|---|
| 字体基准 | 16sp | 12sp | 24sp |
| 栅格列数 | 4 | 1 | 8 |
| 交互热区 | 48dp×48dp | 36dp×36dp | 60dp×60dp |
| 动效时长 | 300ms | 200ms | 400ms |
9. 完整适配示例
9.1 商品卡片组件
// product-card.ets
@Component
struct ProductCard extends AdaptiveComponent {
@Prop product: Product;
@Builder
adaptiveContent() {
const imgSize = useResponsiveValue({
phone: 120,
watch: 80,
tv: 200
});
Column() {
Image(this.product.image)
.width(imgSize)
.height(imgSize)
if (this.deviceClass !== 'small') {
Text(this.product.desc)
.maxLines(this.deviceClass === 'large' ? 3 : 1)
}
}
}
}
9.2 设置页面适配
// settings-page.ets
@Entry
@Component
struct SettingsPage {
build() {
const isWatch = getDeviceType() === 'watch';
if (isWatch) {
RotarySettings()
} else {
Scroll() {
SettingsList()
if (getDeviceType() === 'tv') {
TvSidebar()
}
}
}
}
}
10. 调试工具
10.1 多端预览器
// device-preview.ets
@Component
struct MultiPreview {
@State devices: DeviceMock[] = [
{ type: 'phone', width: 1080 },
{ type: 'watch', width: 454 },
{ type: 'tv', width: 3840 }
];
build() {
Row() {
ForEach(this.devices, (device) => {
DeviceFrame(device) {
PreviewContent() // 待预览组件
}
})
}
}
}
10.2 样式检查器
// style-inspector.ets
export function checkStyleViolations() {
const rules = {
fontSize: {
min: 12,
max: 24
},
contrastRatio: {
min: 4.5
}
};
return StyleValidator.validate(rules);
}
11. 项目结构规范
multi-device-app/
├── src/
│ ├── common/ # 通用组件
│ ├── phone/ # 手机增强
│ ├── watch/ # 手表适配
│ └── tv/ # 智慧屏专有
├── resources/
│ ├── base/ # 基础资源
│ ├── phone/ # 手机资源
│ └── watch/ # 手表资源
└── test/
├── device-mocks/ # 设备模拟
└── a11y/ # 无障碍测试
通过本方案可实现:
- 90%+ 代码复用率
- 像素级 多端适配
- 一致 的交互体验
- 高效 的团队协作