| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- 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}`);
- 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.LARGE:
- return this.adaptForLargeWidget(baseData, widgetData);
- default:
- hilog.warn(0x0000, TAG, `Unknown widget size: ${size}, using medium as default`);
- return this.adaptForMediumWidget(baseData, widgetData);
- }
- }
- /**
- * 获取卡片尺寸对应的页面路径
- * @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.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:
- const smallConfig: WidgetConfig = {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: false,
- showCover: false
- };
- return smallConfig;
- case WidgetSize.MEDIUM:
- const mediumConfig: WidgetConfig = {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: true,
- showCover: false
- };
- return mediumConfig;
- case WidgetSize.LARGE:
- const largeConfig: WidgetConfig = {
- size: baseConfig.size,
- theme: baseConfig.theme,
- showProgress: true,
- showCover: true
- };
- return largeConfig;
- 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;
- }
-
- // 尝试从维度字符串解析 (如 "2*1", "4*2", "4*3")
- switch (sizeStr) {
- case '2*1':
- case '2x1':
- return WidgetSize.SMALL;
- case '4*2':
- case '4x2':
- return WidgetSize.MEDIUM;
- 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.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);
- }
- }
- /**
- * 格式化基础数据
- */
- private formatBaseData(widgetData: WidgetData): FormattedWidgetData {
- return {
- isPlaying: widgetData.playState.isPlaying,
- isPaused: widgetData.playState.isPaused,
- isLoading: widgetData.playState.isLoading,
- songTitle: widgetData.currentSong.title || '暂无播放',
- songArtist: widgetData.currentSong.artist || '未知艺术家',
- songAlbum: widgetData.currentSong.album || '未知专辑',
- coverImage: widgetData.currentSong.coverImagePath || '',
- currentTime: widgetData.progress.currentTimeText || '00:00',
- totalTime: widgetData.progress.totalTimeText || '00:00',
- progressPercentage: widgetData.progress.percentage || 0,
- hasNext: widgetData.playlist.hasNext,
- hasPrevious: widgetData.playlist.hasPrevious,
- showProgress: widgetData.config.showProgress,
- showCover: widgetData.config.showCover,
- widgetSize: widgetData.config.size.toString(),
- timestamp: Date.now()
- };
- }
- /**
- * 适配小尺寸卡片数据
- */
- private adaptForSmallWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- const result: FormattedWidgetData = {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(baseData.songTitle, 20), // 小卡片只显示歌曲标题,如果标题过长则截断
- songArtist: baseData.songArtist,
- 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: WidgetSize.SMALL,
- timestamp: baseData.timestamp
- };
- return result;
- }
- /**
- * 适配中等尺寸卡片数据
- */
- private adaptForMediumWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- const result: FormattedWidgetData = {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(baseData.songTitle, 30), // 中等卡片显示更多信息,但仍需要适当截断
- songArtist: this.truncateText(baseData.songArtist, 25),
- songAlbum: this.truncateText(baseData.songAlbum, 25),
- coverImage: baseData.coverImage,
- currentTime: baseData.currentTime,
- totalTime: baseData.totalTime,
- progressPercentage: baseData.progressPercentage,
- hasNext: baseData.hasNext,
- hasPrevious: baseData.hasPrevious,
- showProgress: true,
- showCover: false,
- widgetSize: WidgetSize.MEDIUM,
- timestamp: baseData.timestamp
- };
- return result;
- }
- /**
- * 适配大尺寸卡片数据
- */
- private adaptForLargeWidget(baseData: FormattedWidgetData, widgetData: WidgetData): FormattedWidgetData {
- const result: FormattedWidgetData = {
- isPlaying: baseData.isPlaying,
- isPaused: baseData.isPaused,
- isLoading: baseData.isLoading,
- songTitle: this.truncateText(baseData.songTitle, 40), // 大卡片可以显示完整信息
- songArtist: this.truncateText(baseData.songArtist, 35),
- songAlbum: this.truncateText(baseData.songAlbum, 35),
- coverImage: baseData.coverImage,
- currentTime: baseData.currentTime,
- totalTime: baseData.totalTime,
- progressPercentage: baseData.progressPercentage,
- hasNext: baseData.hasNext,
- hasPrevious: baseData.hasPrevious,
- showProgress: true,
- showCover: true,
- widgetSize: WidgetSize.LARGE,
- timestamp: baseData.timestamp
- };
- return result;
- }
- /**
- * 截断文本
- */
- private truncateText(text: string, maxLength: number): string {
- if (!text || text.length <= maxLength) {
- return text;
- }
- return text.substring(0, maxLength - 3) + '...';
- }
- }
|