Parcourir la source

优化横屏的样式功能
播放页单行歌词的配置功能

onecold il y a 1 an
Parent
commit
87fab90899

+ 8 - 7
build-profile.json5

@@ -5,7 +5,7 @@
         "name": "default",
         "signingConfig": "default",
         "targetSdkVersion": "5.0.5(17)",
-        "compatibleSdkVersion": "5.0.0(12)",
+        "compatibleSdkVersion": "5.0.5(17)",
         "runtimeOS": "HarmonyOS",
         "buildOption": {
           "strictMode": {
@@ -30,11 +30,11 @@
         "material": {
           "certpath": "C:\\Users\\xjy08\\.ohos\\config\\default_com.xgplayer.ttmusic.hm4_li00v0NJ2KHEZXa_MEhSBo4Q7SMa2KHpzKM8lnBZT1Y=.cer",
           "keyAlias": "debugKey",
-          "keyPassword": "0000001BAEFCFA4794A65008A888BD23285D3BFCEE596FFC2946D515EBF69695318A6F3359B22723B7F54E",
+          "keyPassword": "0000001BD7E2F4E219049C47BEB1C5DF12A84283327CAF6F062BF09C2DAD9BE662F2E0C6EF1B32269C0327",
           "profile": "C:\\Users\\xjy08\\.ohos\\config\\default_com.xgplayer.ttmusic.hm4_li00v0NJ2KHEZXa_MEhSBo4Q7SMa2KHpzKM8lnBZT1Y=.p7b",
           "signAlg": "SHA256withECDSA",
           "storeFile": "C:\\Users\\xjy08\\.ohos\\config\\default_com.xgplayer.ttmusic.hm4_li00v0NJ2KHEZXa_MEhSBo4Q7SMa2KHpzKM8lnBZT1Y=.p12",
-          "storePassword": "0000001B1DBD1DCB5B890E540146D6CA7BBF074F21FE233A96D61631AF1DB8A2C4BC9F91CBB719FE575C12"
+          "storePassword": "0000001B4A054D932A09F7166962992C88D0496184DEDEC08203B3BADBBC1BA9FC6C3F656C9AA5123B3F89"
         }
       }
     ]
@@ -52,10 +52,11 @@
         }
       ]
     },
-        {
-          "name": "ijkplayer",
-          "srcPath": "./ijkplayer"
-        },////注释掉这个代码,用ohpm install @ohos/ijkplayer去装2.0.6版本
+    {
+      "name": "ijkplayer",
+      "srcPath": "./ijkplayer"
+    },
+    ////注释掉这个代码,用ohpm install @ohos/ijkplayer去装2.0.6版本
     {
       "name": "lib",
       "srcPath": "./lib"

+ 26 - 0
entry/src/main/ets/pages/SettingPage.ets

@@ -42,6 +42,7 @@ export struct SettingPage {
   static readonly IS_SHOW_ALLBAR: string = 'IS_SHOW_ALLBAR';
   static readonly IS_SHOW_TITLTBAR: string = 'IS_SHOW_TITLTBAR';
   static readonly IS_SHOW_PLAYPAGE_BACK: string = 'IS_SHOW_PLAYPAGE_BACK';
+  static readonly IS_SHOW_SLLYRIC: string = 'IS_SHOW_SLLYRIC';
   static readonly IS_CIRCLE_BTN: string = 'isCircleBtn';
   static readonly IS_COVER_TOP: string = 'IS_COVER_TOP';
   static readonly IS_COVER_TOP_BIG: string = 'IS_COVER_TOP_BIG';
@@ -83,6 +84,7 @@ export struct SettingPage {
   @State isShowFAV: boolean = true //是否显示我的收藏
   @State isShowHistory: boolean = true //是否显示最近播放
   @State isShowPlayPageBack: boolean = false //是否显示播放页返回键
+  @State isShowSingleLineLyric: boolean = false //是否显示播放页返回键
   @State isCustomizeBg: boolean = false //自定义背景界面
   @State isCustomizeBgSheet: boolean = false //自定义背景界面
   @State isShowTitleBar: boolean = true //是否显示分类导航条
@@ -209,6 +211,7 @@ export struct SettingPage {
     this.isShowTitleBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_TITLTBAR, true)
     this.isShowAllBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_ALLBAR, true)
     this.isShowPlayPageBack = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_PLAYPAGE_BACK, false)
+    this.isShowSingleLineLyric = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_SLLYRIC, false)
     this.isCoverTopBig = PreferencesUtil.getBooleanSync(SettingPage.IS_COVER_TOP_BIG, false)
     // 只用 themeMode 控制主题
     this.themeMode = PreferencesUtil.getNumberSync(SettingPage.THEME_MODE, 0)
@@ -1111,6 +1114,29 @@ export struct SettingPage {
       .height(55)
       .clickEffect({ level: ClickEffectLevel.HEAVY })
 
+      Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
+      // 播放页返回键
+      Row() {
+        Text('播放页单行歌词')
+          .margin({ left: 18 })
+          .fontSize(15)
+          .fontColor(Color.Gray)
+          .fontWeight(480)
+          .layoutWeight(1)
+        Toggle({ type: ToggleType.Switch, isOn: this.isShowSingleLineLyric })
+          .selectedColor(this.themeColor)
+          .switchPointColor(Color.White)
+          .margin({ right: 18 })
+          .onChange((checked: boolean) => {
+            this.isShowSingleLineLyric = checked;
+            PreferencesUtil.put(SettingPage.IS_SHOW_SLLYRIC, this.isShowSingleLineLyric)
+            this.sendChangeEvent()
+          })
+          .width(50)
+          .height(30);
+      }
+      .height(55)
+      .clickEffect({ level: ClickEffectLevel.HEAVY })
 
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
       // 播放页返回键

+ 227 - 97
entry/src/main/ets/view/LocalMusic.ets

@@ -74,6 +74,7 @@ import { LrcParser } from '@sgaolei/lrc_parser';
 import app from '@system.app';
 import { TextNodeController } from './PipLyricTextBuilder';
 import { IndexerView } from './IndexerView';
+import { KeyCode } from '@kit.InputKit';
 
 const TAG = 'LocalMusic';
 
@@ -174,6 +175,7 @@ export struct LocalMusic {
   @State isSameTimePlay: boolean = false //是否和其他app同时播放
   @State isStartAutoPlay: boolean = false //启动后自动播放
   @State isShowPlayPageBack: boolean = false //是否显示播放页返回键
+  @State isShowSingleLineLyric: boolean = false //是否显示播放页返回键
   @State isMemoryLastPlay: boolean = false //是否启用应用退出记忆最后一首的播放进度
   @State isCoverTopBig: boolean = false//顶部大封面部分手机显示会和播放控制页重叠
   @State customizeBgPath: string | undefined = '';
@@ -573,6 +575,7 @@ export struct LocalMusic {
     this.isCircleBtn = PreferencesUtil.getBooleanSync(SettingPage.IS_CIRCLE_BTN, false)
     this.isShowPlayPageBack = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_PLAYPAGE_BACK, false)
     this.isCoverTopBig = PreferencesUtil.getBooleanSync(SettingPage.IS_COVER_TOP_BIG, false)
+    this.isShowSingleLineLyric = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_SLLYRIC, false)
     if (this.isSavePlayMode) {
       this.playType = PreferencesUtil.getNumberSync('musicPlayType', 0)
     }
@@ -1907,6 +1910,29 @@ export struct LocalMusic {
                   this.initDelayPlay(event);
                 }
               })
+              .onLoad((event?: object) => {
+                if (!!event) {
+                  this.initDelayPlay(event);
+                }
+              })
+              .onKeyEvent((event?: KeyEvent) => {
+                // If the button type is pressed, the subsequent code will not be executed; the specific button logic will be executed upon release.
+                if (!event || event.type !== KeyType.Down) {
+                  return;
+                }
+                //空格键 Space key controls pause/play
+                if (event.keyCode === KeyCode.KEYCODE_SPACE) {
+                  this.playOrPause()
+                }
+                // Right-click to fast forward
+                if (event.keyCode === KeyCode.KEYCODE_DPAD_RIGHT) {
+                  this.sessionFastForwardCallback(15);
+                }
+                // Left-click to rewind
+                if (event.keyCode === KeyCode.KEYCODE_DPAD_LEFT) {
+                  this.sessionRewindCallback(15);
+                }
+              })
               .onDestroy(() => {
               })
               .width('100%')// .width(this.videoWidth)
@@ -2558,8 +2584,8 @@ export struct LocalMusic {
                 });
             }
             .layoutWeight(1)
-            .margin({ left: this.currentBreakpoint !== BreakpointTypeEnum.SM?50:5,
-              right: this.currentBreakpoint !== BreakpointTypeEnum.SM?50:5, bottom: 1 });
+            .margin({ left: this.currentBreakpoint !== BreakpointTypeEnum.SM?40:5,
+              right: this.currentBreakpoint !== BreakpointTypeEnum.SM?40:5, bottom: 1 });
           });
         }
         .width('100%')
@@ -5218,6 +5244,21 @@ export struct LocalMusic {
     return false
   }
 
+  //是不是正常的手机竖屏
+  isPhonePortrait() {
+    LogUtil.info('twocold this.currentHeightBreakpoint = '+this.currentHeightBreakpoint)
+    LogUtil.info('twocold this.currentWidthBreakpoint = '+this.currentWidthBreakpoint)
+    if(DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE
+      &&this.currentHeightBreakpoint == HeightBreakpoint.HEIGHT_LG
+      &&this.currentWidthBreakpoint==WidthBreakpoint.WIDTH_SM){//如果是手机横屏,返回false
+
+      return true
+    }
+
+
+    return false
+  }
+
 
   @Builder
   IjkMusicPlayerView() {
@@ -5373,7 +5414,7 @@ export struct LocalMusic {
   private positionX: number = PlayConstants.POSITION_X;
   private positionY: number = PlayConstants.POSITION_Y;
   private windowClass: window.Window = globalThis.windowClass
-  @State volume: number = 0.5;
+  @State volume: number = 0.8;
   @State volumeShow: boolean = PlayConstants.VOLUME_SHOW;
   @State bright: number = PlayConstants.BRIGHT;
   @State brightShow: boolean = PlayConstants.BRIGHT_SHOW;
@@ -5411,6 +5452,7 @@ export struct LocalMusic {
   // 1.初始化controller
   private lyricController: LyricController = new LyricController()
   private lyricControllerXF: LyricController = new LyricController()//悬浮歌词控制器
+  private lyricControllerSingle: LyricController = new LyricController()//播放页单行歌词控制器
   private parser = new LyricParser()
   @State randomColor: string = 'rgb(0,0,0)'
   @State randomShakenX: number = 0
@@ -5444,21 +5486,32 @@ export struct LocalMusic {
     }
 
     this.initPipLyricSetting()
+    this.lyricControllerSingle
+      .setTextSize(15)
+      .setCacheSize(4)
+      .setTextColor("#FFFFFF")
+      .setHighlightColor("#FFFFFF")
+      .setHighlightScale(1.2)
+      .setEmptyHint("")
+      .setAlignMode('center')
+      .setAnimationDuration(500)
+      .setSingleLine(true)
+
     this.lyricContent = ''
     this.lyricController
       .setTextSize(this.currentLyricSize)
       .setCacheSize(4)
       .setTextColor("#DDDDDD")
-      .setHighlightColor("#FFFFFF")// .setLineSpace(18)
+      .setHighlightColor("#FFFFFF")
       .setEmptyHint("")
       .setAnimationDuration(1000)
     this.currentLyricAlignMode = PreferencesUtil.getNumberSync('LyricAlignMode', 1)
-    this.blurDegree = PreferencesUtil.getNumberSync('setBlurDegree', 2)
+    this.blurDegree = PreferencesUtil.getNumberSync('setBlurDegree', 0)
     this.setBlurDegree(this.blurDegree,false)
     this.setLyricAlignMode(this.currentLyricAlignMode,false)
     this.setLyricTextSize(PreferencesUtil.getNumberSync('LyricTextSize', 18),false)
     this.setHighLyricTextSize(PreferencesUtil.getNumberSync('HighLyricTextSize', 1.23),false)
-    this.lyricController.setLineSpace(PreferencesUtil.getNumberSync('LyricLineSpace', 52))
+    this.lyricController.setLineSpace(PreferencesUtil.getNumberSync('LyricLineSpace', 10))
     this.changeLyricColor(PreferencesUtil.getStringSync('LyricColor', '#FFFFFF'),false)
     this.changeLyricHightLightColor(PreferencesUtil.getStringSync('LyricHighLightColor', '#FFFFFF'),false)
     this.isHightLightCenter = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_SIMI, true)
@@ -5468,6 +5521,7 @@ export struct LocalMusic {
     this.showSingleLyric = false
     this.timeOffset = 0
     this.lyricController.setLyric(null)
+    this.lyricControllerSingle.setLyric(null)
     let jiaMilyricPath = lyricPath.substring(0, lyricPath.lastIndexOf('.')) + '.lrcc'
     LogUtil.debug("onecold lyricPath =" + lyricPath)
 
@@ -5483,6 +5537,7 @@ export struct LocalMusic {
       // 4.设置歌词
       this.lyricController.setLyric(lyric);
       this.lyricControllerXF.setLyric(lyric)
+      this.lyricControllerSingle.setLyric(lyric)
       return
 
     }
@@ -5526,6 +5581,7 @@ export struct LocalMusic {
               // 4.设置歌词
               this.lyricController.setLyric(lyric);
               this.lyricControllerXF.setLyric(lyric)
+              this.lyricControllerSingle.setLyric(lyric)
               this.showSingleLyric = true
               // 4.保存歌词文件lyric到本地
 
@@ -5535,6 +5591,7 @@ export struct LocalMusic {
             } else {
               this.lyricController.setLyric(null)
               this.lyricControllerXF.setLyric(null)
+              this.lyricControllerSingle.setLyric(null)
               if (isToast) {
                 ToastUtil.showShort('未获取到歌词!')
               }
@@ -5544,6 +5601,7 @@ export struct LocalMusic {
           } else {
             this.lyricController.setLyric(null)
             this.lyricControllerXF.setLyric(null)
+            this.lyricControllerSingle.setLyric(null)
             if (isToast) {
               ToastUtil.showShort('未获取到歌词!')
             }
@@ -5554,6 +5612,7 @@ export struct LocalMusic {
       } else {
         this.lyricController.setLyric(null)
         this.lyricControllerXF.setLyric(null)
+        this.lyricControllerSingle.setLyric(null)
         if (isToast) {
           ToastUtil.showShort('未获取到歌词!')
         }
@@ -5612,6 +5671,7 @@ export struct LocalMusic {
             // 4.设置歌词
             this.lyricController.setLyric(lyric);
             this.lyricControllerXF.setLyric(lyric)
+            this.lyricControllerSingle.setLyric(lyric)
 
             this.showSingleLyric = true
             console.info(`The content of file: ${fileContent}`);
@@ -5619,16 +5679,19 @@ export struct LocalMusic {
             console.error("chardet.detect failed with error: " + chardetError.message);
             this.lyricController.setLyric(null);
             this.lyricControllerXF.setLyric(null)
+            this.lyricControllerSingle.setLyric(null)
           }
         })
         .catch((err: BusinessError) => {
           this.lyricController.setLyric(null)
           this.lyricControllerXF.setLyric(null)
+          this.lyricControllerSingle.setLyric(null)
           console.error("read file data failed with error message: " + err.message + ", error code: " + err.code);
         })
         .catch((err: Error) => {
           this.lyricController.setLyric(null)
           this.lyricControllerXF.setLyric(null)
+          this.lyricControllerSingle.setLyric(null)
           console.error("read file 2 data failed with error message: " + err.message);
         })
         .finally(() => {
@@ -5637,6 +5700,7 @@ export struct LocalMusic {
 
     } catch (error) {
       this.lyricController.setLyric(null)
+      this.lyricControllerSingle.setLyric(null)
       this.lyricControllerXF.setLyric(null)
       Logger.error(TAG, 'init Lyric failed with err: ' + JSON.stringify(error));
     }
@@ -5658,7 +5722,7 @@ export struct LocalMusic {
     this.setLyricAlignMode(this.currentLyricAlignModePip,true)
     this.setLyricTextSize(PreferencesUtil.getNumberSync('LyricTextSizePip', 18),true)
     this.setHighLyricTextSize(PreferencesUtil.getNumberSync('HighLyricTextSizePip', 1.23),true)
-    this.lyricControllerXF.setLineSpace(PreferencesUtil.getNumberSync('LyricLineSpacePip', 52))
+    this.lyricControllerXF.setLineSpace(PreferencesUtil.getNumberSync('LyricLineSpacePip', 10))
     this.changeLyricColor(PreferencesUtil.getStringSync('LyricColorPip', '#FFFFFF'),true)
     this.changeLyricHightLightColor(PreferencesUtil.getStringSync('LyricHighLightColorPip', '#FFFFFF'),true)
     this.lyricControllerXF.setHightLightCenter(true)
@@ -6020,6 +6084,13 @@ export struct LocalMusic {
           .layoutWeight(1)
           .margin({ left: this.currentLyricAlignMode === 0 ? 0 : 50, top: 2, bottom: this.isPhoneLan() ? 40 :10 })
 
+
+        if(this.isPhoneLan()){
+          Column() {
+            this.playCenterView()
+          }
+          .margin({bottom:20,right:this.currentLyricAlignMode == 0?0:80})
+        }
       }
       .position({
         top: this.currentBreakpoint !== BreakpointTypeEnum.SM ? (this.isPhoneLan() ? 0 : 45) :
@@ -6027,6 +6098,24 @@ export struct LocalMusic {
       })
       .justifyContent(FlexAlign.Center)
       .height(this.isCoverOpacity() ? '95%' : '80%')
+
+    }
+
+  }
+
+  @Builder
+  SingleLyricView() {
+    Column() {
+      Column() {
+        LyricView2({ controller: this.lyricControllerSingle,
+          enableSeek: false,
+          seekUIColor: "#ff0000",// 滑动定位的按钮和文本颜色
+          seekLineColor: "#80ffffff",// 滑动定位线颜色
+          seekUIStyle: "listItem",// 滑动定位样式(seekLine传统样式,listItem类似抖音汽水音乐样式)
+        })
+      }
+      .height(48)
+      .margin({bottom:20})
     }
 
   }
@@ -6036,111 +6125,119 @@ export struct LocalMusic {
   BottomControl() {
     Column() {
       //播放 暂停,下一首,上一首
+      this.playCenterView()
 
-      Row() {
-        Row({ space: 33 }) {
 
+      //播放进度条
+      this.playProgressView()
 
-          Button({type:ButtonType.Circle,stateEffect:true}){
-            //更多功能
-            Image($r('app.media.menu'))
-              .width(24)
-              .clickEffect({level:ClickEffectLevel.MIDDLE})
-              .bindSheet($$this.isShowMoreView, this.PlayMoreSheet(), {
-                height: this.isCoverOpacity() ? '95%' : '93%',
-                preferType: this.currentBreakpoint!==BreakpointTypeEnum.SM?SheetType.CENTER:SheetType.BOTTOM,
-                dragBar: true,
-                showClose: true,
-                blurStyle: BlurStyle.Thin,
-                backgroundColor: Color.Transparent,
-              })
-          }
-          .backgroundColor(Color.Transparent)
-          .onClick(() => {
-            this.isShowMoreView = !this.isShowMoreView;
-          })
 
-          Button({type:ButtonType.Circle,stateEffect:true}){
-            Image($r('app.media.ic_previous'))
-              .width(33)
-              .clickEffect({level:ClickEffectLevel.HEAVY})
-              .aspectRatio(CommonConstants.ASPECT_RATIO)
-              .onClick(async () => {
-                this.playPrevious()
-              })
-          }
-          .backgroundColor(Color.Transparent)
+    }
+    .position({ bottom:this.isCoverOpacity()?55: 100 }) // 将  固定在底部
+
+  }
 
+  //播放控制上一首 下一首 暂停和播放
+  @Builder
+  playCenterView(){
+    Row() {
+      Row({ space: 33 }) {
+
+
+        Button({type:ButtonType.Circle,stateEffect:true}){
+          //更多功能
+          Image($r('app.media.menu'))
+            .width(24)
+            .clickEffect({level:ClickEffectLevel.MIDDLE})
+            .bindSheet($$this.isShowMoreView, this.PlayMoreSheet(), {
+              height: this.isCoverOpacity() ? '95%' : '93%',
+              preferType: this.currentBreakpoint!==BreakpointTypeEnum.SM?SheetType.CENTER:SheetType.BOTTOM,
+              dragBar: true,
+              showClose: true,
+              blurStyle: BlurStyle.Thin,
+              backgroundColor: Color.Transparent,
+            })
         }
-        .margin({ left: 33 })
+
+        .backgroundColor(Color.Transparent)
+        .onClick(() => {
+          this.isShowMoreView = !this.isShowMoreView;
+        })
 
         Button({type:ButtonType.Circle,stateEffect:true}){
-          Column() {
-            Image(this.CONTROL_PlayStatus === PlayStatus.PLAY ?
-              (this.isCircleBtn?$r('app.media.hm_pause'):$r('app.media.ic_public_play'))
-            : (this.isCircleBtn?$r('app.media.hm_play2'):$r('app.media.ic_public_pause')))
-              .width(this.isPhoneLan()?48:60)
-              .clickEffect({level:ClickEffectLevel.HEAVY})
-              .fillColor(Color.White)
-              .aspectRatio(CommonConstants.ASPECT_RATIO)
-              .onClick(async () => {
-                this.playOrPause()
+          Image($r('app.media.ic_previous'))
+            .width(33)
+            .clickEffect({level:ClickEffectLevel.HEAVY})
+            .aspectRatio(CommonConstants.ASPECT_RATIO)
+            .onClick(async () => {
+              this.playPrevious()
+            })
+        }
+        .backgroundColor(Color.Transparent)
 
+      }
+      // .margin({ left: 20 })
 
-              })
-          }
+      Button({type:ButtonType.Circle,stateEffect:true}){
+        Column() {
+          Image(this.CONTROL_PlayStatus === PlayStatus.PLAY ?
+            (this.isCircleBtn?$r('app.media.hm_pause'):$r('app.media.ic_public_play'))
+            : (this.isCircleBtn?$r('app.media.hm_play2'):$r('app.media.ic_public_pause')))
+            .width(this.isPhoneLan()?48:60)
+            .clickEffect({level:ClickEffectLevel.HEAVY})
+            .fillColor(Color.White)
+            .aspectRatio(CommonConstants.ASPECT_RATIO)
+            .onClick(async () => {
+              this.playOrPause()
 
+
+            })
         }
-        .backgroundColor(Color.Transparent)
-        .layoutWeight(1)
-        .margin({ left: 33, right: 33 })
 
+      }
+      .backgroundColor(Color.Transparent)
+      .layoutWeight(1)
+      .margin({ left: 33, right: 33 })
 
-        Row({ space: 33 }) {
-          Button({ type: ButtonType.Capsule, stateEffect: true }) {
-            Image($r('app.media.ic_next'))
-              .width(33)
-              .clickEffect({level:ClickEffectLevel.HEAVY})
-              .aspectRatio(CommonConstants.ASPECT_RATIO)
-              .onClick(() => {
 
-                this.playNext();
+      Row({ space: 33 }) {
+        Button({ type: ButtonType.Capsule, stateEffect: true }) {
+          Image($r('app.media.ic_next'))
+            .width(33)
+            .clickEffect({level:ClickEffectLevel.HEAVY})
+            .aspectRatio(CommonConstants.ASPECT_RATIO)
+            .onClick(() => {
 
-              })
-          }
-          .backgroundColor(Color.Transparent)
-          .width(33)
+              this.playNext();
 
-          Button({type:ButtonType.Circle,stateEffect:true}){
-            //添加或取消收藏
-            Image(Utility.getIsFav(this.favList,this.currentSong)?
-            $r('app.media.add_fac_light'):$r('app.media.add_fac'))
-              .width(24)
-              .clickEffect({level:ClickEffectLevel.MIDDLE})
-              .aspectRatio(CommonConstants.ASPECT_RATIO)
-              .onClick(async () => {
-                if(this.currentSong){
-                  this.doFav(this.currentSong)
-                }
-              })
-          }
-          .backgroundColor(Color.Transparent)
-          .width(24)
+            })
+        }
+        .backgroundColor(Color.Transparent)
+        .width(33)
 
+        Button({type:ButtonType.Circle,stateEffect:true}){
+          //添加或取消收藏
+          Image(Utility.getIsFav(this.favList,this.currentSong)?
+          $r('app.media.add_fac_light'):$r('app.media.add_fac'))
+            .width(24)
+            .clickEffect({level:ClickEffectLevel.MIDDLE})
+            .aspectRatio(CommonConstants.ASPECT_RATIO)
+            .onClick(async () => {
+              if(this.currentSong){
+                this.doFav(this.currentSong)
+              }
+            })
         }
-        .margin({ right: 33 })
+        .backgroundColor(Color.Transparent)
+        .width(24)
 
       }
-      .width('100%')
-      .margin({ left:10,right:10,bottom:this.isCoverOpacity()?0:20 })
-      .justifyContent(FlexAlign.Center)
-      //播放进度条
-      this.playProgressView()
-
+      // .margin({ right: 33 })
 
     }
-    .position({ bottom:this.isCoverOpacity()?55: 100 }) // 将  固定在底部
-
+    .width('100%')
+    .margin({ left:10,right:10,bottom:this.isCoverOpacity()?0:20 })
+    .justifyContent(FlexAlign.Center)
   }
 
   //播放进度条
@@ -6250,7 +6347,7 @@ export struct LocalMusic {
     }
     .width(PlayConstants.PROGRESS_ROW_WIDTH)
     .height(this.isPhoneLan()?25:33)
-    .visibility(this.isPhoneLan()&&this.isAutoHide?Visibility.None:Visibility.Visible)
+    // .visibility(this.isPhoneLan()&&this.isAutoHide?Visibility.None:Visibility.Visible)
     .animation({
       duration: 666,
       curve: 'ease-in-out' // 可选动画曲线
@@ -6403,11 +6500,39 @@ export struct LocalMusic {
       }
 
       .margin({
-        bottom: this.isCoverOpacity() || this.isCoverRectangle ? 55 : 0,
+        bottom: this.isCoverOpacity() || this.isCoverRectangle ?
+          (this.isPhonePortrait()&&this.isShowSingleLineLyric?20:55) : 0,
         top: this.isCoverOpacity() ? 0 : 20
       })
+      if(this.isPhonePortrait()&&this.isShowSingleLineLyric){
+        this.SingleLyricView()
+      }
+      if(this.isPhoneLan()){
+        Column(){
+          Text(this.name)
+            .fontSize(18)
+            .fontWeight(FontWeight.Bold)
+            .textOverflow({ overflow: TextOverflow.Ellipsis })
+            .maxLines(1)
+            .width('99%')
+            .textAlign(TextAlign.Center)
+            .fontColor(Color.White)
+          Text(this.artist + '  ' + this.currentSong?.album)
+            .fontSize(15)
+            .visibility(Visibility.Hidden)
+            .textOverflow({ overflow: TextOverflow.Ellipsis })
+            .fontColor(Color.White)
+            .textAlign(TextAlign.Center)
+            .width('99%')
+            .maxLines(1)
+          this.playProgressView()
+        }
+        .position({bottom:45})
+
+      }else{
+        this.BottomControl()
+      }
 
-      this.BottomControl()
     }
 
     .width(CommonConstants.FULL_PERCENT)
@@ -6533,8 +6658,8 @@ export struct LocalMusic {
   // 高亮歌词放大倍数
   @State currentHightLyricSize: number = 1.2
   @State currentHightLyricSizePip: number = 1.2
-  @State currentLyricLineSpace: number = 52
-  @State currentLyricLineSpacePip: number = 52
+  @State currentLyricLineSpace: number = 10
+  @State currentLyricLineSpacePip: number = 10
   @State currentLyricAlignMode: number = 1
   @State currentLyricAlignModePip: number = 1
   @State blurDegree: number = 2
@@ -6993,9 +7118,9 @@ export struct LocalMusic {
           .fontColor(Color.White)
         Slider({
           value: isPip?this.currentLyricLineSpacePip:this.currentLyricLineSpace,
-          min: 8,
+          min: 2,
           max: 120,
-          step: 0.1,
+          step: 1,
           style: SliderStyle.OutSet
         })
           .blockColor(this.themeColor)
@@ -7578,7 +7703,7 @@ export struct LocalMusic {
                   sessionType: 'video'
                 })
                   .id('AVCastPicker')
-                  .width(46)
+
               } else {
                 Image(more.image)
                   .width(24)
@@ -7754,6 +7879,10 @@ export struct LocalMusic {
         .fontSize(16)
         .fontColor(Color.White)
     }
+    .width('100%')
+    .layoutWeight(1)
+    .alignItems(VerticalAlign.Center)
+    .justifyContent(FlexAlign.Start)
   }
 
   private moreItems: MoreItem[] = [
@@ -8404,6 +8533,7 @@ export struct LocalMusic {
     this.isCurrentTime = true;
     this.lyricController.updatePosition(position + this.timeOffset * 1000)
     this.lyricControllerXF.updatePosition(position + this.timeOffset * 1000)
+    this.lyricControllerSingle.updatePosition(position + this.timeOffset * 1000)
 
     this.currentTime = this.stringForTime(position);
     this.isCurrentTime = false

+ 33 - 10
entry/src/main/module.json5

@@ -53,14 +53,15 @@
             ],
             "uris": [
 
-//              {
-//                "scheme": "file",
-//                "utd":"general.video",
-//                "linkFeature": "FileOpen",
-//              },
               {
                 "scheme": "file",
                 "utd": "general.audio",
+                "linkFeature": "FileOpen"
+              },
+
+              {
+                "scheme": "file",
+                "utd":"general.video",
                 "linkFeature": "FileOpen",
               },
               {
@@ -68,6 +69,12 @@
                 "type": "audio/*",
                 "linkFeature": "FileOpen",
                 "maxFileSupported": 1
+              },
+              {
+                "scheme": "file",
+                "type": "video/*",
+                "linkFeature": "FileOpen",
+                "maxFileSupported": 1
               }
             ],
             "entities": [
@@ -94,20 +101,36 @@
         "skills": [
           {
             "actions": [
-              "ohos.want.action.sendData"
+              "ohos.want.action.sendData",
+              "ohos.want.action.viewData"
             ],
 
             // 目标应用在配置支持接收的数据类型时,需穷举支持的UTD,比如:支持全部图片类型,可声明:general.image
             // maxFileSupported 对于归属指定类型的文件,标识一次支持接收的最大数量。默认为0,代表不支持此类文件的分享。文件类型归属关系参考:@ohos.data.uniformTypeDescriptor (标准化数据定义与描述)
             "uris": [
 
+//              {
+//                "scheme": "file",
+//                "utd": "general.audio",
+//                "linkFeature": "FileOpen"
+//              },
               {
                 "scheme": "file",
-                "utd": "general.audio",
-                "linkFeature": "Share",
+                "type": "audio/*",
+                "linkFeature": "FileOpen",
                 "maxFileSupported": 1
-              }
-
+              },
+              {
+                "scheme": "file",
+                "type": "video/*",
+                "linkFeature": "FileOpen",
+                "maxFileSupported": 1
+              },
+//              {
+//                "scheme": "file",
+//                "utd":"general.video",
+//                "linkFeature": "FileOpen"
+//              }
             ]
           }
         ]

+ 1 - 1
entry/src/main/resources/base/media/list.svg

@@ -1 +1 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749662073454" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1685" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M416 192h448a32 32 0 0 0 0-64h-448a32 32 0 0 0 0 64zM864 448h-448a32 32 0 0 0 0 64h448a32 32 0 0 0 0-64zM864 768h-448a32 32 0 0 0 0 64h448a32 32 0 0 0 0-64z" fill="#231815" p-id="1686"></path><path d="M224 160m-96 0a96 96 0 1 0 192 0 96 96 0 1 0-192 0Z" fill="#231815" p-id="1687"></path><path d="M224 480m-96 0a96 96 0 1 0 192 0 96 96 0 1 0-192 0Z" fill="#231815" p-id="1688"></path><path d="M224 800m-96 0a96 96 0 1 0 192 0 96 96 0 1 0-192 0Z" fill="#231815" p-id="1689"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1752480835993" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7700" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M149.8 64.4c-46.3 0-84 37.7-84 84s37.7 84 84 84 84-37.7 84-84-37.7-84-84-84z m0 124.2c-22.2 0-40.2-18.1-40.2-40.2 0-22.2 18.1-40.2 40.2-40.2 22.2 0 40.2 18.1 40.2 40.2 0 22.2-18.1 40.2-40.2 40.2zM148.3 306.7c-46.3 0-84 37.7-84 84s37.7 84 84 84 84-37.7 84-84-37.7-84-84-84z m0 124.2c-22.2 0-40.2-18.1-40.2-40.2 0-22.2 18.1-40.2 40.2-40.2 22.2 0 40.2 18.1 40.2 40.2 0 22.2-18 40.2-40.2 40.2zM148.3 549c-46.3 0-84 37.7-84 84s37.7 84 84 84 84-37.7 84-84c0-46.4-37.7-84-84-84z m0 124.2c-22.2 0-40.2-18.1-40.2-40.2 0-22.2 18.1-40.2 40.2-40.2 22.2 0 40.2 18.1 40.2 40.2s-18 40.2-40.2 40.2zM148.3 791.2c-46.3 0-84 37.7-84 84s37.7 84 84 84 84-37.7 84-84-37.7-84-84-84z m0 124.3c-22.2 0-40.2-18.1-40.2-40.2 0-22.2 18.1-40.2 40.2-40.2 22.2 0 40.2 18.1 40.2 40.2s-18 40.2-40.2 40.2zM360.2 199.6h548.9c28.3 0 51.2-23 51.2-51.2 0-28.3-23-51.2-51.2-51.2H360.2c-28.3 0-51.2 23-51.2 51.2 0 28.2 23 51.2 51.2 51.2zM909.1 824H360.2c-28.3 0-51.2 23-51.2 51.2 0 28.3 23 51.2 51.2 51.2h548.9c28.3 0 51.2-23 51.2-51.2 0-28.2-23-51.2-51.2-51.2zM909.1 581.7H360.2c-28.3 0-51.2 23-51.2 51.2s23 51.2 51.2 51.2h548.9c28.3 0 51.2-23 51.2-51.2s-23-51.2-51.2-51.2zM909.1 339.4H360.2c-28.3 0-51.2 23-51.2 51.2 0 28.3 23 51.2 51.2 51.2h548.9c28.3 0 51.2-23 51.2-51.2 0-28.2-23-51.2-51.2-51.2z" p-id="7701" fill="#515151"></path></svg>

+ 12 - 0
lib/src/main/ets/LyricController.ets

@@ -26,6 +26,7 @@ export class LyricController {
     private animDuration: number = DEFAULT_ANIM_DURATION
     private cacheSize: number = DEFAULT_CACHE_SIZE
     private isBold: boolean = true
+    private isSingleLine: boolean = false
     private emptyHint: string = "--"
     private alignMode: "left" | "center" = "center"
     private isHightLightCenter: boolean = true
@@ -190,6 +191,17 @@ export class LyricController {
         return this
     }
 
+    getSingleLine(): boolean {
+        return this.isSingleLine
+    }
+
+
+    setSingleLine(isSingle: boolean): LyricController {
+        this.isSingleLine = isSingle
+        this.onInvalidated(false)
+        return this
+    }
+
     /**
      * The bold style of focused lyric.
      * @returns True to set text bold style, false to set normal style.

+ 12 - 2
lib/src/main/ets/view/LyricView2.ets

@@ -49,6 +49,7 @@ export struct LyricView2 {
     @State currentIndex: number = 0 // the focused index of the lyric line list.
     @State isLyricEmpty: boolean = true // is no lyric.
     @State textSize: number = 16
+    @State isSingleLine: boolean = false
     @State lineSpace: number = 16
     @State textWeight: number = FontWeight.Medium
     @State textHighlightSize: number = 18
@@ -129,6 +130,7 @@ export struct LyricView2 {
     private getAttrFromController() {
         this.currentLyric = this.controller.getLyric()
         this.textSize = this.controller.getTextSize()
+        this.isSingleLine = this.controller.getSingleLine()
         this.blurDegree = this.controller.getBlurDegree()
         this.isHightLightCenter = this.controller.getHightLightCenter()
         this.lineSpace = this.controller.getLineSpace()
@@ -229,8 +231,10 @@ export struct LyricView2 {
         .height('100%')
         .scrollBar(BarState.Off)
         .cachedCount(this.cacheSize)
-        .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-            .animation({ duration: 500, curve: Curve.Ease }))
+        .transition(TransitionEffect.asymmetric(
+             this.isSingleLine? TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }):
+             TransitionEffect.move(TransitionEdge.BOTTOM).animation({ duration: 500 }),
+            TransitionEffect.scale({ x: 0, y: 0 })  ))
         .visibility(this.isLoadingData ? Visibility.Hidden : Visibility.Visible)
         .onScrollIndex((_, __, center) => {
             const now = Date.now()
@@ -286,6 +290,9 @@ export struct LyricView2 {
             .fontColor(index == this.currentIndex ? this.textHighlightColor : this.textColor)
             .fontWeight(index == this.currentIndex && this.isHighlightBold ? FontWeight.Bold : this.textWeight)
             .animation({ duration: this.animDuration, curve: Curve.FastOutSlowIn })
+            .visibility(this.isSingleLine?
+                (index == this.currentIndex ?Visibility.Visible:Visibility.None)
+                :Visibility.Visible)
             .width(this.alignMode == 'center' ? '100%' : '76%')
     }
     // 逐字歌词渲染
@@ -304,6 +311,9 @@ export struct LyricView2 {
                     .margin(0)
                     .opacity(this.calculateOpacityFactor(index, this.currentIndex))
                     .blur(this.calculateBlurFactor(index, this.currentIndex))
+                    .visibility(this.isSingleLine?
+                        (index == this.currentIndex ?Visibility.Visible:Visibility.None)
+                        :Visibility.Visible)
                     .animation({
                         // 动画播放速度
                         tempo: 0.8,

+ 0 - 18
oh-package-lock.json5

@@ -11,7 +11,6 @@
     "@changwei/chardet@^1.0.0": "@changwei/chardet@1.0.0",
     "@chinalike/popup@^0.0.7": "@chinalike/popup@0.0.7",
     "@keke/color-picker@^1.0.4": "@keke/color-picker@1.0.4",
-    "@ohos/ijkplayer@^2.0.6": "@ohos/ijkplayer@2.0.6",
     "@ohos/lottie@^2.0.19": "@ohos/lottie@2.0.19",
     "@ohos/pinyin4js@^2.0.2": "@ohos/pinyin4js@2.0.2",
     "@ohos/pulltorefresh@^2.1.1": "@ohos/pulltorefresh@2.1.1",
@@ -24,7 +23,6 @@
     "@taobao-ohos/utdid_sdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@cashier_alipay/cashiersdk/lib/utdid_sdk-1.0.9.har": "@taobao-ohos/utdid_sdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@cashier_alipay/cashiersdk/lib/utdid_sdk-1.0.9.har",
     "class-transformer@^0.5.1": "class-transformer@0.5.1",
     "libblueshield.so@oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/cpp/types/libblueshield": "libblueshield.so@oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/cpp/types/libblueshield",
-    "libijkplayer_audio_napi.so@oh_modules/.ohpm/@ohos+ijkplayer@2.0.6/oh_modules/@ohos/ijkplayer/src/main/cpp/types/ijkplayer_audio_napi": "libijkplayer_audio_napi.so@oh_modules/.ohpm/@ohos+ijkplayer@2.0.6/oh_modules/@ohos/ijkplayer/src/main/cpp/types/ijkplayer_audio_napi",
     "liblrcparser.so@oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser": "liblrcparser.so@oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser",
     "pako@^2.1.0": "pako@2.1.0"
   },
@@ -71,16 +69,6 @@
       "resolved": "https://repo.harmonyos.com/ohpm/@keke/color-picker/-/color-picker-1.0.4.har",
       "registryType": "ohpm"
     },
-    "@ohos/ijkplayer@2.0.6": {
-      "name": "@ohos/ijkplayer",
-      "version": "2.0.6",
-      "integrity": "sha512-xDRUkxAgfdYA2opvE/2fxbMHaiLDx8ROmN8WDCJW+m41z1z53477MiyeLTQtfvxlbI3VOMR7MD39FsbiaJpnvg==",
-      "resolved": "https://repo.harmonyos.com/ohpm/@ohos/ijkplayer/-/ijkplayer-2.0.6.har",
-      "registryType": "ohpm",
-      "dependencies": {
-        "libijkplayer_audio_napi.so": "file:./src/main/cpp/types/ijkplayer_audio_napi"
-      }
-    },
     "@ohos/lottie@2.0.19": {
       "name": "@ohos/lottie",
       "version": "2.0.19",
@@ -172,12 +160,6 @@
       "resolved": "oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/cpp/types/libblueshield",
       "registryType": "local"
     },
-    "libijkplayer_audio_napi.so@oh_modules/.ohpm/@ohos+ijkplayer@2.0.6/oh_modules/@ohos/ijkplayer/src/main/cpp/types/ijkplayer_audio_napi": {
-      "name": "libijkplayer_audio_napi.so",
-      "version": "2.0.3-rc.3",
-      "resolved": "oh_modules/.ohpm/@ohos+ijkplayer@2.0.6/oh_modules/@ohos/ijkplayer/src/main/cpp/types/ijkplayer_audio_napi",
-      "registryType": "local"
-    },
     "liblrcparser.so@oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser": {
       "name": "liblrcparser.so",
       "version": "1.0.0",