Просмотр исходного кода

初步实现瀑布流效果布局

onecold 11 месяцев назад
Родитель
Сommit
eece4b4a23

+ 109 - 0
entry/src/main/ets/common/util/AttributeModifierUtil.ets

@@ -0,0 +1,109 @@
+import { CommonModifier } from '@kit.ArkUI';
+
+export class ShadowModifier extends CommonModifier {
+  constructor() {
+    super()
+  }
+
+  applyNormalAttribute(instance: CommonAttribute): void {
+    instance.shadow({ radius: 26, color: $r('app.color.shadow_color') })
+      .backgroundColor($r('app.color.start_window_background_blur'))
+      .backdropBlur(150)
+  }
+}
+
+export class ImageFancyModifier implements AttributeModifier<ImageAttribute> {
+  private borderRadius: Length | BorderRadiuses | LocalizedBorderRadiuses;
+  private width: number | string;
+  private height: number | string;
+
+  constructor(borderRadius: Length | BorderRadiuses | LocalizedBorderRadiuses, width: number | string,
+    height: number | string) {
+    this.borderRadius = borderRadius;
+    this.width = width;
+    this.height = height;
+  }
+
+  applyNormalAttribute(attr: ImageAttribute): void {
+    attr
+      .alt($r("app.media.avatar"))
+      .backgroundImageSize(ImageSize.Auto)
+      .borderRadius(this.borderRadius)
+      .width(this.width)
+      .height(this.height)
+      .interpolation(ImageInterpolation.Medium)// 用于重采样后的抗锯齿
+      .draggable(false)// 禁止长按手势拖动
+      .autoResize(true) // 重采样,可减少内存占用
+  }
+}
+
+export class SymbolGlyphFancyModifier implements AttributeModifier<SymbolGlyphAttribute> {
+  private fontSize: number;
+  private width: number | string;
+  private height: number | string;
+
+  constructor(fontSize: number, width: number | string, height: number | string) {
+    this.fontSize = fontSize;
+    this.width = width;
+    this.height = height;
+  }
+
+  applyNormalAttribute(attr: SymbolGlyphAttribute): void {
+    attr
+      .fontSize(this.fontSize)
+      .fontColor([$r('app.color.text_color')])
+      .width(this.width)
+      .height(this.height);
+  }
+}
+
+export class ButtonFancyModifier implements AttributeModifier<ButtonAttribute> {
+  private width: number | string;
+  private height: number | string;
+
+  constructor(width: number | string, height: number | string) {
+    this.width = width;
+    this.height = height;
+  }
+
+  applyNormalAttribute(attr: ButtonAttribute): void {
+    attr
+      .borderRadius(16)
+      .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.5 })
+      .width(this.width)
+      .height(this.height)
+      .backgroundColor($r('app.color.start_window_background_blur'))
+  }
+}
+
+export class SelectItemTextFancyModifier implements AttributeModifier<TextAttribute> {
+  private selected: boolean;
+
+  constructor(selected: boolean) {
+    this.selected = selected
+  }
+
+  applyNormalAttribute(attr: TextAttribute): void {
+    if (this.selected) {
+      attr
+        .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
+        .fontSize($r('sys.float.ohos_id_text_size_body1'))
+        .fontWeight(FontWeight.Regular)
+    } else {
+      attr
+        .fontSize($r('sys.float.ohos_id_text_size_body1'))
+        .fontWeight(FontWeight.Regular)
+    }
+    attr.margin({ left: 20, right: 20 })
+  }
+}
+
+export class MenuModifier extends CommonModifier {
+  constructor() {
+    super()
+  }
+
+  applyNormalAttribute(instance: MenuAttribute): void {
+    instance.font({ size: 15, weight: FontWeight.Normal }).radius(16)
+  }
+}

+ 11 - 4
entry/src/main/ets/common/util/Utility.ets

@@ -426,7 +426,7 @@ export class Utility {
 
 
   // 获取缩略图
-  static async getFetchFrameByTime(filePath: string,time?:number) {
+  static async getFetchFrameByTime(filePath: string,time?:number,imageWidth?:number,imageHeight?:number) {
     if(Utility.isMusicByExtension(filePath)){
       return undefined
     }
@@ -441,12 +441,18 @@ export class Utility {
       let timeUs = 0
       console.info('onecold time='+time)
       if(time){
-        timeUs = (time > 0) ? time*60 : 0
+        timeUs = (time > 0) ? time*50 : 0
       }
       let queryOption = media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC
+      if(imageWidth){
+        imageWidth =imageWidth/2.5
+      }
+      if(imageHeight){
+        imageHeight =  imageHeight/2.5
+      }
       let param: media.PixelMapParams = {
-        width : 300,
-        height : 400,
+        width : imageWidth||300,
+        height : imageHeight||400,
       }
       // 获取缩略图(promise模式)
       pixelMap = await avImageGenerator.fetchFrameByTime(timeUs, queryOption, param)
@@ -462,6 +468,7 @@ export class Utility {
     return pixelMap
   }
 
+
   // 获取fd文件路径
   static async getFdDir(path:string){
     let fdPath = 'fd://';

+ 404 - 7
entry/src/main/ets/view/LocalMusic.ets

@@ -38,6 +38,7 @@ import { AvSessionController } from '../controller/AvSessionController';
 import { repairAudioMetadata,  getApiLyric,changeMusicCover} from '../common/util/MusicTagUtils';
 import { FFMpegTags,Utility } from '../common/util/Utility';
 import { TagsContentCover } from '../view/TagsContentCover';
+import { ImageFancyModifier } from '../common/util/AttributeModifierUtil'
 import {
   // DeviceChangeReason,
   IjkMediaPlayer,
@@ -1995,10 +1996,14 @@ export struct LocalMusic {
                 this.tabTitle()
               }
 
-              if (this.isGridMusic) {
-                this.getGridView()
-              } else {
-                this.getListView()
+              if(this.twoFingerType==4){
+                this.getWaterView()
+              }else{
+                if(this.isGridMusic){
+                  this.getGridView()
+                }else {
+                  this.getListView()
+                }
               }
               if (this.modeType == 0) {
                 Column() {
@@ -3346,6 +3351,393 @@ export struct LocalMusic {
     this.dataSource.pushArrayData(this.videoLocalList)
   }
 
+
+  //瀑布流布局 支持双指缩放
+  @State columns: number = 2;
+  @State waterFlowScale: number = 1;
+  @State imageScale: number = 1;
+  @State waterFlowOpacity: number = 1;
+  @State waterFlowSnapshot: image.PixelMap | undefined = undefined;
+  private columnChanged: boolean = false;
+  private oldColumn: number = this.columns;
+  private pinchTime: number = 0;
+  // 根据缩放阈值改变列数,触发WaterFlow重新布局
+  changeColumns(scale: number) {
+    if (scale > (this.columns / (this.columns - 0.5)) && this.columns > 1) {
+      this.columns--;
+      this.columnChanged = true;
+    } else if (scale < 1 && this.columns < 4) {
+      this.columns++;
+      this.columnChanged = true;
+    }
+
+
+  }
+  @Builder
+  getWaterView(){
+    Scroll(this.scroller) {
+      Column() {
+        if(this.isShowCoverHeader()){
+          this.coverHeader()
+        }else {
+          this.listViewTitle()
+        }
+
+        WaterFlow({
+          layoutMode: WaterFlowLayoutMode.SLIDING_WINDOW
+        }) {
+
+          LazyForEach(this.dataSource, (item: VideoItem, index: number) => {
+            FlowItem() {
+              this.MusicWaterCardItem(item,index)
+            }
+            .width('100%')
+            .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.9 })
+            .bindContextMenu(this.MenuBuilder(item, index, item.filePath), ResponseType.LongPress,
+              {
+                preview: MenuPreviewMode.IMAGE,
+                previewAnimationOptions: { scale: [0.8, 1.0] },
+              })
+            .bindContextMenu(this.MenuBuilder(item, index, item.filePath), ResponseType.RightClick,
+              {
+                preview: MenuPreviewMode.IMAGE,
+                previewAnimationOptions: { scale: [0.8, 1.0] },
+              })
+            .transition(TransitionEffect.scale({ x: 0.8, y: 0.8 }).animation({ duration: 500 }))
+            .transition(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 0.8, y: 0.8 }).animation({ duration: 500 }),
+              TransitionEffect.scale({ x: 0, y: 0 })  ))
+            .gesture(
+              GestureGroup(GestureMode.Exclusive,
+                SwipeGesture({ direction: SwipeDirection.Horizontal })
+                  .onAction((event: GestureEvent) => {
+                    if (event) {
+                      // this.sideBarController.openSideBar()
+                    }
+                  }),
+                TapGesture({ count: 1, fingers: 1 })
+                  .onAction(async () => {
+
+                  })
+              )
+            )
+          }, (item: VideoItem) =>  item.filePath)
+        }
+        // .columnsTemplate('repeat(auto-fit, 160)')
+        .id('waterflow') // 设置id用于截图
+        .columnsTemplate('1fr '.repeat(this.columns))  // 动态生成列模板,如:'1fr 1fr 1fr'表示3列等宽
+        .columnsGap(12) // 列间距
+        .rowsGap(16) // 行间距
+        .cachedCount(6)
+        .margin({bottom:this.isShowCoverHeader()? 25:
+          this.isCoverOpacity()?this.topBarHeight+this.bottomBarHeight+78
+            :this.topBarHeight+this.bottomBarHeight+108})
+        .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
+          .animation({ duration: 500, curve: Curve.Ease }))
+        .scrollBar(BarState.Off)
+        // .fadingEdge(true, { fadingEdgeLength: LengthMetrics.vp(38) })
+        // 效果:只有向上或者向下滑动到顶部时才会有弹簧回弹效果
+        .edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true })
+        .width('100%')
+        .height('100%')
+        .padding(10)
+        .opacity(this.waterFlowOpacity)
+        .scale({
+          x: this.waterFlowScale,
+          y: this.waterFlowScale,
+          centerX: 0,
+          centerY: 0
+        })
+        .onAppear(() => {
+          this.scroller.scrollEdge(Edge.Top)
+        })
+        .nestedScroll({
+          scrollForward: NestedScrollMode.PARENT_FIRST,
+          scrollBackward: NestedScrollMode.SELF_FIRST
+        })
+        .priorityGesture(
+          PinchGesture()
+            .onActionStart((event: GestureEvent) => {
+              // 双指捏合手势识别成功时截图
+              this.pinchTime = event.timestamp;
+              this.columnChanged = false;
+              this.oldColumn = this.columns;
+              this.getUIContext().getComponentSnapshot().get('waterflow', (error: Error, pixmap: image.PixelMap) => {
+                if (error) {
+                  console.info('error:' + JSON.stringify(error));
+                  return;
+                }
+                this.waterFlowSnapshot = pixmap;
+
+                if ((this.oldColumn === 1 ) || (this.oldColumn === 4 && event.scale < 1)) {
+                  console.info("onecold onActionStart oldColumn:" + this.oldColumn)
+                  if (this.oldColumn ===4) {
+                    this.twoFingerType =3
+                    this.isGridMusic = true
+                  }else if (this.oldColumn ===1) {
+                    this.twoFingerType =1
+                    this.isGridMusic = false
+                  }
+                  return;
+                }
+
+              })
+            })
+            .onActionUpdate((event: GestureEvent) => {
+              // 手势更新:处理缩放逻辑和视觉效果
+              // 边界限制:防止超出列数范围时继续缩放
+              if ((this.oldColumn === 1 && event.scale > 1) || (this.oldColumn === 4 && event.scale < 1)) {
+                return;
+              }
+
+              // 节流处理:避免过于频繁的更新,提升性能
+              if (event.timestamp - this.pinchTime < 10000000) {
+                return;
+              }
+              this.pinchTime = event.timestamp;
+
+              this.waterFlowScale = event.scale;
+              this.imageScale = event.scale;
+              // 根据缩放比例设置WaterFlow透明度
+              this.waterFlowOpacity = (this.waterFlowScale > 1) ? (this.waterFlowScale - 1) : (1 - this.waterFlowScale);
+              this.waterFlowOpacity *= 3;
+              if (!this.columnChanged) {
+                this.changeColumns(event.scale);
+              }
+
+              // 列数改变后的缩放比例调整:避免出现空白区域
+              if (this.columnChanged) {
+                this.waterFlowScale = this.imageScale * this.columns / this.oldColumn;
+
+                // 限制缩放范围,确保视觉效果自然
+                if (event.scale < 1) {
+                  this.waterFlowScale = this.waterFlowScale > 1 ? this.waterFlowScale : 1;
+                } else {
+                  this.waterFlowScale = this.waterFlowScale < 1 ? this.waterFlowScale : 1;
+                }
+              }
+            })
+            .onActionEnd((event: GestureEvent) => {
+              // 手势结束:执行归位动画并保存状态
+              // 执行归位动画:平滑过渡到正常状态
+              this.getUIContext()?.animateTo({ duration: 300 }, () => {
+                this.waterFlowScale = 1;
+                this.waterFlowOpacity = 1;
+              })
+
+              // 持久化保存当前列数:下次启动时恢复
+              AppStorage.setOrCreate<number>('columnsCount', this.columns);
+            })
+        )
+
+
+        //允许拖拽音乐和视频到List或Grid上自动导入视频
+        .allowDrop([uniformTypeDescriptor.UniformDataType.AUDIO,uniformTypeDescriptor.UniformDataType.VIDEO])
+        .onDrop((event?: DragEvent) => {
+          try {
+            let dragData: UnifiedData = (event as DragEvent).getData() as UnifiedData;
+            if (dragData !== undefined) {
+              let records: unifiedDataChannel.UnifiedRecord[] = dragData.getRecords();
+              if (records.length > 0) {
+                for (let i = 0; i < records.length; i++) {
+                  let types = records[i].getTypes();
+                  if (types.includes(uniformTypeDescriptor.UniformDataType.FILE_URI)) {
+                    const fileUriUds =
+                      records[i].getEntry(uniformTypeDescriptor.UniformDataType.FILE_URI) as uniformDataStruct.FileUri;
+                    let typeDescriptor = uniformTypeDescriptor.getTypeDescriptor(fileUriUds.fileType);
+                    if (typeDescriptor.belongsTo(uniformTypeDescriptor.UniformDataType.AUDIO)
+                      ||typeDescriptor.belongsTo(uniformTypeDescriptor.UniformDataType.VIDEO)) {
+                      this.targetFile = fileUriUds.oriUri;
+                      this.saveVideoDatas([this.targetFile])
+                      hilog.info(0x0000, 'Heanup', '当前targetFile:' + this.targetFile);
+                    }
+                  }
+                }
+              } else {
+                hilog.info(0x0000, TAG, `%{public}s`, `dragData arr is null`);
+              }
+            } else {
+              hilog.info(0x0000, TAG, `%{public}s`, `dragData is undefined`);
+            }
+
+          } catch (error) {
+            const err = error as BusinessError;
+            hilog.error(0x0000, TAG, `startDataLoading errorCode: ${err.code}, errorMessage: ${err.message}`);
+          }
+        })
+
+
+
+
+      }
+
+
+    }
+    .scrollBar(BarState.Off)
+
+  }
+
+  //瀑布流卡片布局
+  @Builder
+  private MusicWaterCardItem(item: VideoItem, index: number) {
+    Button({ type: ButtonType.Normal, stateEffect: false }) {
+      Stack() {
+        Column() {
+          Image(StrUtil.isEmpty(item.pixelMapPath) ? Utility.getMusisBg2(index) : item.pixelMapPath)
+            .attributeModifier(new ImageFancyModifier({
+              topLeft: 10,
+              topRight: 10,
+              bottomLeft: 0,
+              bottomRight: 0
+            }, 60, 200))
+            .width('100%')
+            .height('auto')
+            .objectFit(ImageFit.Auto)
+            .bindSheet(this.longItemFilePath== item.filePath, this.editSheet(item), {
+              height:  '99%' ,
+              dragBar: true,
+              onDisappear: () => {
+                this.longItemFilePath = '';
+                this.tempLyricContent = ''
+              },
+              showClose: true,
+              preferType: SheetType.CENTER ,
+              title: { title: '编辑标签' }
+            })
+            .draggable(false)
+            .opacity(this.opacityItem)// 绑定透明度
+            // .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
+            //   .animation({ duration: 500, curve: Curve.Ease }))
+            .animation({
+              duration: 666,
+              curve: 'ease-in-out' // 可选动画曲线
+            })
+            .margin({
+              left: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 40 : 20,
+              right: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 40 : 20
+            })
+          Column() {
+            Text(item.name.startsWith('.') ? item.name.replace(/\./g, '') : item.name)
+              .fontSize(this.columns == 4 ||this.columns==3? 12 : this.columns == 2 ? 15 : 18)
+              .maxLines(1)
+              .fontWeight(FontWeight.Bold)
+              .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
+              .animation({
+                duration: 555,
+                curve: 'Linear',
+              })
+              .bindSheet(this.longItemFilePathDetail== item.filePath, this.detailSheet(item), {
+                height:  '95%',
+                dragBar: true,
+                showClose: true,
+                onDisappear: () => {
+                  this.longItemFilePathDetail = '';
+                },
+                blurStyle:BlurStyle.Thin,
+                backgroundColor:Color.Transparent,
+                preferType: SheetType.CENTER ,
+                title: { title: '详情' }
+              })
+              .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+              $r('app.color.text_color'))
+
+            Column() {
+              Text(`${this.artistMap.get(item.name)?.length ?? 0}首`)
+                .fontSize(11)
+                .fontSize(this.columns == 4 ||this.columns==3? 10 : this.columns == 2 ? 12 : 14)
+                .visibility(this.modeType === 2 && !this.isCanBack ? Visibility.Visible : Visibility.None)
+                .fontColor($r('app.color.text_color'))
+              Text(`${this.albumMap.get(item.name)?.length ?? 0}首`)
+                .fontSize(11)
+                .fontSize(this.columns == 4 ||this.columns==3? 10 : this.columns == 2 ? 12 : 14)
+                .visibility(this.modeType === 3 && !this.isCanBack ? Visibility.Visible : Visibility.None)
+                .fontColor($r('app.color.text_color'))
+              Row(){
+                Column(){
+                  Text(item.md5Str?.includes('Lossless')?
+                  Utility.resourceToString(this.context,$r('app.string.lossless')):item.md5Str)//音质
+                    .fontSize(this.columns == 4 ||this.columns==3? 8 : this.columns == 2 ? 9 : 11)
+                    .padding({ top: 3,right:6,left:6,bottom:3 })
+                    .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+                    $r('app.color.text_color'))
+                    .fontWeight(500)
+                    .borderRadius(12)
+                    .margin({ left: this.twoFingerType == 3 ? 6 : 8 })
+                    .backgroundColor('#FFC107')
+                    .visibility(StrUtil.isEmpty(item.md5Str)||this.twoFingerType==1?Visibility.None:Visibility.Visible)
+                }
+                .margin({ top: 2 ,right:6})
+                .visibility((this.modeType == 3 && !this.isCanBack)||(this.modeType == 2 && !this.isCanBack)
+                  ||(this.modeType == 0&&item.type==CommonConstants.TYPE_IS_DIR)? Visibility.None : Visibility.Visible)
+                Text(StrUtil.isEmpty(item.artist) ? item.duration: item.artist)
+                  .fontSize(this.columns == 4 ||this.columns==3? 10 : this.columns == 2 ? 12 : 13)
+                  .maxLines(1)
+                  .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
+                  .margin({ top: 2})
+                  .visibility(item.type == CommonConstants.TYPE_IS_ARTIST
+                    || item.type == CommonConstants.TYPE_IS_ALBUM
+                    || item.type == CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
+                  .fontWeight(FontWeight.Medium)
+                  .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+                  $r('app.color.text_color'))
+              }
+
+
+            }
+            .alignItems(HorizontalAlign.Center) // 关键:使内容水平居中
+
+          }
+
+          .height(this.columns == 4 ||this.columns==3? 40 : this.columns == 2 ? 48 : 58)
+          .width('100%')
+          .justifyContent(FlexAlign.Center)
+          .margin({
+            left: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 40 : 20,
+            right: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 40 : 20
+          })
+
+        }
+        .width('100%')
+        .borderRadius(12)
+        .backgroundImage(StrUtil.isEmpty(item.pixelMapPath)?Utility.getMusisBg2(index):item.pixelMapPath)
+        .backgroundImageSize({ height: '100%', width: '100%' })
+        .backgroundBlurStyle(BlurStyle.BACKGROUND_ULTRA_THICK)
+        .animation({ curve: Curve.Sharp, duration: 300 })
+
+
+        Checkbox({ name: 'checkbox' + index })
+          .select(this.selectedFiles.some(x => x.filePath == item.filePath))
+          .selectedColor(this.themeColor)
+          .shape(CheckBoxShape.CIRCLE)
+          .opacity(this.isMultiSelect ? 1 : 0)
+          .animation({
+            duration: 666,
+            curve: 'Smooth' // 可选动画曲线
+          })
+          .visibility(this.isMultiSelect && item.type !== CommonConstants.TYPE_IS_DIR ? Visibility.Visible :
+          Visibility.None)
+          .onChange((checked: boolean) => this.handleFileSelection(item, checked))
+          .margin({ left: 20, top: 8, bottom: 8 })
+          .width(38)
+          .height(38)
+      }
+    }
+    .backgroundColor(Color.Transparent)
+    .width('100%')
+    .height('auto')
+    .padding({top:2})
+    .reuseId('card_item')
+    .onClick(() => {
+      if (this.isMultiSelect && item.type !== CommonConstants.TYPE_IS_DIR) {
+        const isChecked = this.selectedFiles.some(x => x.filePath == item.filePath);
+        this.handleFileSelection(item, !isChecked);
+      } else {
+        this.doPlay(item, index)
+      }
+
+    })
+  }
+
+
   // Grid布局的开始
   private dragRefOffSetX: number = 0;
   private dragRefOffSetY: number = 0;
@@ -3484,6 +3876,7 @@ export struct LocalMusic {
       bottom: this.isCoverOpacity() ? (this.isShowCoverHeader() ? this.topBarHeight+30 : this.topBarHeight+90)
         : (this.isShowCoverHeader() ? this.topBarHeight+45 : this.topBarHeight+128)
     })
+    .reuseId('grid_item')
     .layoutWeight(1)
     .scrollBar(BarState.Off)
     .supportAnimation(true)
@@ -3575,8 +3968,9 @@ export struct LocalMusic {
     if (this.pinchValue >= 1) {
       this.twoFingerType++
       Logger.info('this.twoFingerType1 = ' + this.twoFingerType);
-      if (this.twoFingerType > 3) {
-        this.twoFingerType = 3
+      if(this.twoFingerType >= 4){
+        this.twoFingerType = 4//切换成瀑布流
+        this.columns = 4
       }
     } else {
       this.twoFingerType--
@@ -3588,6 +3982,7 @@ export struct LocalMusic {
       }
     }
     PreferencesUtil.put(SettingPage.TWO_FINGER_TYPE, this.twoFingerType)
+    PreferencesUtil.put(SettingPage.IS_GRID_MUSIC, this.isGridMusic)
     this.pinchValue = 1;
     this.scaleValue = 1;
   }
@@ -3966,11 +4361,12 @@ export struct LocalMusic {
       this.twoFingerType--
       Logger.info('this.twoFingerType2 = ' + this.twoFingerType);
       if (this.twoFingerType < 1) {
-        this.twoFingerType = 1
+        this.twoFingerType = 4
 
       }
     }
     PreferencesUtil.put(SettingPage.TWO_FINGER_TYPE, this.twoFingerType)
+    PreferencesUtil.put(SettingPage.IS_GRID_MUSIC, this.isGridMusic)
     this.pinchValue = 1;
     this.scaleValue = 1;
   }
@@ -4152,6 +4548,7 @@ export struct LocalMusic {
         : (this.isShowCoverHeader() ? this.topBarHeight+35 : this.isHiCarSmall()?this.topBarHeight+90:this.topBarHeight+125)
     })
     .cachedCount(6)
+    .reuseId('list_item')
     .borderRadius(20)
     .transition(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
       TransitionEffect.scale({ x: 0, y: 0 })))

+ 8 - 0
entry/src/main/resources/base/element/color.json

@@ -179,6 +179,14 @@
     {
       "name": "left_draw_bg",
       "value": "#FEFEFE"
+    },
+    {
+      "name": "shadow_color",
+      "value": "#33000000"
+    },
+    {
+      "name": "start_window_background_blur",
+      "value": "#ffffff"
     }
   ]
 }