chendeben před 1 rokem
rodič
revize
6432df6ce0

+ 65 - 5
entry/src/main/ets/common/widget/FormLayoutManager.ets

@@ -41,6 +41,8 @@ export class FormLayoutManager {
         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:
@@ -136,6 +138,32 @@ export class FormLayoutManager {
     };
   }
 
+  /**
+   * 适配方形尺寸卡片 (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
+    };
+  }
+
   /**
    * 适配大尺寸卡片
    */
@@ -181,6 +209,8 @@ export class FormLayoutManager {
         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:
@@ -229,6 +259,13 @@ export class FormLayoutManager {
           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,
@@ -260,14 +297,17 @@ export class FormLayoutManager {
       return sizeStr as WidgetSize;
     }
     
-    // 尝试从维度字符串解析 (如 "2*1", "4*2", "4*3")
+    // 尝试从维度字符串解析 (如 "1*2", "2*4", "2*2")
     switch (sizeStr) {
-      case '2*1':
-      case '2x1':
+      case '1*2':
+      case '1x2':
         return WidgetSize.SMALL;
-      case '4*2':
-      case '4x2':
+      case '2*4':
+      case '2x4':
         return WidgetSize.MEDIUM;
+      case '2*2':
+      case '2x2':
+        return WidgetSize.SQUARE;
       case '4*3':
       case '4x3':
         return WidgetSize.LARGE;
@@ -324,6 +364,26 @@ export class FormLayoutManager {
           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 };

+ 4 - 3
entry/src/main/ets/common/widget/WidgetTypes.ets

@@ -6,9 +6,10 @@
  * 卡片尺寸枚举
  */
 export enum WidgetSize {
-  SMALL = 'small',    // 2x1
-  MEDIUM = 'medium',  // 4x2
-  LARGE = 'large'     // 4x3
+  SMALL = 'small',    // 1x2
+  MEDIUM = 'medium',  // 2x4
+  SQUARE = 'square',  // 2x2
+  LARGE = 'large'     // 4x3 (已删除)
 }
 
 /**

+ 149 - 0
entry/src/main/ets/widget/pages/PlayerWidgetSquare.ets

@@ -0,0 +1,149 @@
+import { WidgetController } from '../../common/widget/WidgetController';
+/**
+ * 方形播放器卡片 (2x2)
+ * 显示专辑封面、歌曲信息和播放按钮
+ * 参考华为官方设计,移除收藏功能
+ * 需求: 5.1, 1.4, 1.5
+ */
+
+// 定义对齐规则 - 参考华为官方代码
+const SingerAlignRules: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
+  'top': { 'anchor': 'musicTitle', 'align': VerticalAlign.Bottom },
+  'left': { 'anchor': 'musicCover', 'align': HorizontalAlign.End }
+};
+
+const CoverAlignRules: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
+  'bottom': { 'anchor': '__container__', 'align': VerticalAlign.Bottom }
+};
+
+const PlayAlignRules: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
+  'bottom': { 'anchor': '__container__', 'align': VerticalAlign.Bottom },
+  'right': { 'anchor': '__container__', 'align': HorizontalAlign.End }
+};
+
+@Entry
+@Component
+struct PlayerWidgetSquare {
+  // 卡片数据属性 - 使用LocalStorageProp与FormExtensionAbility通信
+  @LocalStorageProp('isPlaying') isPlaying: boolean = false;
+  @LocalStorageProp('songTitle') songTitle: string = 'Dream It Possible';
+  @LocalStorageProp('songArtist') songArtist: string = 'Delacey';
+  @LocalStorageProp('coverImage') coverImage: string = '';
+  @LocalStorageProp('isLoading') isLoading: boolean = false;
+  @LocalStorageProp('imageColorHex') imageColorHex: string = '2A2A2A';
+
+  /**
+   * 格式化歌曲标题显示
+   */
+  private getDisplayTitle(): string {
+    if (!this.songTitle || this.songTitle.trim() === '') {
+      return '暂无播放';
+    }
+    return this.songTitle;
+  }
+
+  /**
+   * 格式化艺术家显示
+   */
+  private getDisplayArtist(): string {
+    if (!this.songArtist || this.songArtist.trim() === '') {
+      return '未知艺术家';
+    }
+    return this.songArtist;
+  }
+
+  /**
+   * 获取专辑封面
+   */
+  private getCoverImage(): Resource | string {
+    console.info(`Heanup PlayerWidgetSquare: getCoverImage called, coverImage='${this.coverImage}'`);
+    // 如果有封面图片,使用封面图片,否则使用默认图片
+    if (this.coverImage && this.coverImage.trim() !== '') {
+      console.info(`Heanup PlayerWidgetSquare: Using actual cover image: ${this.coverImage}`);
+      return this.coverImage; // 直接返回文件路径
+    }
+    console.info(`Heanup PlayerWidgetSquare: Using default cover image`);
+    return $r('app.media.ic_avatar4'); // 使用默认专辑封面
+  }
+
+  build() {
+    RelativeContainer() {
+      // 歌曲标题 - 参考华为官方样式
+      Text(this.getDisplayTitle())
+        .fontSize(14)
+        .fontWeight(700)
+        .width('85%')
+        .fontColor(Color.White)
+        .textOverflow({ overflow: TextOverflow.Ellipsis })
+        .maxLines(1)
+        .id('musicTitle')
+
+      // 艺术家名称 - 参考华为官方样式
+      Text(this.getDisplayArtist())
+        .fontSize(12)
+        .fontColor('#CCFFFFFF')
+        .fontWeight(500)
+        .maxLines(1)
+        .alignRules(SingerAlignRules)
+        .margin({ top: 2 })
+        .id('singerText')
+
+      // 专辑封面 - 参考华为官方黑胶唱片设计
+      Stack({ alignContent: Alignment.Center }) {
+        Image($r('app.media.ic_music_bg_mini'))
+          .height(88)
+          .width(88)
+        
+        Button()
+          .backgroundImage(this.getCoverImage())
+          .backgroundImageSize(ImageSize.Cover)
+          .height(58)
+          .width(58)
+          .borderRadius(29)
+      }
+      .alignRules(CoverAlignRules)
+      .id('musicCover')
+      .onClick(() => {
+        console.info('Heanup PlayerWidgetSquare: Album cover clicked');
+        postCardAction(this, {
+          'action': 'router',
+          'abilityName': 'EntryAbility'
+        });
+      })
+
+      // 播放按钮 - 参考华为官方样式
+      SymbolGlyph(this.isPlaying ? $r('sys.symbol.pause_round_triangle_fill') : $r('sys.symbol.play_round_triangle_fill'))
+        .fontSize(36)
+        .symbolEffect(new ReplaceSymbolEffect(EffectScope.WHOLE), true)
+        .fontColor(['#E5FFFFFF'])
+        .alignRules(PlayAlignRules)
+        .enabled(!this.isLoading)
+        .onClick(() => {
+          console.info('Heanup PlayerWidgetSquare: Play/Pause button clicked');
+          if (!this.isLoading) {
+            postCardAction(this, {
+              'action': 'message',
+              'params': {
+                "func":"play_pause"
+              }
+            });
+          }
+        })
+    }
+    .height('100%')
+    .width('100%')
+    .linearGradient({
+      direction: GradientDirection.Bottom,
+      repeating: false,
+      colors: [[`#ff${this.imageColorHex}`, 0.0], [`#ff${this.imageColorHex}`, 0.5], [`#ff${this.imageColorHex}`, 1.0]]
+    })
+    .padding(12)
+    .onClick(() => {
+      console.info('Heanup PlayerWidgetSquare: Container clicked, jumping to main app');
+      postCardAction(this, {
+        'action': 'router',
+        'abilityName': 'EntryAbility'
+      });
+    })
+  }
+}

+ 19 - 0
entry/src/main/resources/base/profile/form_config.json

@@ -37,6 +37,25 @@
       "supportDimensions": [
         "2*4"
       ]
+    },
+    {
+      "name": "PlayerWidgetSquare",
+      "description": "方形播放器卡片",
+      "src": "./ets/widget/pages/PlayerWidgetSquare.ets",
+      "uiSyntax": "arkts",
+      "window": {
+        "designWidth": 720,
+        "autoDesignWidth": true
+      },
+      "colorMode": "auto",
+      "isDefault": false,
+      "updateEnabled": true,
+      "scheduledUpdateTime": "10:30",
+      "updateDuration": 1,
+      "defaultDimension": "2*2",
+      "supportDimensions": [
+        "2*2"
+      ]
     }
   ]
 }