From 55002685cc0d0798f33daccbffb194eac08a4b82 Mon Sep 17 00:00:00 2001 From: sunlian Date: Thu, 26 Sep 2024 16:07:36 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=B8=83=E5=B1=80=EF=BC=8C?= =?UTF-8?q?=E7=83=AD=E9=97=A8=E6=8E=A8=E8=8D=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sunlian --- .../main/ets/constants/ServerConstants.ets | 3 +- .../src/main/ets/manager/HttpManager.ets | 101 ++----- .../src/main/ets/manager/PlayerManager.ets | 18 +- .../model/{AudioItem.ets => AudioData.ets} | 2 +- .../entry/src/main/ets/model/PlayListData.ets | 8 +- .../src/main/ets/model/PlayListGroupData.ets | 40 +++ .../entry/src/main/ets/pages/Index.ets | 247 ++---------------- .../view/{PlayList.ets => PlayListDetail.ets} | 12 +- .../entry/src/main/ets/view/PlayListItem.ets | 5 +- .../entry/src/main/ets/view/PlayerBar.ets | 4 +- .../entry/src/main/ets/view/PlayerDetail.ets | 13 +- .../main/ets/view/SingleRowScrollerList.ets | 94 +++++++ .../ets/view/{SongCell.ets => SongItem.ets} | 6 +- .../src/main/ets/view/TriColGridList.ets | 82 ++++++ .../main/ets/view/TriColNestScrollerGrid.ets | 97 +++++++ 15 files changed, 399 insertions(+), 333 deletions(-) rename scenario/MusicPlayerOnline/entry/src/main/ets/model/{AudioItem.ets => AudioData.ets} (96%) create mode 100644 scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListGroupData.ets rename scenario/MusicPlayerOnline/entry/src/main/ets/view/{PlayList.ets => PlayListDetail.ets} (91%) create mode 100644 scenario/MusicPlayerOnline/entry/src/main/ets/view/SingleRowScrollerList.ets rename scenario/MusicPlayerOnline/entry/src/main/ets/view/{SongCell.ets => SongItem.ets} (92%) create mode 100644 scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColGridList.ets create mode 100644 scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColNestScrollerGrid.ets diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets index 87f26ac2f..78e09c1e1 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets @@ -118,8 +118,7 @@ export default class ServerConstants { static readonly UPDATE_USER_LIST_CUSTOM = '81'; static readonly UPDATE_USER_LIST_RECENT = '82'; static readonly UPDATE_USER_LIST_FAVOR = '83'; - static readonly UPDATE_USER_LIST_SINGER = '84'; - static readonly UPDATE_USER_LIST_SEARCH = '85'; + static readonly UPDATE_USER_LIST_SEARCH = '84'; //首页登录更新消息 static readonly LOGIN_RESULT = '9' diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/manager/HttpManager.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/manager/HttpManager.ets index 594112761..ac4f64fc8 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/manager/HttpManager.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/manager/HttpManager.ets @@ -17,8 +17,9 @@ import ServerConstants from '../constants/ServerConstants'; import emitter from '@ohos.events.emitter'; import PlayerManager from './PlayerManager'; import prompt from '@ohos.promptAction'; -import AudioItem from '../model/AudioItem'; +import AudioData from '../model/AudioData'; import PlayListData from '../model/PlayListData'; +import PlayListGroupData from '../model/PlayListGroupData'; // 单例对象 HttpManager export default class HttpManager { @@ -375,16 +376,21 @@ export default class HttpManager { let isStart = true; const jsonObject: object = JSON.parse(data.result as string); Object.keys(jsonObject).forEach((key) => { - let aPlayingList: AudioItem[] = Array(); - Object.keys(jsonObject[key]).forEach((key2) => { - aPlayingList.push(new AudioItem(jsonObject[key][key2].name, jsonObject[key][key2].singer, jsonObject[key][key2].id)); - }) - let item = new PlayListData(key, $r('app.media.icon'), aPlayingList.length + ServerConstants.LIST_SONG_COUNT, - aPlayingList, '') + let playingLists: PlayListData[] = []; + Object.keys(jsonObject[key]).forEach((key1) => { + let aPlayingList: AudioData[] = []; + Object.keys(jsonObject[key][key1]).forEach((key2) => { + aPlayingList.push(new AudioData(jsonObject[key][key1][key2].name, jsonObject[key][key1][key2].singer, jsonObject[key][key1][key2].id)); + }) + let item = new PlayListData(key1, $r('app.media.icon'), + aPlayingList.length > 1 ? aPlayingList.length + ServerConstants.LIST_SONG_COUNT : '', + aPlayingList, '') + playingLists.push(item); + }); let eventData: emitter.EventData = { data: { "message": ServerConstants.UPDATE_USER_LIST_RECOMMEND, - "item": item, + "item": new PlayListGroupData(key, playingLists), "isStart": isStart, } }; @@ -395,7 +401,6 @@ export default class HttpManager { catch (error) { console.error("JSON :", error.message); } - this.getSingerListFromServer(); console.info('HttpResponse code:' + data.responseCode); console.info('HttpResponse type:' + JSON.stringify(data.resultType)); console.info('HttpResponse header:' + JSON.stringify(data.header)); @@ -415,59 +420,6 @@ export default class HttpManager { } } - //获取推荐歌手 - getSingerListFromServer() { - try { - this.httpRequest.request(ServerConstants.SINGER_LIST_URL, - { - method: http.RequestMethod.GET, - header: { - 'Cookie': AppStorage.get('loginCookie') - } - }, - (err: Error, data: http.HttpResponse) => { - if (!err) { - console.info('HttpResponse getSingerListFromServer Result:' + data.result); - try { - const jsonObject: object = JSON.parse(data.result as string); - let isStart = true; - Object.keys(jsonObject).forEach((key) => { - let aPlayingList: AudioItem[] = Array(); - Object.keys(jsonObject[key]).forEach((key2) => { - aPlayingList.push(new AudioItem(jsonObject[key][key2].name, jsonObject[key][key2].singer, jsonObject[key][key2].id)); - }); - let item = new PlayListData(key, $r('app.media.icon'), aPlayingList.length + ServerConstants.LIST_SONG_COUNT, - aPlayingList, '') - let eventData: emitter.EventData = { - data: { - "message": ServerConstants.UPDATE_USER_LIST_SINGER, - "item": item, - "isStart": isStart, - } - }; - emitter.emit(ServerConstants.UPDATE_USER_LIST, this.emitterOptions, eventData); - isStart = false; - }); - } - catch (error) { - console.error("JSON :", error.message); - } - console.info('HttpResponse code:' + data.responseCode); - console.info('HttpResponse type:' + JSON.stringify(data.resultType)); - console.info('HttpResponse header:' + JSON.stringify(data.header)); - console.info('HttpResponse cookies:' + data.cookies); - } else { - console.info('HttpResponse error:' + JSON.stringify(err)); - prompt.showToast({ - message: JSON.stringify(err) - }) - } - }); - } catch (err) { - console.info('HttpRequest error:' + JSON.stringify(err)); - } - } - //获取我的收藏 getFavorListFromServer() { try { @@ -482,14 +434,15 @@ export default class HttpManager { if (!err) { console.info('HttpResponse getFavorListFromServer Result:' + data.result); try { - let aPlayingList: AudioItem[] = Array(); + let aPlayingList: AudioData[] = Array(); const jsonObject: object = JSON.parse(data.result as string); let item: PlayListData | undefined = undefined; if (jsonObject[ServerConstants.LIST_SONG_FAVOURITE]) { Object.keys(jsonObject[ServerConstants.LIST_SONG_FAVOURITE]).forEach((key) => { - aPlayingList.push(new AudioItem(jsonObject[ServerConstants.LIST_SONG_FAVOURITE][key].name, jsonObject[ServerConstants.LIST_SONG_FAVOURITE][key].singer, jsonObject[ServerConstants.LIST_SONG_FAVOURITE][key].id)); + aPlayingList.push(new AudioData(jsonObject[ServerConstants.LIST_SONG_FAVOURITE][key].name, jsonObject[ServerConstants.LIST_SONG_FAVOURITE][key].singer, jsonObject[ServerConstants.LIST_SONG_FAVOURITE][key].id)); }); - item = new PlayListData(ServerConstants.LIST_SONG_FAVOURITE, $r('app.media.icon'), aPlayingList.length + ServerConstants.LIST_SONG_COUNT, + item = new PlayListData(ServerConstants.LIST_SONG_FAVOURITE, $r('app.media.icon'), + aPlayingList.length > 1 ? aPlayingList.length + ServerConstants.LIST_SONG_COUNT : '', aPlayingList, '') } this.PlayerManager.setFavourList(aPlayingList); @@ -540,12 +493,13 @@ export default class HttpManager { const jsonObject: object = JSON.parse(data.result as string); let isStart = true; Object.keys(jsonObject).forEach((key) => { - let aPlayingList: AudioItem[] = Array(); + let aPlayingList: AudioData[] = Array(); Object.keys(jsonObject[key]).forEach((key2) => { - aPlayingList.push(new AudioItem(jsonObject[key][key2].name, jsonObject[key][key2].singer, jsonObject[key][key2].id)); + aPlayingList.push(new AudioData(jsonObject[key][key2].name, jsonObject[key][key2].singer, jsonObject[key][key2].id)); }); - let item = new PlayListData(key, $r('app.media.icon'), aPlayingList.length + ServerConstants.LIST_SONG_COUNT, + let item = new PlayListData(key, $r('app.media.icon'), + aPlayingList.length > 1 ? aPlayingList.length + ServerConstants.LIST_SONG_COUNT : '', aPlayingList, ''); let eventData: emitter.EventData = { data: { @@ -615,12 +569,13 @@ export default class HttpManager { let isStart = true; keys.forEach((playlistName) => { console.log(`Playlist: ${playlistName}`); - let aPlayingList: AudioItem[] = Array(); + let aPlayingList: AudioData[] = Array(); groupedByPlaylistName[playlistName].forEach((song, index) => { - aPlayingList.push(new AudioItem(song.name, song.singer, song.id.toString())); + aPlayingList.push(new AudioData(song.name, song.singer, song.id.toString())); }); - let item = new PlayListData(playlistName, $r('app.media.icon'), aPlayingList.length + ServerConstants.LIST_SONG_COUNT, + let item = new PlayListData(playlistName, $r('app.media.icon'), + aPlayingList.length > 1 ? aPlayingList.length + ServerConstants.LIST_SONG_COUNT : '', aPlayingList, '') let eventData: emitter.EventData = { data: { @@ -668,8 +623,8 @@ export default class HttpManager { let isStart = true; Object.keys(jsonObject).forEach((key) => { Object.keys(jsonObject[key]).forEach((key2) => { - let aPlayingList: AudioItem[] = Array(); - let aAudioItem = new AudioItem(jsonObject[key][key2].name, jsonObject[key][key2].singer, jsonObject[key][key2].id) + let aPlayingList: AudioData[] = Array(); + let aAudioItem = new AudioData(jsonObject[key][key2].name, jsonObject[key][key2].singer, jsonObject[key][key2].id) aPlayingList.push(aAudioItem); let item = new PlayListData(jsonObject[key][key2].name, $r('app.media.icon'), '', aPlayingList, '') let eventData: emitter.EventData = { diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets index 7e65f9b75..cf80333ef 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets @@ -15,7 +15,7 @@ import media from '@ohos.multimedia.media'; import { BusinessError } from '@ohos.base'; -import AudioItem from '../model/AudioItem'; +import AudioData from '../model/AudioData'; import Logger from '../utils/Logger'; import emitter from '@ohos.events.emitter'; import ServerConstants from '../constants/ServerConstants'; @@ -30,11 +30,11 @@ export default class PlayerManager { private tag: string = 'PlayerManager'; private isSeek: boolean = false; private avPlayer: media.AVPlayer | undefined = undefined; - private list: AudioItem[] = []; - private favourList: AudioItem[] = []; + private list: AudioData[] = []; + private favourList: AudioData[] = []; private currentTime: number = 0; private currentDuration: number = 0; - private item: AudioItem = new AudioItem('', '', ''); + private item: AudioData = new AudioData('', '', ''); private listPosition: number = 0; private state: string = ServerConstants.PLAYER_STATE_UNKNOWN; private listTitle: string = ServerConstants.LIST_SONG_NO_PLAYING; @@ -143,7 +143,7 @@ export default class PlayerManager { /** * 初始化 */ - playList(listTitle: string, list: AudioItem[], item: AudioItem): void { + playList(listTitle: string, list: AudioData[], item: AudioData): void { this.stop(); if (list.length <= 0) { Logger.error(this.tag, 'PlayList:' + 'list length <= 0'); @@ -159,7 +159,7 @@ export default class PlayerManager { this.play(item); } - getCurrentPlayList(): AudioItem[] { + getCurrentPlayList(): AudioData[] { return this.list; } @@ -177,7 +177,7 @@ export default class PlayerManager { /** * 播放 */ - play(item: AudioItem): void { + play(item: AudioData): void { Logger.info(this.tag, 'Play finish:' + this.listPosition.toString()); if (this.item) { this.item.isPlaying = false; @@ -315,7 +315,7 @@ export default class PlayerManager { return this.playMode; } - getItem(): AudioItem { + getItem(): AudioData { return this.item; } @@ -361,7 +361,7 @@ export default class PlayerManager { this.favourList = []; } - setFavourList(list: AudioItem[]) { + setFavourList(list: AudioData[]) { this.favourList = list; } diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/model/AudioItem.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/model/AudioData.ets similarity index 96% rename from scenario/MusicPlayerOnline/entry/src/main/ets/model/AudioItem.ets rename to scenario/MusicPlayerOnline/entry/src/main/ets/model/AudioData.ets index b53eaef22..6accefa14 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/model/AudioItem.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/model/AudioData.ets @@ -17,7 +17,7 @@ * AudioItem data entity. */ -export default class AudioItem { +export default class AudioData { title: string = ''; artist: string = ''; id: string = '' diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListData.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListData.ets index a5ba54331..530d62ebb 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListData.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListData.ets @@ -12,12 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import AudioItem from './AudioItem'; +import AudioData from './AudioData'; /** * List item data entity. */ -export default class PlayList { +export default class PlayListData { /** * Text of list item. */ @@ -31,9 +31,9 @@ export default class PlayList { */ others?: string; subTitle: string - list: AudioItem[] = [] + list: AudioData[] = [] - constructor(title: string, img: Resource, subTitle: string, list: AudioItem[], others?: string) { + constructor(title: string, img: Resource, subTitle: string, list: AudioData[], others?: string) { this.title = title; this.img = img; this.others = others; diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListGroupData.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListGroupData.ets new file mode 100644 index 000000000..3c58f5813 --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/model/PlayListGroupData.ets @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import AudioData from './AudioData'; +import PlayListData from './PlayListData'; + +/** + * List item data entity. + */ +export default class PlayListGroupData { + /** + * Text of list item. + */ + title: string; + /** + * Image of list item. + */ + lists: PlayListData[] = []; + /** + * Other resource of list item. + */ + type?: string; + + constructor(title: string, lists: PlayListData[], type?: string) { + this.title = title; + this.lists = lists; + this.type = type; + } +} \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/pages/Index.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/pages/Index.ets index 7e58bb29c..6c95bdae1 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/pages/Index.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/pages/Index.ets @@ -14,17 +14,20 @@ */ import PlayerBar from '../view/PlayerBar'; -import PlayList from '../view/PlayList'; -import PlayListItem from '../view/PlayListItem'; +import PlayListDetail from '../view/PlayListDetail'; import ServerConstants from '../constants/ServerConstants'; import UIConstants from '../constants/UIConstants'; import PlayListData from '../model/PlayListData'; +import PlayListGroupData from '../model/PlayListGroupData'; import PlayerDetail from '../view/PlayerDetail'; import emitter from '@ohos.events.emitter'; import prompt from '@ohos.promptAction'; import Setting from '../view/Setting'; import { LoginCustomDialog } from '../view/loginDialog'; import HttpManager from '../manager/HttpManager'; +import SingleRowScrollerList from '../view/SingleRowScrollerList'; +import TriColGridList from '../view/TriColGridList'; +import TriColNestScrollerGrid from '../view/TriColNestScrollerGrid'; PersistentStorage.persistProp('loginCookie', ''); PersistentStorage.persistProp('loginName', ServerConstants.LOGIN_INFO_NO); @@ -32,10 +35,9 @@ PersistentStorage.persistProp('loginName', ServerConstants.LOGIN_INFO_NO); @Entry @Component struct Index { - @State recommendPlayLists: PlayListData[] = []; + @State recommendPlayLists: PlayListGroupData[] = []; @State customPlayLists: PlayListData[] = []; @State searchResultPlayLists: PlayListData[] = []; - @State singerList: PlayListData[] = []; @State searchSongTitle: string = ServerConstants.SEARCH_DEFAULT; @State isShowPlayerDetail: boolean = false; @State isShowPlayList: boolean = false; @@ -46,14 +48,10 @@ struct Index { @State maskOpacity: number = 0.5; @State loginInfo: string = ServerConstants.LOGIN_INFO_NO; @State loginButton: string = ServerConstants.LOGIN_BUTTON_IN; - @State rowAngle: number = 0; @State colAngle: number = 0; - @State SingerAngle: number = 0; @State isShowSidebar: boolean = false; - private rowScroller: Scroller = new Scroller(); - private colScroller: Scroller = new Scroller() private rootScroller: Scroller = new Scroller() - private singerListClickable: boolean = true; + private colScroller: Scroller = new Scroller(); @State inputUserName: string = '' @State inputPwd: string = '' @State inputPwd2: string = '' @@ -216,210 +214,21 @@ struct Index { }) { Scroll(this.rootScroller) { Column() { - Row() { - Text($r('app.string.recommend_list')) - .fontSize('20fp') - .fontWeight(FontWeight.Medium) - Image($r('app.media.chevron_right_2')) - .objectFit(ImageFit.Contain) - .width(48) - .height(48) - .padding(8) - .rotate({ angle: this.rowAngle }) - .id('scroll_row') - .clickEffect(UIConstants.CLICK_EFFECT) - .onClick(() => { - animateTo({ duration: 1000 }, () => { - if (this.rowAngle === 0) { - this.rowScroller.scrollEdge(Edge.End) - this.rowAngle = 180; - } else { - this.rowScroller.scrollEdge(Edge.Start) - this.rowAngle = 0; - } - }) - }) - } - .height(36) - .justifyContent(FlexAlign.SpaceBetween) - .width('90%') - .margin(12) - - Scroll(this.rowScroller) { - Row() { - ForEach(this.recommendPlayLists, (item: PlayListData) => { - PlayListItem({ item }).margin({ left: 12, right: 12 }) - .transition({ type: TransitionType.All, opacity: 0 }) - }) - } - .margin(12) - } - .scrollable(ScrollDirection.Horizontal) - .scrollBar(BarState.Off) - .edgeEffect(EdgeEffect.Spring) - .width('100%') - .onReachEnd(() => { - animateTo({ duration: 1000 }, () => { - this.rowAngle = 180; - }) - }) - .onReachStart(() => { - animateTo({ duration: 1000 }, () => { - this.rowAngle = 0; - }) - }) if (this.searchSongTitle !== ServerConstants.SEARCH_DEFAULT) { - Row() { - Text(this.searchSongTitle) - .fontSize('20fp') - .fontWeight(FontWeight.Medium) - .transition(TransitionEffect.OPACITY.animation({ duration: 2000, curve: Curve.Ease })) - Image($r('app.media.xmark_circle')) - .objectFit(ImageFit.Contain) - .width(48) - .height(48) - .padding(8) - .transition(TransitionEffect.OPACITY.animation({ duration: 2000, curve: Curve.Ease }).combine( - TransitionEffect.rotate({ z: 1, angle: 180 }) - )) - .clickEffect(UIConstants.CLICK_EFFECT) - .onClick(() => { - animateTo({ duration: 1000 }, () => { - this.searchSongTitle = ServerConstants.SEARCH_DEFAULT; - this.searchResultPlayLists = []; - }) - }) - } - .height(36) - .justifyContent(FlexAlign.SpaceBetween) - .width('90%') - .margin(12) - - Grid() { - ForEach(this.searchResultPlayLists, (item: PlayListData) => { - GridItem() { - PlayListItem({ item }) - } - .id('search_list_item') - .transition({ type: TransitionType.All, opacity: 0 }) - }) - } - .margin(12) - .columnsTemplate('1fr 1fr 1fr') - .columnsGap(8) - .rowsGap(12) - .width('90%') - } - Row() { - Text($r('app.string.singer_list')) - .fontSize('20fp') - .fontWeight(FontWeight.Medium) - .transition(TransitionEffect.OPACITY.animation({ duration: 2000, curve: Curve.Ease })) - if (this.singerListClickable) { - Image($r('app.media.chevron_down_2')) - .objectFit(ImageFit.Contain) - .width(48) - .height(48) - .padding(8) - .rotate({ angle: this.SingerAngle }) - .clickEffect(UIConstants.CLICK_EFFECT) - .onClick(() => { - if (!this.singerListClickable) { - return; - } - this.singerListClickable = false; - setTimeout(() => { - this.singerListClickable = true; - }, 2000) - animateTo({ duration: 1000 }, () => { - if (this.singerList.length > 0) { - animateTo( - { duration: 1000 }, - () => { - this.SingerAngle = 0; - this.singerList = []; - }) - } else { - HttpManager.getInstance().getSingerListFromServer(); - } - }) - }) - } + TriColGridList({ title: this.searchSongTitle, playLists: this.searchResultPlayLists }) } - .height(36) - .justifyContent(FlexAlign.SpaceBetween) - .width('90%') - .margin(12) - - Grid() { - ForEach(this.singerList, (item: PlayListData) => { - GridItem() { - PlayListItem({ item }) - } - .id('search_list_item') - .transition({ type: TransitionType.All, opacity: 0 }) - }) - } - .margin(12) - .columnsTemplate('1fr 1fr 1fr') - .columnsGap(8) - .rowsGap(12) - .width('90%') - - Row() { - Text($r('app.string.my_list')) - .fontSize('20fp') - .fontWeight(FontWeight.Medium) - Image($r('app.media.chevron_down_2')) - .objectFit(ImageFit.Contain) - .width(48) - .height(48) - .padding(8) - .id('scroll_col') - .rotate({ angle: this.colAngle }) - .clickEffect(UIConstants.CLICK_EFFECT) - .onClick(() => { - animateTo({ duration: 1000 }, () => { - if (this.colAngle === 0) { - if (!this.rootScroller.isAtEnd()) { - this.colAngle = 180; - this.rootScroller.scrollEdge(Edge.Bottom); - } - } else { - if (this.rootScroller.currentOffset().yOffset !== 0) { - this.colAngle = 0; - this.rootScroller.scrollEdge(Edge.Top); - } - } - }) - }) - } - .height(36) - .justifyContent(FlexAlign.SpaceBetween) - .width('90%') - .margin(12) + ForEach(this.recommendPlayLists, (item: PlayListGroupData) => { + SingleRowScrollerList({ title: item.title, playLists: item.lists }) + }) - Grid(this.colScroller) { - ForEach(this.customPlayLists, (item: PlayListData) => { - GridItem() { - PlayListItem({ item }) - } - .id('my_list_item') - .transition({ type: TransitionType.All, opacity: 0 }) - }) - } - .margin(12) - .columnsTemplate('1fr 1fr 1fr') - .columnsGap(8) - .rowsGap(12) - .scrollBar(BarState.Off) - .width('90%') - .height('75%') - .nestedScroll({ - scrollForward: NestedScrollMode.PARENT_FIRST, - scrollBackward: NestedScrollMode.SELF_FIRST + TriColNestScrollerGrid({ + title: '我的歌单', + colAngle: this.colAngle, + rootScroller: this.rootScroller, + colScroller: this.colScroller, + playLists: this.customPlayLists, }) } } @@ -495,7 +304,7 @@ struct Index { .transition(TransitionEffect.OPACITY.animation({ duration: 1000, curve: Curve.Ease })) } if (this.isShowPlayList) { - PlayList() + PlayListDetail() .width('100%') .height('80%') .transition(TransitionEffect.OPACITY @@ -606,8 +415,8 @@ struct Index { { duration: 1000 }, () => { if (eventData.data !== undefined && eventData.data.item !== undefined) { - console.info('UPDATE_USER_LIST_RECOMMEND:' + (eventData.data.item as PlayListData).title); - this.recommendPlayLists.push(eventData.data.item as PlayListData); + console.info('UPDATE_USER_LIST_RECOMMEND:' + (eventData.data.item as PlayListGroupData).title); + this.recommendPlayLists.push(eventData.data.item as PlayListGroupData); } }) break; @@ -676,22 +485,6 @@ struct Index { } }) break; - case ServerConstants.UPDATE_USER_LIST_SINGER: - if (eventData.data.isStart) { - animateTo({ duration: 2000 }, () => { - this.singerList = [] - }) - } - animateTo( - { duration: 1000 }, - () => { - if (eventData.data !== undefined && eventData.data.item !== undefined) { - console.info('UPDATE_USER_LIST_SINGER:' + (eventData.data.item as PlayListData).title); - this.singerList.push(eventData.data.item as PlayListData); - this.SingerAngle = 180; - } - }) - break; default: break; } diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayList.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListDetail.ets similarity index 91% rename from scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayList.ets rename to scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListDetail.ets index 26ae890bd..365252ca0 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayList.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListDetail.ets @@ -13,17 +13,17 @@ * limitations under the License. */ -import AudioItem from '../model/AudioItem'; +import AudioData from '../model/AudioData'; import PlayerManager from '../manager/PlayerManager' -import SongCell from './SongCell'; +import SongItem from './SongItem'; import emitter from '@ohos.events.emitter'; import ServerConstants from '../constants/ServerConstants'; import UIConstants from '../constants/UIConstants'; @Component -export default struct PlayList { +export default struct PlayListDetail { private playerManager: PlayerManager = AppStorage.get('PlayerManager') as PlayerManager; - @State playingList: AudioItem[] = Array(); + @State playingList: AudioData[] = Array(); @State listTitle: string = ServerConstants.LIST_SONG_NO_PLAYING; private scrollerForList: Scroller = new Scroller(); @@ -53,9 +53,9 @@ export default struct PlayList { .maxLines(1) .textOverflow({ overflow: TextOverflow.MARQUEE }) List({ scroller: this.scrollerForList }) { - ForEach(this.playingList, (item: AudioItem) => { + ForEach(this.playingList, (item: AudioData) => { ListItem() { - SongCell({ item }) + SongItem({ item }) } .width('100%') .height('84vp') diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListItem.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListItem.ets index 4d84ee4c4..9f1003b66 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListItem.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayListItem.ets @@ -55,8 +55,11 @@ export default struct PlayListItem { .justifyContent(FlexAlign.SpaceBetween) Text(this.item.title) - .fontSize('20fp') + .fontSize(20) .maxLines(1) + .textOverflow({overflow:TextOverflow.MARQUEE}) + .width(120) + .textAlign(TextAlign.Center) .margin({ top: 4 }) } .alignItems(HorizontalAlign.Center) diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerBar.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerBar.ets index e38eeba43..ac2dc985c 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerBar.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerBar.ets @@ -18,7 +18,7 @@ */ import emitter from '@ohos.events.emitter'; import Logger from '../utils/Logger'; -import AudioItem from '../model/AudioItem'; +import AudioData from '../model/AudioData'; import ServerConstants from '../constants/ServerConstants'; import UIConstants from '../constants/UIConstants'; import PlayerManager from '../manager/PlayerManager'; @@ -26,7 +26,7 @@ import PlayerManager from '../manager/PlayerManager'; @Component export default struct PlayerBar { private tag: string = 'PlayerBar'; - @State item: AudioItem = new AudioItem('', '', '') + @State item: AudioData = new AudioData('', '', '') @State rotateAngle: number = 0; @State durationTime: number = 100; @State currentTime: number = 0; diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerDetail.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerDetail.ets index 12ea409a8..710ddb5b0 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerDetail.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/PlayerDetail.ets @@ -20,7 +20,7 @@ import LrcLine from '../model/LrcLine'; import CommonUtils from '../utils/CommonUtils'; import ServerConstants from '../constants/ServerConstants'; import UIConstants from '../constants/UIConstants'; -import AudioItem from '../model/AudioItem'; +import AudioData from '../model/AudioData'; import { PLAY_MODE } from '../constants/PlayMode'; import { addToListDialog } from './addToListDialog'; import PlayListData from '../model/PlayListData'; @@ -34,7 +34,7 @@ import HttpManager from '../manager/HttpManager'; export default struct PlayerDetail { private tag: string = 'PlayerDetail'; private PlayerManager: PlayerManager = AppStorage.get('PlayerManager') as PlayerManager; - @State item: AudioItem = this.PlayerManager.getItem(); + @State item: AudioData = this.PlayerManager.getItem(); @State listTitle: string = this.PlayerManager.getListTitle(); @State durationTime: number = 0; @State currentTime: number = 0; @@ -163,7 +163,9 @@ export default struct PlayerDetail { Column() { Row() { Image($r('app.media.chevron_down')) - .width('36vp') + .width(48) + .height(48) + .padding(6) .clickEffect(UIConstants.CLICK_EFFECT) .onClick(() => { this.isShowPlayerDetail = false; @@ -200,8 +202,9 @@ export default struct PlayerDetail { .height('60vp') Image($r('app.media.folder_badge_plus')) - .height('36vp') - .width('36vp') + .width(48) + .height(48) + .padding(8) .clickEffect(UIConstants.CLICK_EFFECT) .onClick(() => { if (this.loginInfo === ServerConstants.LOGIN_INFO_NO) { diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/SingleRowScrollerList.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/SingleRowScrollerList.ets new file mode 100644 index 000000000..e13722646 --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/SingleRowScrollerList.ets @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * SingleRowList component. + * 单行横向滚动组件 + */ + +import UIConstants from '../constants/UIConstants'; +import PlayListData from '../model/PlayListData'; +import PlayListItem from './PlayListItem'; + +@Component +export default struct SingleRowScrollerList { + @State arrowAngle: number = 0; + @Prop playLists: PlayListData[] = []; + @Prop title: string = '推荐歌单' + private rowScroller: Scroller = new Scroller(); + + aboutToAppear() { + } + + aboutToDisappear() { + } + + build() { + Column() { + Row() { + Text(this.title) + .fontSize('20fp') + .fontWeight(FontWeight.Medium) + Image($r('app.media.chevron_right_2')) + .objectFit(ImageFit.Contain) + .width(48) + .height(48) + .padding(8) + .rotate({ angle: this.arrowAngle }) + .id('scroll_row') + .clickEffect(UIConstants.CLICK_EFFECT) + .onClick(() => { + animateTo({ duration: 1000 }, () => { + if (this.arrowAngle === 0) { + this.rowScroller.scrollEdge(Edge.End) + this.arrowAngle = 180; + } else { + this.rowScroller.scrollEdge(Edge.Start) + this.arrowAngle = 0; + } + }) + }) + } + .height(36) + .justifyContent(FlexAlign.SpaceBetween) + .width('90%') + .margin(12) + + Scroll(this.rowScroller) { + Row() { + ForEach(this.playLists, (item: PlayListData) => { + PlayListItem({ item }).margin({ left: 12, right: 12 }) + .transition({ type: TransitionType.All, opacity: 0 }) + }) + } + .margin(12) + } + .scrollable(ScrollDirection.Horizontal) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.Spring) + .width('100%') + .onReachEnd(() => { + animateTo({ duration: 1000 }, () => { + this.arrowAngle = 180; + }) + }) + .onReachStart(() => { + animateTo({ duration: 1000 }, () => { + this.arrowAngle = 0; + }) + }) + } + } +} \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/SongCell.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/SongItem.ets similarity index 92% rename from scenario/MusicPlayerOnline/entry/src/main/ets/view/SongCell.ets rename to scenario/MusicPlayerOnline/entry/src/main/ets/view/SongItem.ets index 476f6ebf3..b4fc59a01 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/view/SongCell.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/SongItem.ets @@ -13,12 +13,12 @@ * limitations under the License. */ -import AudioItem from '../model/AudioItem'; +import AudioData from '../model/AudioData'; import ServerConstants from '../constants/ServerConstants'; @Component -export default struct SongCell { - @State item: AudioItem = new AudioItem('', '', ''); +export default struct SongItem { + @State item: AudioData = new AudioData('', '', ''); private spaces: string = ' ' build() { diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColGridList.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColGridList.ets new file mode 100644 index 000000000..da3b7ba19 --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColGridList.ets @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import ServerConstants from '../constants/ServerConstants'; + +/** + * TriColGridList component. + * 三列竖向Grid列表 + */ + +import UIConstants from '../constants/UIConstants'; +import PlayListData from '../model/PlayListData'; +import PlayListItem from './PlayListItem'; + +@Component +export default struct TriColGridList { + @State arrowAngle: number = 0; + @Prop playLists: PlayListData[] = []; + @Link title: string; + + aboutToAppear() { + } + + aboutToDisappear() { + } + + build() { + Column() { + Row() { + Text(this.title) + .fontSize('20fp') + .fontWeight(FontWeight.Medium) + .transition(TransitionEffect.OPACITY.animation({ duration: 2000, curve: Curve.Ease })) + Image($r('app.media.xmark_circle')) + .objectFit(ImageFit.Contain) + .width(48) + .height(48) + .padding(8) + .transition(TransitionEffect.OPACITY.animation({ duration: 2000, curve: Curve.Ease }).combine( + TransitionEffect.rotate({ z: 1, angle: 180 }) + )) + .clickEffect(UIConstants.CLICK_EFFECT) + .onClick(() => { + animateTo({ duration: 1000 }, () => { + this.title = ServerConstants.SEARCH_DEFAULT; + this.playLists = []; + }) + }) + } + .height(36) + .justifyContent(FlexAlign.SpaceBetween) + .width('90%') + .margin(12) + + Grid() { + ForEach(this.playLists, (item: PlayListData) => { + GridItem() { + PlayListItem({ item }) + } + .id('search_list_item') + .transition({ type: TransitionType.All, opacity: 0 }) + }) + } + .margin(12) + .columnsTemplate('1fr 1fr 1fr') + .columnsGap(8) + .rowsGap(12) + .width('90%') + } + } +} \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColNestScrollerGrid.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColNestScrollerGrid.ets new file mode 100644 index 000000000..9655b54e4 --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/view/TriColNestScrollerGrid.ets @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import ServerConstants from '../constants/ServerConstants'; + +/** + * TriColNestScrollerGridList component. + * 三列竖向联动滚动Grid列表 + */ + +import UIConstants from '../constants/UIConstants'; +import PlayListData from '../model/PlayListData'; +import PlayListItem from './PlayListItem'; + +@Component +export default struct TriColNestScrollerGrid { + @Prop playLists: PlayListData[] = []; + @Prop title: string = '我的歌单'; + @Link colAngle: number; + private colScroller: Scroller = new Scroller(); + private rootScroller: Scroller = new Scroller(); + + aboutToAppear() { + } + + aboutToDisappear() { + } + + build() { + Column() { + Row() { + Text(this.title) + .fontSize('20fp') + .fontWeight(FontWeight.Medium) + Image($r('app.media.chevron_down_2')) + .objectFit(ImageFit.Contain) + .width(48) + .height(48) + .padding(8) + .id('scroll_col') + .rotate({ angle: this.colAngle }) + .clickEffect(UIConstants.CLICK_EFFECT) + .onClick(() => { + animateTo({ duration: 1000 }, () => { + if (this.colAngle === 0) { + if (!this.rootScroller.isAtEnd()) { + this.colAngle = 180; + this.rootScroller.scrollEdge(Edge.Bottom); + } + } else { + if (this.rootScroller.currentOffset().yOffset !== 0) { + this.colAngle = 0; + this.rootScroller.scrollEdge(Edge.Top); + } + } + }) + }) + } + .height(36) + .justifyContent(FlexAlign.SpaceBetween) + .width('90%') + .margin(12) + + Grid(this.colScroller) { + ForEach(this.playLists, (item: PlayListData) => { + GridItem() { + PlayListItem({ item }) + } + .id('my_list_item') + .transition({ type: TransitionType.All, opacity: 0 }) + }) + } + .margin(12) + .columnsTemplate('1fr 1fr 1fr') + .columnsGap(8) + .rowsGap(12) + .scrollBar(BarState.Off) + .width('90%') + .height('75%') + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.SELF_FIRST + }) + } + } +} \ No newline at end of file -- Gitee