| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- import { WidgetSize, WidgetData, FormattedWidgetData, WidgetConfig, ContainerPadding, ButtonSize, FontSizeConfig, SpacingConfig, ShowElementsConfig, ResponsiveLayoutParams } from './WidgetTypes';
- import hilog from '@ohos.hilog';
- const TAG = 'FormLayoutManager';
- /**
- * 卡片布局管理器
- * 负责处理多尺寸卡片的布局适配和UI重构
- * 需求: 5.4, 5.5
- */
- export class FormLayoutManager {
- private static instance: FormLayoutManager;
- /**
- * 获取单例实例
- */
- public static getInstance(): FormLayoutManager {
- if (!FormLayoutManager.instance) {
- FormLayoutManager.instance = new FormLayoutManager();
- }
- return FormLayoutManager.instance;
- }
- private constructor() {
- hilog.info(0x0000, TAG, 'FormLayoutManager initialized');
- }
- /**
- * 根据卡片尺寸适配数据
- * @param widgetData 原始卡片数据
- * @param size 卡片尺寸
- * @returns 适配后的格式化数据
- */
- public adaptDataForSize(widgetData: WidgetData, size: WidgetSize): FormattedWidgetData {
- hilog.info(0x0000, TAG, `Adapting data for size: ${size}, coverImagePath: ${widgetData.currentSong.coverImagePath}`);
- const baseData = this.formatBaseData(widgetData);
-
- switch (size) {
- case WidgetSize.SMALL:
- return this.adaptForSmallWidget(baseData, widgetData);
- case WidgetSize.MEDIUM:
- return this.adaptForMediumWidget(baseData, widgetData);
- case WidgetSize.SQUARE:
- return this.adaptForSquareWidget(baseData, widgetData);
- case WidgetSize.LARGE:
- return this.adaptForLargeWidget(baseData, widgetData);
- default:
- hilog.warn(0x0000, TAG, `Unknown widget size: ${size}, using medium as default`);
- return this.adaptForMediumWidget(baseData, widgetData);
- }
- }
- /**
- * 格式化基础数据
- */
- private formatBaseData(data: WidgetData): FormattedWidgetData {
- hilog.info(0x0000, TAG, `Formatting base data: coverImagePath=${data.currentSong.coverImagePath}`);
-
- return {
- // 播放状态
- isPlaying: data.playState.isPlaying,
- isPaused: data.playState.isPaused,
- isLoading: data.playState.isLoading,
-
- // 歌曲信息
- songTitle: this.truncateText(data.currentSong.title, 30),
- songArtist: this.truncateText(data.currentSong.artist, 20),
- songAlbum: this.truncateText(data.currentSong.album, 20),
- coverImage: data.currentSong.coverImagePath || '',
-
- // 播放进度
- currentTime: data.progress.currentTimeText,
- totalTime: data.progress.totalTimeText,
- progressPercentage: data.progress.percentage,
-
- // 控制按钮状态
- hasNext: data.playlist.hasNext,
- hasPrevious: data.playlist.hasPrevious,
-
- // 卡片配置
- showProgress: data.config.showProgress,
- showCover: data.config.showCover,
- widgetSize: data.config.size as string,
-
- // 时间戳用于强制更新
- timestamp: Date.now()
- };
- }
- /**
- * 适配小尺寸卡片
- */
- private adaptForSmallWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- return {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(widgetData.currentSong.title, 15),
- songArtist: this.truncateText(widgetData.currentSong.artist, 12),
- songAlbum: baseData.songAlbum,
- coverImage: baseData.coverImage,
- currentTime: baseData.currentTime,
- totalTime: baseData.totalTime,
- progressPercentage: baseData.progressPercentage,
- hasNext: baseData.hasNext,
- hasPrevious: baseData.hasPrevious,
- showProgress: false,
- showCover: false,
- widgetSize: baseData.widgetSize,
- timestamp: baseData.timestamp
- };
- }
- /**
- * 适配中等尺寸卡片
- */
- private adaptForMediumWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- hilog.info(0x0000, TAG, `Adapting for medium widget: coverImage=${baseData.coverImage}`);
-
- return {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(widgetData.currentSong.title, 25),
- songArtist: this.truncateText(widgetData.currentSong.artist, 18),
- songAlbum: baseData.songAlbum,
- coverImage: widgetData.currentSong.coverImagePath || '', // 确保coverImage被正确传递
- currentTime: baseData.currentTime,
- totalTime: baseData.totalTime,
- progressPercentage: baseData.progressPercentage,
- hasNext: baseData.hasNext,
- hasPrevious: baseData.hasPrevious,
- showProgress: false,
- showCover: true,
- widgetSize: baseData.widgetSize,
- timestamp: baseData.timestamp
- };
- }
- /**
- * 适配方形尺寸卡片 (2x2)
- */
- private adaptForSquareWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- hilog.info(0x0000, TAG, `Adapting for square widget: coverImage=${baseData.coverImage}`);
-
- return {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(widgetData.currentSong.title, 20),
- songArtist: this.truncateText(widgetData.currentSong.artist, 15),
- songAlbum: baseData.songAlbum,
- coverImage: widgetData.currentSong.coverImagePath || '', // 确保coverImage被正确传递
- currentTime: baseData.currentTime,
- totalTime: baseData.totalTime,
- progressPercentage: baseData.progressPercentage,
- hasNext: baseData.hasNext,
- hasPrevious: baseData.hasPrevious,
- showProgress: false,
- showCover: true,
- widgetSize: baseData.widgetSize,
- timestamp: baseData.timestamp
- };
- }
- /**
- * 适配大尺寸卡片
- */
- private adaptForLargeWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- return {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(widgetData.currentSong.title, 35),
- songArtist: this.truncateText(widgetData.currentSong.artist, 25),
- songAlbum: baseData.songAlbum,
- coverImage: baseData.coverImage,
- currentTime: baseData.currentTime,
- totalTime: baseData.totalTime,
- progressPercentage: baseData.progressPercentage,
- hasNext: baseData.hasNext,
- hasPrevious: baseData.hasPrevious,
- showProgress: true,
- showCover: true,
- widgetSize: baseData.widgetSize,
- timestamp: baseData.timestamp
- };
- }
- /**
- * 截断文本
- */
- private truncateText(text: string, maxLength: number): string {
- if (!text || text.length <= maxLength) {
- return text || '';
- }
- return text.substring(0, maxLength - 1) + '…';
- }
- /**
- * 获取卡片尺寸对应的页面路径
- * @param size 卡片尺寸
- * @returns 页面路径
- */
- public getWidgetPagePath(size: WidgetSize): string {
- switch (size) {
- case WidgetSize.SMALL:
- return 'widget/pages/PlayerWidgetSmall';
- case WidgetSize.MEDIUM:
- return 'widget/pages/PlayerWidgetMedium';
- case WidgetSize.SQUARE:
- return 'widget/pages/PlayerWidgetSquare';
- case WidgetSize.LARGE:
- return 'widget/pages/PlayerWidgetLarge';
- default:
- hilog.warn(0x0000, TAG, `Unknown widget size: ${size}, using medium as default`);
- return 'widget/pages/PlayerWidgetMedium';
- }
- }
- /**
- * 检查尺寸变化并返回是否需要重构UI
- * @param oldSize 旧尺寸
- * @param newSize 新尺寸
- * @returns 是否需要重构UI
- */
- public shouldRebuildUI(oldSize: WidgetSize, newSize: WidgetSize): boolean {
- const needsRebuild = oldSize !== newSize;
- hilog.info(0x0000, TAG, `Size change from ${oldSize} to ${newSize}, needs rebuild: ${needsRebuild}`);
- return needsRebuild;
- }
- /**
- * 获取卡片尺寸的显示配置
- * @param size 卡片尺寸
- * @returns 显示配置
- */
- public getSizeDisplayConfig(size: WidgetSize): WidgetConfig {
- const baseConfig: WidgetConfig = {
- size: size,
- theme: 'auto',
- showProgress: true,
- showCover: true
- };
- switch (size) {
- case WidgetSize.SMALL:
- return {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: false,
- showCover: false
- };
- case WidgetSize.MEDIUM:
- return {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: false,
- showCover: true
- };
- case WidgetSize.SQUARE:
- return {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: false,
- showCover: true
- };
- case WidgetSize.LARGE:
- return {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: true,
- showCover: true
- };
- default:
- return baseConfig;
- }
- }
- /**
- * 验证卡片尺寸是否有效
- * @param size 卡片尺寸
- * @returns 是否有效
- */
- public isValidSize(size: string): boolean {
- return Object.values(WidgetSize).includes(size as WidgetSize);
- }
- /**
- * 从字符串解析卡片尺寸
- * @param sizeStr 尺寸字符串
- * @returns 卡片尺寸枚举
- */
- public parseSizeFromString(sizeStr: string): WidgetSize {
- if (this.isValidSize(sizeStr)) {
- return sizeStr as WidgetSize;
- }
-
- // 尝试从维度字符串解析 (如 "1*2", "2*4", "2*2")
- switch (sizeStr) {
- case '1*2':
- case '1x2':
- return WidgetSize.SMALL;
- case '2*4':
- case '2x4':
- return WidgetSize.MEDIUM;
- case '2*2':
- case '2x2':
- return WidgetSize.SQUARE;
- case '4*3':
- case '4x3':
- return WidgetSize.LARGE;
- default:
- hilog.warn(0x0000, TAG, `Unknown size string: ${sizeStr}, using medium as default`);
- return WidgetSize.MEDIUM;
- }
- }
- /**
- * 获取响应式布局参数
- * @param size 卡片尺寸
- * @returns 布局参数
- */
- public getResponsiveLayoutParams(size: WidgetSize): ResponsiveLayoutParams {
- switch (size) {
- case WidgetSize.SMALL:
- const smallPadding: ContainerPadding = { left: 16, right: 16, top: 8, bottom: 8 };
- const smallButtonSize: ButtonSize = { width: 32, height: 32 };
- const smallPlayButtonSize: ButtonSize = { width: 36, height: 36 };
- const smallFontSize: FontSizeConfig = { title: 14, artist: 12, time: 10 };
- const smallSpacing: SpacingConfig = { horizontal: 8, vertical: 4 };
- const smallShowElements: ShowElementsConfig = {
- progress: false,
- cover: false,
- album: false,
- time: false
- };
- return {
- containerPadding: smallPadding,
- buttonSize: smallButtonSize,
- playButtonSize: smallPlayButtonSize,
- fontSize: smallFontSize,
- spacing: smallSpacing,
- showElements: smallShowElements
- };
- case WidgetSize.MEDIUM:
- const mediumPadding: ContainerPadding = { left: 16, right: 16, top: 16, bottom: 16 };
- const mediumButtonSize: ButtonSize = { width: 36, height: 36 };
- const mediumPlayButtonSize: ButtonSize = { width: 44, height: 44 };
- const mediumFontSize: FontSizeConfig = { title: 16, artist: 12, time: 10 };
- const mediumSpacing: SpacingConfig = { horizontal: 12, vertical: 8 };
- const mediumShowElements: ShowElementsConfig = {
- progress: true,
- cover: false,
- album: true,
- time: true
- };
- return {
- containerPadding: mediumPadding,
- buttonSize: mediumButtonSize,
- playButtonSize: mediumPlayButtonSize,
- fontSize: mediumFontSize,
- spacing: mediumSpacing,
- showElements: mediumShowElements
- };
- case WidgetSize.SQUARE:
- const squarePadding: ContainerPadding = { left: 16, right: 16, top: 16, bottom: 16 };
- const squareButtonSize: ButtonSize = { width: 40, height: 40 };
- const squarePlayButtonSize: ButtonSize = { width: 56, height: 56 };
- const squareFontSize: FontSizeConfig = { title: 18, artist: 14, time: 12 };
- const squareSpacing: SpacingConfig = { horizontal: 16, vertical: 12 };
- const squareShowElements: ShowElementsConfig = {
- progress: false,
- cover: true,
- album: false,
- time: false
- };
- return {
- containerPadding: squarePadding,
- buttonSize: squareButtonSize,
- playButtonSize: squarePlayButtonSize,
- fontSize: squareFontSize,
- spacing: squareSpacing,
- showElements: squareShowElements
- };
- case WidgetSize.LARGE:
- const largePadding: ContainerPadding = { left: 16, right: 16, top: 16, bottom: 16 };
- const largeButtonSize: ButtonSize = { width: 40, height: 40 };
- const largePlayButtonSize: ButtonSize = { width: 52, height: 52 };
- const largeFontSize: FontSizeConfig = { title: 16, artist: 13, time: 11 };
- const largeSpacing: SpacingConfig = { horizontal: 16, vertical: 16 };
- const largeShowElements: ShowElementsConfig = {
- progress: true,
- cover: true,
- album: true,
- time: true
- };
- return {
- containerPadding: largePadding,
- buttonSize: largeButtonSize,
- playButtonSize: largePlayButtonSize,
- fontSize: largeFontSize,
- spacing: largeSpacing,
- showElements: largeShowElements
- };
- default:
- return this.getResponsiveLayoutParams(WidgetSize.MEDIUM);
- }
- }
- }
|