import TitleBar from '../view/TitleBar' import { promptAction, router } from '@kit.ArkUI' import { CommonConstants } from '../common/constants/CommonConstants' import { AppUtil, DeviceUtil, DisplayUtil, FileUtil, MD5, PreferencesUtil, ToastUtil } from '@pura/harmony-utils' import { CustomContentDialog } from '@kit.ArkUI' import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; import common from '@ohos.app.ability.common'; import { photoAccessHelper } from '@kit.MediaLibraryKit' import { fileIo, fileUri } from '@kit.CoreFileKit' import { BusinessError, emitter } from '@kit.BasicServicesKit' import { BreakpointTypeEnum } from '../common/util/BreakpointSystem' import { resourceManager } from '@kit.LocalizationKit' import { IBestButton, IBestColorPicker, IBestField, IBestIcon, IBestPopup, IBestRadio, IBestRadioGroup } from '@ibestservices/ibest-ui' import { Utility } from '../common/util/Utility' @Preview @Entry @Component export struct SettingPage { static readonly THEME_MODE: string = 'themeMode'; static readonly SORT_TYPE: string = 'musicSortType'; static readonly IS_BGPLAY_OPEN: string = 'isBgPlayOpen'; static readonly IS_AUTO_RATATE: string = 'isAutoRatate'; static readonly iS_MEMORY_PLAY: string = 'isMemoryPlay'; static readonly IS_MIDIACODEC_OPEN: string = 'isMediacodec'; static readonly iS_MUSIC_MEMORY_PLAY: string = 'isMusicMemoryPlay'; static readonly iS_MUSIC_BG_COVER: string = 'isMusicBGCover'; static readonly iS_SAVE_PLAY_MODE: string = 'isSavePlayMode'; static readonly IS_COVER_RECTANGLE: string = 'isCoverRectangle'; //封面圆形或者方形 static readonly IS_SHOW_SIMI: string = 'isShowSimi'; static readonly IS_SHOW_FAV: string = 'isShowFAV'; static readonly IS_SHOW_HISTORY: string = 'isShowHistory'; static readonly IS_CUSTOMIZE_BG: string = 'is_customize_bg'; static readonly IS_GRID_MUSIC: string = 'is_grid_music'; static readonly IS_CUSTOMIZE_BG_PATH: string = 'is_customize_bg_path'; static readonly IS_SCROLL_HIDE: string = 'isScrollHide'; static readonly IS_SAMETIME_PLAY: string = 'isSameTimePlay'; static readonly CUSTOMIZE_BG_BLUR: string = 'customize_bg_blur'; static readonly BG_BRIGHTNESS: string = 'bg_brightness'; public static THEME_COLOR_KEY: string = 'THEME_COLOR'; public static THEME_COLOR_LIST: Array = [ { name: '经典蓝', color: '#0A59F7' }, { name: '活力黄', color: '#FFC107' }, { name: '枫叶红', color: '#F44336' }, { name: '玫瑰粉', color: '#FF4081' }, { name: '幻影紫', color: '#9C27B0' }, { name: '翡翠绿', color: '#64BB5C' }, { name: '竹青蓝', color: '#00BCD4' }, { name: '深空灰', color: '#607D8B' }, { name: '橙霞橙', color: '#FF9800' }, { name: '湖水蓝', color: '#00BFFF' }, { name: '柠檬绿', color: '#C6FF00' }, { name: '樱花粉', color: '#FF69B4' }, { name: '暮夜蓝', color: '#283593' }, { name: '薄荷青', color: '#1DE9B6' }, { name: '银沙灰', color: '#B0BEC5' }, { name: '自定义', color: '#ffecec' } ]; @State showApiDialog: boolean = false @State tempApiUrl: string = '' @State lyricApiUrl: string = PreferencesUtil.getStringSync('LRC_API', '') @State isBgPlayOpen: boolean = true //是否启用后台播放 @State isAutoRatate: boolean = true //是否启用自动横竖屏 @State isMemoryPlay: boolean = true //是否启用记忆播放 @State isMediacodec: boolean = false //是否启用硬件解码 @State isMusicMemoryPlay: boolean = false //是否启用记忆播放 @State isMusicBGCover: boolean = true //播放背景随封面 @State sortType: number = 4 //默认排序方式 @State isStartAutoPlay: boolean = false //启动后自动播放 @State isMemoryLastPlay: boolean = false //是否启用应用退出记忆最后一首的播放进度 @State isShowSimi: boolean = false //是否显示私密音频 @State isShowFAV: boolean = true //是否显示我的收藏 @State isShowHistory: boolean = true //是否显示最近播放 @State isCustomizeBg: boolean = false //自定义背景界面 @State isCustomizeBgSheet: boolean = false //自定义背景界面 @State blurValue: number = 0 //背景模糊 @State bgBrightness: number = 0 //背景亮度 @State isGridMusic: boolean = false //是否网格布局 @State isScrollHide: boolean = false //是否滚动隐藏 @State isSameTimePlay: boolean = false //是否和其他app同时播放 @State isSavePlayMode: boolean = true @State customizeBgPath: string | undefined = ''; context = getContext(this); @State showCoverApiDialog: boolean = false @State tempCoverApiUrl: string = '' @State coverApiUrl: string = PreferencesUtil.getStringSync('COVER_API', '') @State apiDialogType: 'lyric' | 'cover' = 'lyric' @State themeMode: number = 0 // 0: 跟随系统, 1: 浅色, 2: 深色 @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT; @StorageLink('isDarkMode') isDarkMode: boolean = false // 是否启用深色模式 static readonly iS_START_AUTO_PLAY: string = 'isStartAutoPlay'; static readonly iS_MEMORY_LAST_PLAY: string = 'isMemoryLastPlay'; /** 当前断点类型(如大屏/小屏) */ @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD; @State verName: string = '' @StorageProp('themeColor') themeColor: string = PreferencesUtil.getStringSync('THEME_COLOR', '#FF4081'); @State showColorPicker: boolean = false @State customColor: string = PreferencesUtil.getStringSync('THEME_COLOR', '#FF4081'); @State isThemeSheet: boolean = false // 主题设置弹窗显示状态 @State colorRows: Array> = chunkArray(SettingPage.THEME_COLOR_LIST, 2); @State colorGroup: string = "group" apiDialogController: CustomDialogController = new CustomDialogController({ builder: CustomContentDialog({ primaryTitle: this.apiDialogType === 'lyric' ? '修改歌词API地址' : '修改封面API地址', contentBuilder: () => { this.buildApiDialogContent(); }, buttons: [ { value: '取消', action: () => { this.apiDialogController.close(); } }, { value: '保存', action: () => { if (this.apiDialogType === 'lyric') { this.lyricApiUrl = this.tempApiUrl.trim() PreferencesUtil.put('LRC_API', this.lyricApiUrl) this.getUIContext().getPromptAction().showToast({ message: '保存成功,当前LRC_API:' + this.lyricApiUrl, duration: 2000, showMode: promptAction.ToastShowMode.TOP_MOST, bottom: 85 }) } else { this.coverApiUrl = this.tempApiUrl.trim() PreferencesUtil.put('COVER_API', this.coverApiUrl) this.getUIContext().getPromptAction().showToast({ message: '保存成功,当前COVER_API:' + this.coverApiUrl, duration: 2000, showMode: promptAction.ToastShowMode.TOP_MOST, bottom: 85 }) } this.apiDialogController.close(); } } ] }), autoCancel: true, alignment: DialogAlignment.Center }) @Builder buildApiDialogContent() { Column() { TextInput({ text: this.tempApiUrl, placeholder: this.apiDialogType === 'lyric' ? '请输入歌词API地址' : '请输入封面API地址' }) .onChange((val: string) => { this.tempApiUrl = val }) .width('90%') .height(60) } .width('100%') } // 组件生命周期 aboutToAppear() { this.isBgPlayOpen = PreferencesUtil.getBooleanSync(SettingPage.IS_BGPLAY_OPEN, true) this.isAutoRatate = PreferencesUtil.getBooleanSync(SettingPage.IS_AUTO_RATATE, true) this.isMemoryPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_PLAY, true) this.isMediacodec = PreferencesUtil.getBooleanSync(SettingPage.IS_MIDIACODEC_OPEN, false) this.isMusicMemoryPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_MEMORY_PLAY, false) this.isMusicBGCover = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_BG_COVER, true) this.sortType = PreferencesUtil.getNumberSync(SettingPage.SORT_TYPE, 4) this.isShowSimi = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_SIMI, false) this.isShowFAV = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_FAV, true) this.isShowHistory = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_HISTORY, true) this.isCustomizeBg = PreferencesUtil.getBooleanSync(SettingPage.IS_CUSTOMIZE_BG, false) this.customizeBgPath = PreferencesUtil.getStringSync(SettingPage.IS_CUSTOMIZE_BG_PATH, '') this.isGridMusic = PreferencesUtil.getBooleanSync(SettingPage.IS_GRID_MUSIC, false) this.isScrollHide = PreferencesUtil.getBooleanSync(SettingPage.IS_SCROLL_HIDE, false) this.isSameTimePlay = PreferencesUtil.getBooleanSync(SettingPage.IS_SAMETIME_PLAY, false) this.isSavePlayMode = PreferencesUtil.getBooleanSync(SettingPage.iS_SAVE_PLAY_MODE, true) this.blurValue = PreferencesUtil.getNumberSync(SettingPage.CUSTOMIZE_BG_BLUR, 0) this.bgBrightness = PreferencesUtil.getNumberSync(SettingPage.BG_BRIGHTNESS, 0) this.isStartAutoPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_START_AUTO_PLAY, false) this.isMemoryLastPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_LAST_PLAY, false) // 只用 themeMode 控制主题 this.themeMode = PreferencesUtil.getNumberSync(SettingPage.THEME_MODE, 0) this.applyThemeMode(this.themeMode) let themeColor = PreferencesUtil.getStringSync('THEME_COLOR', '#FF4081'); AppStorage.setOrCreate('themeColor', themeColor); this.themeColor = themeColor; } // 监听颜色模式变化 onColorModeChange(): void { this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK; AppStorage.setOrCreate('isDarkMode', this.isDarkMode); } // 组件生命周期 aboutToDisappear() { // 无需处理apiDialogController } applyThemeMode(mode: number) { let colorMode = ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET if (mode === 1) { colorMode = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT } else if (mode === 2) { colorMode = ConfigurationConstant.ColorMode.COLOR_MODE_DARK } AppStorage.setOrCreate('currentColorMode', colorMode) AppStorage.setOrCreate('isDarkMode', colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) PreferencesUtil.putSync(SettingPage.THEME_MODE, mode) AppStorage.setOrCreate('themeMode', mode) // 只有强制浅色/深色时才主动设置 const context = getContext(this) as common.UIAbilityContext context.getApplicationContext().setColorMode(colorMode) } //是不是手机横屏 isPhoneLan() { if (DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE && this.currentBreakpoint !== BreakpointTypeEnum.SM) { if (DisplayUtil.getFoldStatus() === 0) { return true } } return false } @Builder pickerBuilder() { Column({ space: 20 }) { IBestColorPicker({ value: this.customColor }) Row({ space: 20 }) { IBestButton({ text: "取消", btnBorderRadius:10, onBtnClick: () => { this.showColorPicker = false } }) IBestButton({ type: "primary", text: "确定", btnBorderRadius:10, onBtnClick: () => { this.themeColor = this.customColor PreferencesUtil.putSync(SettingPage.THEME_COLOR_KEY, this.customColor) AppStorage.setOrCreate('themeColor', this.customColor) this.sendChangeEvent() this.showColorPicker = false } }) } }.padding(20) } @Builder themeSheetBuilder() { Column() { // 颜色模式分组卡片 Column() { Row() { Row(){ IBestIcon({ name: 'brush-o', color: this.themeColor , iconSize: 20 }) .margin({ right: 8 }) Text('颜色模式') .fontSize(15) .fontWeight(500) } .layoutWeight(1) Blank() Row(){ IBestRadioGroup({ group: this.colorGroup, active: $themeMode, placeDirection: Axis.Horizontal }) { ForEach(['自动', '日间', '夜间'], (item: string, idx: number) => { Column() { IBestRadio({ group: this.colorGroup, checkedColor: this.themeColor, label: '', name: idx }) .margin({ left: 3 }) Text(item) .fontSize(15) .fontColor($r('app.color.text_color')) .margin({ top: 6 }) } .onClick(() => { this.themeMode = idx this.applyThemeMode(idx) this.sendChangeEvent() }) .alignItems(HorizontalAlign.Center) }) } } .margin({left:12,right:12}) } } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(18) .border({ width: 1, color: '#F0F0F0' }) .shadow({ radius: 12, color: 0x11000000, offsetX: 0, offsetY: 2 }) .margin({ left: 0, right: 0, bottom: 20 }) .padding({ top: 18, bottom: 18, left: 20, right: 20 }) .width('90%') // 主题色分组卡片 Column() { Row() { Image($r('app.media.theme')) .width(20) .height(20) .fillColor(this.themeColor) Text('主题色') .fontSize(15) .fontWeight(500) .margin({ left: 8 }) .layoutWeight(1) } .margin({left:20, top: 12 }) Row(){ Column() { ForEach(this.colorRows, (row: Array, rowIdx: number) => { Row() { ForEach(row, (item: ThemeColorItem, colIdx: number) => { Button() { Row() { Blank() .width(22) .height(22) .backgroundColor(item.name === '自定义' && this.isCustomThemeColor() ? this.themeColor : item.color) .border({ width: 2, color:$r('app.color.text_color')}) .borderRadius(11) Text(item.name) .fontSize(15) .fontColor($r('app.color.text_color')) .margin({ left: 10 }) } .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Start) .layoutWeight(1) } .height(40) .layoutWeight(1) .backgroundColor( (item.name === '自定义' && this.isCustomThemeColor()) || this.themeColor === item.color ? this.themeColor : $r('app.color.settings_background_main') ) .borderRadius(20) .onClick(() => { if (item.name === '自定义') { this.showColorPicker = true } else { this.themeColor = item.color PreferencesUtil.putSync(SettingPage.THEME_COLOR_KEY, item.color) AppStorage.setOrCreate('themeColor', item.color) this.sendChangeEvent() } }) .margin({ right: colIdx === 0 ? '4%' : 20, bottom: 10, left: 20 }) }) } .justifyContent(FlexAlign.Start) }) } .margin({ left: 12, right: 12, top: 12 }) } } .width('90%') .backgroundColor($r('app.color.settings_background_main')) .borderRadius(18) .border({ width: 1, color: '#F0F0F0' }) .shadow({ radius: 12, color: 0x11000000, offsetX: 0, offsetY: 2 }) .margin({ left: 0, right: 0, bottom: 18 }) .padding({ top: 18, bottom: 18, left: 0, right: 0 }) // 主题色自定义弹窗 IBestPopup({ visible: $showColorPicker, popupWidth: 320, contentBuilder: (): void => this.pickerBuilder(), cornerRadius:20, }) } .padding({ top: 8, bottom: 8, left: 18, right: 18 }) .width('100%') .backgroundColor(Color.Transparent) .borderRadius(24) } build() { Column() { Column() { Line().width('100%').height('100%') } .height(this.isPhoneLan() ? 0 : px2vp(AppUtil.getStatusBarHeight())) .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor) .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP]) // 自定义标题栏 Stack() { // 居中标题 Text('通用设置') .fontSize(20) .fontColor(Color.White) .align(Alignment.Center) // 左侧返回按钮 Row() { Image($r('app.media.left_back_white')) .width(32) .height(32) .margin({ left: 12, right: 8 }) .onClick(() => { router.back(); }) Blank().flexGrow(1) Blank().width(32) } .height(48) .width('100%') .alignItems(VerticalAlign.Center) } .height(48) .width('100%') .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor) Scroll() { Column() { // 主题设置分组 Column() { Row() { Text('个性化') .margin({ left: 18, right: 20 }) .fontSize(16) .fontColor(Color.Gray) .fontWeight(480) .layoutWeight(1) } .height(48) 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) Image($r('app.media.arrow_right')) .width(22) .height(22) .margin({ right: 18 }) } .height(55) .onClick(() => { this.showColorPicker = false; this.isThemeSheet = true; // 如果当前颜色是自定义,则同步到自定义色块 // if (this.isCustomThemeColor()) { this.customColor = this.themeColor; // } }) .bindSheet($$this.isThemeSheet, this.themeSheetBuilder(), { height: '95%', dragBar: true, preferType: this.currentBreakpoint !== BreakpointTypeEnum.SM ? SheetType.CENTER : SheetType.BOTTOM, showClose: true, blurStyle: BlurStyle.Thin, backgroundColor: Color.Transparent, title: { title: '主题设置' }, shouldDismiss:(SheetDismiss:SheetDismiss)=>{ SheetDismiss.dismiss(); this.showColorPicker = false; } }) Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color')) Button({ type: ButtonType.Normal, stateEffect: true }) { Row() { Text('自定义背景') .margin({ left: 18 }) .fontSize(15) .fontColor(Color.Gray) .fontWeight(480) .layoutWeight(1) .bindSheet($$this.isCustomizeBgSheet, this.customizeBgSheet(), { height: '95%', dragBar: true, preferType: this.currentBreakpoint !== BreakpointTypeEnum.SM ? SheetType.CENTER : SheetType.BOTTOM, showClose: true, blurStyle: BlurStyle.Thin, backgroundColor: Color.Transparent, title: { title: '自定义背景' } }) Blank() // 右侧箭头 Image($r('app.media.arrow_right')) .width(22) .height(22) .margin({ left: 20, right: 20 }) .align(Alignment.Center) } } .height(55) .onClick(() => { this.isCustomizeBgSheet = !this.isCustomizeBgSheet; }) .backgroundColor(Color.Transparent) 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.isScrollHide }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isScrollHide = checked; PreferencesUtil.put(SettingPage.IS_SCROLL_HIDE, this.isScrollHide) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) 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.isGridMusic }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isGridMusic = checked; PreferencesUtil.put(SettingPage.IS_GRID_MUSIC, this.isGridMusic) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) 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.isShowSimi }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isShowSimi = checked; PreferencesUtil.put(SettingPage.IS_SHOW_SIMI, this.isShowSimi) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) 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.isShowFAV }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isShowFAV = checked; PreferencesUtil.put(SettingPage.IS_SHOW_FAV, this.isShowFAV) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) 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.isShowHistory }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isShowHistory = checked; PreferencesUtil.put(SettingPage.IS_SHOW_HISTORY, this.isShowHistory) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(20) .margin({ left: 0, right: 0, top: 0, bottom: 10 }) .padding(0) // 音频设置分组 Column() { Row() { Text('音频设置') .margin({ left: 18, right: 20 }) .fontSize(16) .fontColor(Color.Gray) .fontWeight(480) .layoutWeight(1) } .height(48) 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.isStartAutoPlay }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isStartAutoPlay = checked; PreferencesUtil.put(SettingPage.iS_START_AUTO_PLAY, this.isStartAutoPlay) }) .width(50) .height(30); } .height(55) 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.isMemoryLastPlay }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isMemoryLastPlay = checked; PreferencesUtil.put(SettingPage.iS_MEMORY_LAST_PLAY, this.isMemoryLastPlay) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) 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.isMusicMemoryPlay }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isMusicMemoryPlay = checked; PreferencesUtil.put(SettingPage.iS_MUSIC_MEMORY_PLAY, this.isMusicMemoryPlay) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) 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) Select([ { value: CommonConstants.SORT_ARRAY[0] }, { value: CommonConstants.SORT_ARRAY[1] }, { value: CommonConstants.SORT_ARRAY[2] }, { value: CommonConstants.SORT_ARRAY[3] }, { value: CommonConstants.SORT_ARRAY[4] }, { value: CommonConstants.SORT_ARRAY[5] }, { value: CommonConstants.SORT_ARRAY[6] }, { value: CommonConstants.SORT_ARRAY[7] }]) .font({ size: 15, weight: FontWeight.Medium }) .fontColor(Color.Gray) .margin({ right: 18 }) .selected(this.sortType) .value(CommonConstants.SORT_ARRAY[this.sortType]) .onSelect(async (_index: number, text?: string | undefined) => { this.sortType = _index PreferencesUtil.put(SettingPage.SORT_TYPE, this.sortType) this.sendChangeEvent() }) } .height(55) Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color')) .visibility(Visibility.None) // 默认排序模式 Row() { Text('保存播放模式') .margin({ left: 18 }) .fontSize(15) .fontColor(Color.Gray) .fontWeight(480) .layoutWeight(1) Toggle({ type: ToggleType.Switch, isOn: this.isSavePlayMode }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isSavePlayMode = checked; PreferencesUtil.put(SettingPage.iS_SAVE_PLAY_MODE, this.isSavePlayMode) }) .width(50) .height(30); } .height(55) Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color')) .visibility(Visibility.None) Row() { Text('与其他应用同时播放') .margin({ left: 18 }) .fontSize(15) .fontColor(Color.Gray) .fontWeight(480) .layoutWeight(1) Toggle({ type: ToggleType.Switch, isOn: this.isSameTimePlay }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isSameTimePlay = checked; PreferencesUtil.put(SettingPage.IS_SAMETIME_PLAY, this.isSameTimePlay) }) .width(50) .height(30); } .height(55) .visibility(Visibility.None) 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.isMusicBGCover }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isMusicBGCover = checked; PreferencesUtil.put(SettingPage.iS_MUSIC_BG_COVER, this.isMusicBGCover) }) .width(50) .height(30); } .height(55) } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(20) .margin({ left: 0, right: 0, top: 10, bottom: 10 }) .padding(0) // API设置分组 Column() { Row() { Text('API设置') .margin({ left: 18, right: 20 }) .fontSize(16) .fontColor(Color.Gray) .fontWeight(480) .layoutWeight(1) } .height(48) Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color')) // 歌词API Row() { Text('歌词:') .margin({ left: 18, right: 6 }) .fontSize(15) .fontColor(Color.Gray) Text(this.lyricApiUrl) .margin({ right: 10 }) .fontSize(15) .fontColor(Color.Gray) .layoutWeight(1) Image(this.isDarkMode ? $r('app.media.rename2') : $r('app.media.ic_public_edit')) .width(22) .height(22) .margin({ right: 18 }) } .onClick(() => { this.apiDialogType = 'lyric' this.tempApiUrl = this.lyricApiUrl this.apiDialogController.open() }) .height(55) // 封面API Row() { Text('封面:') .margin({ left: 18, right: 6 }) .fontSize(15) .fontColor(Color.Gray) Text(this.coverApiUrl) .margin({ right: 10 }) .fontSize(15) .fontColor(Color.Gray) .layoutWeight(1) Image(this.isDarkMode ? $r('app.media.rename2') : $r('app.media.ic_public_edit')) .width(22) .height(22) .margin({ right: 18 }) } .onClick(() => { this.apiDialogType = 'cover' this.tempApiUrl = this.coverApiUrl this.apiDialogController.open() }) .justifyContent(FlexAlign.Center) .height(55) } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(20) .margin({ left: 0, right: 0, top: 10, bottom: 20 }) .padding(0) Button({ type: ButtonType.Capsule, stateEffect: true }) { Column() { Row() { Text('设置教程:') .margin({ left: 18 }) .fontSize(15) .fontColor(Color.Gray) .fontWeight(480) Text('点击进Q群讨论') .margin({ right: 10 }) .fontSize(15) .fontColor(Color.Gray) .layoutWeight(1) Blank() // 右侧箭头 Image($r('app.media.arrow_right')) .width(22) .height(22) .margin({ left: 20, right: 20 }) .align(Alignment.Center) } .height(55) } } .onClick(() => { const qqUrl = `mqqapi://card/show_pslcard?src_type=internal&version=1&uin=${CommonConstants.QQ_GROUP}&card_type=group&source=external`; let context = this.getUIContext().getHostContext() as common.UIAbilityContext; context.openLink(qqUrl, {}) }) .backgroundColor($r('app.color.settings_background_main')) .borderRadius(15) .margin({ top: 0, bottom: 20 }) .padding(0) //空白 Column() { Blank() .height(88) }.height(88) } .margin({ left: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 35 : 20, right: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 35 : 20, top: 20, bottom: 20 }) .justifyContent(FlexAlign.Start) } .scrollBar(BarState.Auto) .height(px2vp(DisplayUtil.getHeight() - AppUtil.getStatusBarHeight() - AppUtil.getNavigationIndicatorHeight())) .width('100%') .margin({ bottom: 10 }) .backgroundColor($r('app.color.settings_background')) } .height('100%') .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM]) } //发送广播通知更新UI sendChangeEvent() { const eventData: emitter.EventData = {}; emitter.emit({ eventId: 333 }, eventData); // 发送广播通知更新doSwipBack } goSelectImage() { let selectUris: Array = []; let photoPicker = new photoAccessHelper.PhotoViewPicker(); let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE photoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目 photoPicker.select(photoSelectOptions).then(async (photoSelectResult: photoAccessHelper.PhotoSelectResult) => { //用一个全局变量存储返回的uri selectUris = photoSelectResult.photoUris; console.info('photoViewPicker.select to file succeed and uris are:' + selectUris); //使用fs.openSync接口,通过uri打开这个文件得到fd let file = fileIo.openSync(selectUris[0], fileIo.OpenMode.READ_ONLY); console.info('file fd: ' + file.fd); const timestamp: number = Math.floor(Date.now() / 1000); let name = timestamp + "_homebg" let imagePath = this.context.filesDir + FileUtil.separator + name imagePath = fileUri.getUriFromPath(imagePath) let file2 = fileIo.openSync(imagePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE) fileIo.copyFileSync(file.fd, file2.fd) fileIo.closeSync(file); fileIo.closeSync(file2); this.customizeBgPath = imagePath PreferencesUtil.put(SettingPage.IS_CUSTOMIZE_BG_PATH, this.customizeBgPath) this.sendChangeEvent() }).catch((err: BusinessError) => { console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`); }) } @Builder customizeBgSheet() { Scroll() { Column() { this.CustomizeBg() } } .width('100%') .height('100%') } @Builder CustomizeBg() { Column() { Image(this.customizeBgPath) .height('42%') .alt($r('app.color.white')) .objectFit(ImageFit.Contain) .borderRadius(20) .clip(true) .blur(this.blurValue) .brightness(this.bgBrightness + 0.8) .margin({ left: 30, right: 30, bottom: 20 }) Row() { Row() { Button('选择图片') .fontColor(Color.White) .fontSize(12) .height(48) .width(100) .backgroundColor($r('app.color.title_bar_bg')) .stateEffect(true) .onClick(async () => { this.goSelectImage() }) } .height('100%') .justifyContent(FlexAlign.Center) .layoutWeight(1) } .width('100%') .height(58) .margin({ bottom: 20 }) Column() { Row() { Text('自定义背景:') .margin({ left: 18 }) .fontSize(15) .fontColor($r('app.color.text_color')) .fontWeight(480) .layoutWeight(1) Toggle({ type: ToggleType.Switch, isOn: this.isCustomizeBg }) .selectedColor($r('app.color.tab_item_bg')) .switchPointColor(Color.White) .margin({ right: 18 }) .onChange((checked: boolean) => { this.isCustomizeBg = checked; PreferencesUtil.put(SettingPage.IS_CUSTOMIZE_BG, this.isCustomizeBg) this.sendChangeEvent() }) .width(50) .height(30); } .height(55) } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(15) .margin({ left: 30, right: 30, top: 0, bottom: 20 }) .padding(0) Column() { Row() { Text('背景模糊:') .margin({ left: 18 }) .fontSize(15) .fontColor($r('app.color.text_color')) .fontWeight(480) Slider({ value: this.blurValue, min: 0, max: 100, step: 1, style: SliderStyle.OutSet }) .blockColor(Color.Red) .trackColor($r('app.color.speed_text_color')) .selectedColor($r('app.color.index_background')) .trackThickness(8) .onChange((value: number) => { this.blurValue = value; PreferencesUtil.put(SettingPage.CUSTOMIZE_BG_BLUR, this.blurValue) this.sendChangeEvent() }) .layoutWeight(1) } .height(55) } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(15) .margin({ left: 30, right: 30, top: 0, bottom: 20 }) .padding(0) Column() { Row() { Text('背景亮度:') .margin({ left: 18 }) .fontSize(15) .fontColor($r('app.color.text_color')) .fontWeight(480) Slider({ value: this.bgBrightness, min: -0.4, max: 0.4, step: 0.1, style: SliderStyle.OutSet }) .blockColor(Color.Red) .trackColor($r('app.color.speed_text_color')) .selectedColor($r('app.color.index_background')) .trackThickness(8) .onChange((value: number) => { this.bgBrightness = value; PreferencesUtil.put(SettingPage.BG_BRIGHTNESS, this.bgBrightness) this.sendChangeEvent() }) .layoutWeight(1) } .height(55) } .backgroundColor($r('app.color.settings_background_main')) .borderRadius(15) .margin({ left: 30, right: 30, top: 0, bottom: 20 }) .padding(0) } .margin({ bottom: 30 }) } // 判断当前主题色是否为自定义色 isCustomThemeColor(): boolean { for (let i = 0; i < SettingPage.THEME_COLOR_LIST.length - 1; i++) { if (SettingPage.THEME_COLOR_LIST[i].color === this.themeColor) { return false; } } return true; } } // 主题色类型声明 export interface ThemeColorItem { name: string; color: string; } // 工具函数:将一维数组分成每行2个的二维数组 function chunkArray(arr: Array, size: number): Array> { const result: Array> = []; for (let i = 0; i < arr.length; i += size) { const row: Array = []; for (let j = 0; j < size; j++) { if (i + j < arr.length) { row.push(arr[i + j]); } } result.push(row); } return result; }