|
@@ -1,2560 +0,0 @@
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-import router from '@ohos.router';
|
|
|
|
|
-import { BusinessError, Callback } from '@ohos.base';
|
|
|
|
|
-import { IjkMediaPlayer, InterruptEvent, InterruptHintType } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnPreparedListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnVideoSizeChangedListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnCompletionListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnBufferingUpdateListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnErrorListener, OnTimedTextListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnInfoListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { OnSeekCompleteListener } from '@ohos/ijkplayer';
|
|
|
|
|
-import { LogUtils } from '@ohos/ijkplayer';
|
|
|
|
|
-import prompt from '@ohos.promptAction';
|
|
|
|
|
-import { PlayStatus } from '../common/PlayStatus';
|
|
|
|
|
-import { RouterParam } from './RouterParam';
|
|
|
|
|
-import { VideoItem } from '../viewmodel/VideoItem';
|
|
|
|
|
-import { CommonConstants } from '../common/constants/CommonConstants';
|
|
|
|
|
-import { PlayConstants } from '../common/constants/PlayConstants';
|
|
|
|
|
-import { ArrayUtil, DialogUtil, DisplayUtil, GlobalContext,
|
|
|
|
|
- ImageUtil,
|
|
|
|
|
- LogUtil,
|
|
|
|
|
- PreferencesUtil,
|
|
|
|
|
- RandomUtil,
|
|
|
|
|
- StrUtil,
|
|
|
|
|
- ToastUtil } from '@pura/harmony-utils';
|
|
|
|
|
-import { BubbleBean } from '../viewmodel/BubbleBean';
|
|
|
|
|
-import { PopupPosition, XPopup } from '@chinalike/popup';
|
|
|
|
|
-import { display, promptAction, window } from '@kit.ArkUI';
|
|
|
|
|
-import Logger from '../common/util/Logger';
|
|
|
|
|
-import { PiPWindow } from '@kit.ArkUI';
|
|
|
|
|
-import { AnimationHelper, DialogHelper } from '@pura/harmony-dialog';
|
|
|
|
|
-import fs from '@ohos.file.fs';
|
|
|
|
|
-import { AvSessionController } from '../controller/AvSessionController';
|
|
|
|
|
-import { AVCastPicker, AVCastPickerState, avSession } from '@kit.AVSessionKit';
|
|
|
|
|
-import { CommonConstants2 } from '../common/util/CommonConstants2';
|
|
|
|
|
-import { secondToTime } from '../common/util/CommUtils';
|
|
|
|
|
-import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
|
|
|
-import { SettingPage } from './SettingPage';
|
|
|
|
|
-import { BackgroundTaskManager } from '../common/util/BackgroundTaskManager';
|
|
|
|
|
-import { Utility } from '../common/util/Utility';
|
|
|
|
|
-import { ColorConversion } from '../common/util/ColorConversion';
|
|
|
|
|
-import { image } from '@kit.ImageKit';
|
|
|
|
|
-import { common } from '@kit.AbilityKit';
|
|
|
|
|
-import { effectKit } from '@kit.ArkGraphics2D';
|
|
|
|
|
-import { FileParser, LyricController, LyricParser, LyricView2 } from '@seagazer/cclyric';
|
|
|
|
|
-import { fileIo, picker } from '@kit.CoreFileKit';
|
|
|
|
|
-import * as chardet from '@changwei/chardet';
|
|
|
|
|
-import { util } from '@kit.ArkTS';
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-const TAG = 'onecold MusicPlayer';
|
|
|
|
|
-
|
|
|
|
|
-interface GeneratedObjectLiteralInterface_1 {
|
|
|
|
|
- assetId: string;
|
|
|
|
|
- title: string;
|
|
|
|
|
- artist: string;
|
|
|
|
|
-
|
|
|
|
|
- // 网络资源投播,设置mediaUri; 本地资源投播,将本地文件打开后,相关的文件描述符设置到fdSrc
|
|
|
|
|
- mediaUri: string;
|
|
|
|
|
-
|
|
|
|
|
- // 该字段大写,音频'AUDIO',视频'VIDEO'
|
|
|
|
|
- mediaType: string;
|
|
|
|
|
- mediaSize: number;
|
|
|
|
|
-
|
|
|
|
|
- //startPosition为投播当前进度,设置该字段可将本机播放进度同步到远端
|
|
|
|
|
- startPosition: number;
|
|
|
|
|
-
|
|
|
|
|
- // 投播资源播放时长,设置该字段可将本机播放时长同步到远端显示
|
|
|
|
|
- duration: number;
|
|
|
|
|
- albumCoverUri: string;
|
|
|
|
|
- albumTitle: string;
|
|
|
|
|
- appName: string;
|
|
|
|
|
-
|
|
|
|
|
- // DRM资源,需要配置支持的DRM类型, 以chinaDRM为例。
|
|
|
|
|
- drmScheme: string;
|
|
|
|
|
-}
|
|
|
|
|
-@Entry
|
|
|
|
|
-@Component
|
|
|
|
|
-struct IjkMusicPlayerPage {
|
|
|
|
|
- @State progressValue: number = 0;
|
|
|
|
|
- @State currentTime: string = "00:00";
|
|
|
|
|
- @State totalTime: string = "00:00";
|
|
|
|
|
- @State loadingVisible: Visibility = Visibility.None;
|
|
|
|
|
- @State replayVisible: Visibility = Visibility.None;
|
|
|
|
|
- @State slideEnable: boolean = false;
|
|
|
|
|
- @State aspRatio: number = 0.5;
|
|
|
|
|
- @State mContext: object | undefined = undefined;
|
|
|
|
|
- private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
|
|
|
|
|
- @State mFirst: boolean = true;
|
|
|
|
|
- @State mDestroyPage: boolean = false;
|
|
|
|
|
- @State playSpeed: string = '1f';
|
|
|
|
|
-
|
|
|
|
|
- @State oldSeconds: number = 0;
|
|
|
|
|
- @State isSeekTo: boolean = false;
|
|
|
|
|
- @State isCurrentTime: boolean = false;
|
|
|
|
|
- @State videoWidth: string = '100%';
|
|
|
|
|
- @State videoHeight: string = '100%';
|
|
|
|
|
- @State initAspectRatio: number = 1;
|
|
|
|
|
- @State videoAspectRatio: number = this.initAspectRatio;
|
|
|
|
|
- private videoUrl: string = '';
|
|
|
|
|
- private last: number = 0;
|
|
|
|
|
- @State videoParentAspectRatio: number = this.initAspectRatio;
|
|
|
|
|
- private mIjkMediaPlayer = IjkMediaPlayer.getInstance();
|
|
|
|
|
- @State CONTROL_PlayStatus:number = PlayStatus.INIT;
|
|
|
|
|
- @State PROGRESS_MAX_VALUE: number = 100;
|
|
|
|
|
- @State updateProgressTimer: number = 0;
|
|
|
|
|
- @State curIndex: number = 0;
|
|
|
|
|
- @State isHide: boolean = false;//是否因此播放器的按钮,默认是进入横屏模式隐藏,点击视频的时候显示
|
|
|
|
|
- @State name: string = '';
|
|
|
|
|
- // @State loop: boolean = false;
|
|
|
|
|
- @State playType: number = 0; //0:连续播放 1:单片重复播放 2:正常播放 3:随机播放
|
|
|
|
|
- @State isLandscape: boolean = false;
|
|
|
|
|
- @Provide globalVideoList: Array<VideoItem> = []
|
|
|
|
|
- @State multiple: string = '1.0X';
|
|
|
|
|
-
|
|
|
|
|
- xcomponentController: XComponentController = new XComponentController()
|
|
|
|
|
- private panOptionBright: PanGestureOptions = new PanGestureOptions({ direction:PanDirection.Up| PanDirection.Down});
|
|
|
|
|
- private panOptionVolume: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Vertical| PanDirection.Up| PanDirection.Down });
|
|
|
|
|
- private panOptionSeekTo: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Horizontal });
|
|
|
|
|
- //手势的音量控制和亮度控制
|
|
|
|
|
- private positionX: number = PlayConstants.POSITION_X;
|
|
|
|
|
- private positionY: number = PlayConstants.POSITION_Y;
|
|
|
|
|
- private windowClass: window.Window = globalThis.windowClass
|
|
|
|
|
- @State volume: number = 0.5;
|
|
|
|
|
- @State volumeShow: boolean = PlayConstants.VOLUME_SHOW;
|
|
|
|
|
- @State bright: number = PlayConstants.BRIGHT;
|
|
|
|
|
- @State brightShow: boolean = PlayConstants.BRIGHT_SHOW;
|
|
|
|
|
- @State seekToShow: boolean = PlayConstants.BRIGHT_SHOW;
|
|
|
|
|
- // @State screenHeight:number = 0
|
|
|
|
|
- @State screenWidth: number =0
|
|
|
|
|
- @State screenHeight: number =0
|
|
|
|
|
- @State statusBarHeight: number =0
|
|
|
|
|
-
|
|
|
|
|
- @State isYesFull: boolean = false
|
|
|
|
|
- private seekValue:number = 0
|
|
|
|
|
- @State isVideoLock: boolean = false; // Whether the video playback is locked
|
|
|
|
|
- eventHub = getContext().eventHub;
|
|
|
|
|
-
|
|
|
|
|
- //投播组件
|
|
|
|
|
- private avSessionController: AvSessionController = AvSessionController.getInstance(false);
|
|
|
|
|
- private castController: avSession.AVCastController | undefined = undefined;
|
|
|
|
|
- @State isCastPlaying: boolean = false;
|
|
|
|
|
- @State currentTime2: number = 0;
|
|
|
|
|
- @State currentStringTime: string = '00:00';
|
|
|
|
|
- @State duration: number = 0;
|
|
|
|
|
- @State isReady: boolean = false;
|
|
|
|
|
- @State durationTime: number = 0;
|
|
|
|
|
- @State durationStringTime: string = '00:00';
|
|
|
|
|
- @State isPlaying: boolean = false;
|
|
|
|
|
- private castSeek: boolean = false;
|
|
|
|
|
- private castItem: avSession.AVQueueItem | undefined = undefined;
|
|
|
|
|
- // @State isBgPlayOpen:boolean = true //是否启用后台播放
|
|
|
|
|
-
|
|
|
|
|
- @State imageLabel: PixelMap | Resource = CommonConstants.musicBgList[0];
|
|
|
|
|
- @State imageLabelBg: PixelMap | Resource = CommonConstants.musicBgList[0] ;
|
|
|
|
|
- @State rotateAngle: number = 0
|
|
|
|
|
- @State rotateAngle2: number = 0
|
|
|
|
|
- @StorageLink('imageColor') imageColor: string = 'rgba(0, 0, 2, 1.00)';
|
|
|
|
|
-
|
|
|
|
|
- @State cover: string|undefined = '';
|
|
|
|
|
- @State artist:string|undefined = ''
|
|
|
|
|
-
|
|
|
|
|
- // 1.初始化controller
|
|
|
|
|
- private lyricController: LyricController = new LyricController()
|
|
|
|
|
- private parser = new LyricParser()
|
|
|
|
|
-
|
|
|
|
|
- @State randomColor: string = 'rgb(0,0,0)'
|
|
|
|
|
- @State randomShakenX: number = 0
|
|
|
|
|
- @State randomShakenY: number = 0
|
|
|
|
|
- aboutToAppear() {
|
|
|
|
|
- LogUtils.getInstance().LOGI("aboutToAppear");
|
|
|
|
|
-
|
|
|
|
|
- let params = router.getParams() as Record<string, Object>;
|
|
|
|
|
- this.name = params.name as string;
|
|
|
|
|
- this.curIndex = params.index as number;
|
|
|
|
|
- this.playType = params.playType as number;
|
|
|
|
|
- this.globalVideoList = params.globalVideoList as VideoItem[];
|
|
|
|
|
- this.cover = params.cover as string;
|
|
|
|
|
-
|
|
|
|
|
- this.videoUrl = (router.getParams() as RouterParam).videoUrl;
|
|
|
|
|
- // this.isBgPlayOpen = PreferencesUtil.getBooleanSync(SettingPage.IS_BGPLAY_OPEN,true)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- if(this.cover!=undefined&&StrUtil.isNotEmpty(this.cover)){
|
|
|
|
|
- this.setImageColor(this.cover)
|
|
|
|
|
- }else{
|
|
|
|
|
- this.getImageColor();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- let event: Callback<InterruptEvent> = (event) => {
|
|
|
|
|
- LogUtils.getInstance().LOGI(`event: ${JSON.stringify(event)}`);
|
|
|
|
|
- if (event.hintType === InterruptHintType.INTERRUPT_HINT_PAUSE) {
|
|
|
|
|
- this.pause();
|
|
|
|
|
- } else if (event.hintType === InterruptHintType.INTERRUPT_HINT_RESUME) {
|
|
|
|
|
- this.startPlayOrResumePlay();
|
|
|
|
|
- } else if (event.hintType === InterruptHintType.INTERRUPT_HINT_STOP) {
|
|
|
|
|
- this.stop();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.on('audioInterrupt', event);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- window.getLastWindow(getContext(this))
|
|
|
|
|
- .then((windowClass: window.Window) => {
|
|
|
|
|
- let area = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
|
|
|
|
|
- this.screenWidth = px2fp(windowClass.getWindowProperties().windowRect.width);
|
|
|
|
|
- this.screenHeight = px2fp(windowClass.getWindowProperties().windowRect.height);
|
|
|
|
|
- this.statusBarHeight = px2fp(area.topRect.height);
|
|
|
|
|
- })
|
|
|
|
|
- .catch((error: Error) => {
|
|
|
|
|
- Logger.error('[ScreenUtil] Failed to obtain the window size. Cause: ' + JSON.stringify(error));
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- this.windowClass.on('windowSizeChange', (size) => {
|
|
|
|
|
- let viewWidth = px2vp(size.width);
|
|
|
|
|
- let viewHeight = px2vp(size.height);
|
|
|
|
|
- if (this.isExpandedOrHalfFolded()) {
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (viewWidth > viewHeight) {
|
|
|
|
|
- Logger.info('横屏 windowSizeChange isLandscape = ' + this.isLandscape)
|
|
|
|
|
- this.isLandscape = true;
|
|
|
|
|
- this.windowClass.setSpecificSystemBarEnabled('navigationIndicator', false); // hide bottom navigation bar
|
|
|
|
|
- } else {
|
|
|
|
|
- Logger.info('竖屏 windowSizeChange isLandscape = ' + this.isLandscape)
|
|
|
|
|
- this.windowClass.setSpecificSystemBarEnabled('navigationIndicator', true); // show bottom navigation bar
|
|
|
|
|
- this.isLandscape = false;
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- this.getVideoSize()
|
|
|
|
|
-
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- initLyric(lyricPath:string){
|
|
|
|
|
- // 2.自定义样式属性
|
|
|
|
|
- this.lyricController
|
|
|
|
|
- .setTextSize(24)
|
|
|
|
|
- .setCacheSize(4)
|
|
|
|
|
- .setTextColor("#FFFFFF")
|
|
|
|
|
- .setHighlightColor("#ff6b47")
|
|
|
|
|
- .setLineSpace(16)
|
|
|
|
|
- .setEmptyHint("当前没有歌词")
|
|
|
|
|
- .setAlignMode("center")
|
|
|
|
|
- .setAnimationDuration(1000)
|
|
|
|
|
-
|
|
|
|
|
- LogUtil.debug("onecold lyricPath =" + lyricPath)
|
|
|
|
|
- try {
|
|
|
|
|
-
|
|
|
|
|
- // 3.读取文件内容并指定编码为 UTF-8
|
|
|
|
|
- let file = fs.openSync(lyricPath, fs.OpenMode.READ_WRITE);
|
|
|
|
|
- let arrayBuffer = new ArrayBuffer(4096);
|
|
|
|
|
- fs.read(file.fd, arrayBuffer).then((readLen: number) => {
|
|
|
|
|
- console.info("read file data succeed");
|
|
|
|
|
- // let buf = buffer.from(arrayBuffer, 0, readLen);
|
|
|
|
|
-
|
|
|
|
|
- let buf = new Uint8Array(arrayBuffer, 0, readLen);
|
|
|
|
|
-
|
|
|
|
|
- // 检测文件编码
|
|
|
|
|
- let detectedEncoding = chardet.detect(buf);
|
|
|
|
|
- console.info("Detected encoding: " + detectedEncoding);
|
|
|
|
|
-
|
|
|
|
|
- // 使用检测到的编码解码,解决中文乱码问题
|
|
|
|
|
- let textDecoder = new util.TextDecoder(detectedEncoding || 'utf-8');
|
|
|
|
|
- let fileContent = textDecoder.decode(buf);
|
|
|
|
|
- // 使用 TextDecoder 解码
|
|
|
|
|
- // let textDecoder = new util.TextDecoder('utf-8');
|
|
|
|
|
- // let fileContent = textDecoder.decode(buf);
|
|
|
|
|
- // 将文件内容按行分割成字符串数组
|
|
|
|
|
- let lines = fileContent.split('\n').map(line => line.trim());
|
|
|
|
|
- // 3.解析歌词
|
|
|
|
|
- let lyric = this.parser.parse(lines )
|
|
|
|
|
-
|
|
|
|
|
- //4.设置歌词
|
|
|
|
|
- this.lyricController.setLyric(lyric)
|
|
|
|
|
- console.info(`The content of file: ${buf.toString()}`);
|
|
|
|
|
- }).catch((err: BusinessError) => {
|
|
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- console.error("read file data failed with error message: " + err.message + ", error code: " + err.code);
|
|
|
|
|
- }).finally(() => {
|
|
|
|
|
- fs.closeSync(file);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- }catch (error) {
|
|
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- Logger.error(TAG, 'init Lyric failed with err: ' + JSON.stringify(error));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- aboutToDisappear() {
|
|
|
|
|
- LogUtils.getInstance().LOGI("aboutToDisappear");
|
|
|
|
|
- this.mDestroyPage = true;
|
|
|
|
|
- this.mIjkMediaPlayer.setScreenOnWhilePlaying(false);
|
|
|
|
|
- if (this.CONTROL_PlayStatus != PlayStatus.INIT) {
|
|
|
|
|
- this.stop();
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.off('audioInterrupt');
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- onPageShow() {
|
|
|
|
|
-
|
|
|
|
|
- this.getVideoSize()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //修复播放器全屏横屏的时候 按home键处理页面为竖屏
|
|
|
|
|
- onBackPress(): boolean | void {
|
|
|
|
|
- Logger.info('playPage player onBackPress: ' );
|
|
|
|
|
- if(this.isLandscape){
|
|
|
|
|
- this.isLandscape = false
|
|
|
|
|
- this.setOrientation(window.Orientation.USER_ROTATION_PORTRAIT);
|
|
|
|
|
- }
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- onPageHide() {
|
|
|
|
|
- // this.pause();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- getStatus() {
|
|
|
|
|
- return this.CONTROL_PlayStatus;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Get largest proportion color of an image.
|
|
|
|
|
- */
|
|
|
|
|
- getImageColor() {
|
|
|
|
|
- if (!this.context) {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- let bg = Utility.getMusisBg()
|
|
|
|
|
-
|
|
|
|
|
- this.imageLabel = bg
|
|
|
|
|
- ColorConversion.setSysBarLightBackground(true);
|
|
|
|
|
- this.context.resourceManager.getMediaContent(bg)
|
|
|
|
|
- .then((value: Uint8Array) => {
|
|
|
|
|
- let buffer = value.buffer as ArrayBuffer;
|
|
|
|
|
- image.createImageSource(buffer).createPixelMap().then((pixelMap) => {
|
|
|
|
|
- effectKit.createColorPicker(pixelMap, (error, colorPicker) => {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- Logger.error('Failed to create color picker.');
|
|
|
|
|
- } else {
|
|
|
|
|
- let color = colorPicker.getLargestProportionColor();
|
|
|
|
|
- let colorArr = ColorConversion.dealColor(color.red, color.green, color.blue);
|
|
|
|
|
- this.imageColor = `rgba(${colorArr[0]}, ${colorArr[1]}, ${colorArr[2]}, 1)`;
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- let headFilter = effectKit.createEffect(pixelMap);
|
|
|
|
|
- if (headFilter !== null) {
|
|
|
|
|
- headFilter.blur(15);
|
|
|
|
|
- headFilter.getEffectPixelMap().then((value) => {
|
|
|
|
|
- this.imageLabelBg = value;
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .catch((error: BusinessError) => {
|
|
|
|
|
- Logger.error(`${error.code} + ${error.message}`)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- .catch((error: BusinessError) => {
|
|
|
|
|
- Logger.error(`${error.code} + ${error.message}`)
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- setImageColor(cover:string) {
|
|
|
|
|
-
|
|
|
|
|
- if (!this.context) {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- ImageUtil.base64ToPixelMap(cover).then((value)=>{
|
|
|
|
|
- let headFilter = effectKit.createEffect(value);
|
|
|
|
|
- if (headFilter !== null) {
|
|
|
|
|
- headFilter.blur(15);
|
|
|
|
|
- headFilter.getEffectPixelMap().then((value) => {
|
|
|
|
|
- this.imageLabelBg = value;
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }).catch((error: BusinessError) => {
|
|
|
|
|
- Logger.error(`${error.code} + ${error.message}`)
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- isExpandedOrHalfFolded(): boolean {
|
|
|
|
|
- return display.getFoldStatus() === display.FoldStatus.FOLD_STATUS_EXPANDED ||
|
|
|
|
|
- display.getFoldStatus() == display.FoldStatus.FOLD_STATUS_HALF_FOLDED
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setOrientation(orientation: number) {
|
|
|
|
|
- this.windowClass.setPreferredOrientation(orientation).then(() => {
|
|
|
|
|
- Logger.info('setWindowOrientation: ' + orientation + ' Succeeded.');
|
|
|
|
|
- }).catch((err: BusinessError) => {
|
|
|
|
|
- Logger.info('setWindowOrientation: ' + orientation + ' Failed. Cause: ' + JSON.stringify(err));
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- showPlayList(){
|
|
|
|
|
- promptAction.openCustomDialog({
|
|
|
|
|
- transition: AnimationHelper.transitionInDown(888),
|
|
|
|
|
- builder: () => {
|
|
|
|
|
- this.customDialogComponent()
|
|
|
|
|
- },
|
|
|
|
|
- alignment: this.isLandscape?DialogAlignment.TopEnd:DialogAlignment.BottomEnd,
|
|
|
|
|
- onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
|
|
|
|
|
- console.info("reason" + JSON.stringify(dismissDialogAction.reason))
|
|
|
|
|
- console.log("dialog onWillDismiss")
|
|
|
|
|
- if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
|
|
|
|
|
- dismissDialogAction.dismiss()
|
|
|
|
|
- }
|
|
|
|
|
- if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
|
|
|
|
|
- dismissDialogAction.dismiss()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }).then((dialogId: number) => {
|
|
|
|
|
- this.customDialogComponentId = dialogId
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private customDialogComponentId: number = 0
|
|
|
|
|
- @Builder
|
|
|
|
|
- customDialogComponent() {
|
|
|
|
|
- Column() {
|
|
|
|
|
- Row(){
|
|
|
|
|
- Blank()
|
|
|
|
|
- Text('播放列表')
|
|
|
|
|
- .fontSize(15)
|
|
|
|
|
- .fontColor($r('app.color.pri_bg'))
|
|
|
|
|
- .margin({top:16})
|
|
|
|
|
- Blank()
|
|
|
|
|
- Image($r('app.media.close'))
|
|
|
|
|
- .fillColor(Color.White)
|
|
|
|
|
- .margin({top:18,right:18})
|
|
|
|
|
- .width(20)
|
|
|
|
|
- .onClick(()=>{
|
|
|
|
|
- promptAction.closeCustomDialog(this.customDialogComponentId)
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .width('100%') // 使Row占据整个宽度
|
|
|
|
|
- .justifyContent(FlexAlign.SpaceBetween); // 在Row中创建空间
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- List() {
|
|
|
|
|
- ForEach(this.globalVideoList, (item: VideoItem, index: number) => {
|
|
|
|
|
- ListItem() {
|
|
|
|
|
- Row(){
|
|
|
|
|
- Text(index+1+'')
|
|
|
|
|
- .margin({left:20,top:5,bottom:5,right:1})
|
|
|
|
|
- .fontWeight(900)
|
|
|
|
|
- .fontColor(Color.Gray)
|
|
|
|
|
- if(this.curIndex === index){
|
|
|
|
|
- Text('正在播放:')
|
|
|
|
|
- .margin({left:1,top:5,bottom:5})
|
|
|
|
|
- .fontWeight(500)
|
|
|
|
|
- .fontColor( $r('app.color.title_bar_bg'))
|
|
|
|
|
- .padding({ top:10,bottom:10,left:10})
|
|
|
|
|
- Text(item.name)
|
|
|
|
|
- .margin({top:5,bottom:5,right:10})
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .fontColor( $r('app.color.title_bar_bg'))
|
|
|
|
|
- .padding({ top:10,bottom:10 ,left:1,right:4})
|
|
|
|
|
- .textAlign(TextAlign.Start)
|
|
|
|
|
- .textOverflow({overflow: TextOverflow.MARQUEE}) //超长滚动
|
|
|
|
|
- Text(item.artist)
|
|
|
|
|
- .margin({left:1,top:5,bottom:5,right:10})
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .fontColor(Color.Gray)
|
|
|
|
|
- .fontSize(10)
|
|
|
|
|
- .padding({ top:10,bottom:10 ,left:1,right:10})
|
|
|
|
|
- .textAlign(TextAlign.Start)
|
|
|
|
|
- }else{
|
|
|
|
|
- Text(item.name)
|
|
|
|
|
- .margin({left:1,top:5,bottom:5,right:10})
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .fontColor(Color.Black)
|
|
|
|
|
- .padding({ top:10,bottom:10 ,left:10,right:4})
|
|
|
|
|
- .textAlign(TextAlign.Start)
|
|
|
|
|
- Text(item.artist)
|
|
|
|
|
- .margin({left:1,top:5,bottom:5,right:10})
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .fontSize(10)
|
|
|
|
|
- .fontColor(Color.Gray)
|
|
|
|
|
- .padding({ top:10,bottom:10 ,left:1,right:10})
|
|
|
|
|
- .textAlign(TextAlign.Start)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .width('93%')
|
|
|
|
|
-
|
|
|
|
|
- }.onClick(() => {
|
|
|
|
|
- promptAction.closeCustomDialog(this.customDialogComponentId)
|
|
|
|
|
- this.playIndex(index)
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- .height('100%')
|
|
|
|
|
- .divider({
|
|
|
|
|
- strokeWidth:1,
|
|
|
|
|
- color:"#D3D3D3"
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- }.height(this.isLandscape?'100%':'60%')
|
|
|
|
|
- .backgroundColor($r('app.color.index_background'))
|
|
|
|
|
- .justifyContent(FlexAlign.SpaceBetween)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //倍速播放
|
|
|
|
|
- showMultipleDialog(xid:string){
|
|
|
|
|
-
|
|
|
|
|
- let dataBean = new BubbleBean()
|
|
|
|
|
- dataBean.data = ["0.75X","1.0X", "1.25X","1.5X","1.75X", "2.0X", "3.0X"]
|
|
|
|
|
- dataBean.onItemClick = (i) => {
|
|
|
|
|
- // ToastUtil.showToast('您点击了第'+index+'个')
|
|
|
|
|
- this.multiple = dataBean.data[i]
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- switch (i){
|
|
|
|
|
-
|
|
|
|
|
- case 0://0.75X
|
|
|
|
|
- this.playSpeed = '0.75f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("0.75f");
|
|
|
|
|
- break
|
|
|
|
|
- case 1://1.0X
|
|
|
|
|
- this.playSpeed = '1f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("1f");
|
|
|
|
|
- break
|
|
|
|
|
- case 2://1.25X
|
|
|
|
|
- this.playSpeed = '1.25f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("1.25f");
|
|
|
|
|
- break
|
|
|
|
|
- case 3://1.5X
|
|
|
|
|
- this.playSpeed = '1.5f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("1.5f");
|
|
|
|
|
- break
|
|
|
|
|
- case 4://1.75X
|
|
|
|
|
- this.playSpeed = '1.75f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("1.75f");
|
|
|
|
|
- break
|
|
|
|
|
- case 5://2.0X
|
|
|
|
|
- this.playSpeed = '2f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("2f");
|
|
|
|
|
- break
|
|
|
|
|
-
|
|
|
|
|
- case 6://3.0X
|
|
|
|
|
- this.playSpeed = '3f'
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed("3f");
|
|
|
|
|
- break
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- xpup.dismiss()
|
|
|
|
|
- }
|
|
|
|
|
- let popupPosition:PopupPosition = PopupPosition.BOTTOM
|
|
|
|
|
- if(xid.includes('down')){
|
|
|
|
|
- popupPosition = PopupPosition.TOP
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let xpup = XPopup.Builder()
|
|
|
|
|
- .setPopupPosition(popupPosition)
|
|
|
|
|
- .atView(xid)
|
|
|
|
|
- .asBubble(wrapBuilder(customPopupBuilder), dataBean)
|
|
|
|
|
- .show()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- onActionEvent(event: PiPWindow.PiPActionEventType, status: number | undefined) {
|
|
|
|
|
- switch (event) {
|
|
|
|
|
- case 'playbackStateChanged':
|
|
|
|
|
- if (status === 0) {
|
|
|
|
|
- // this.updatePlayStatus(false);
|
|
|
|
|
- this.pause();
|
|
|
|
|
- } else {
|
|
|
|
|
- // this.updatePlayStatus(true);
|
|
|
|
|
- this.startPlayOrResumePlay();
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- build() {
|
|
|
|
|
-
|
|
|
|
|
- Stack() {
|
|
|
|
|
-
|
|
|
|
|
- Stack({ alignContent: Alignment.Center }) {
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Column(){
|
|
|
|
|
-
|
|
|
|
|
- XComponent({
|
|
|
|
|
- id: 'xcomponentId',
|
|
|
|
|
- type: 'surface',
|
|
|
|
|
- libraryname: 'ijkplayer_napi',
|
|
|
|
|
- controller: this.xcomponentController
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- .onLoad((event?: object) => {
|
|
|
|
|
- if (!!event) {
|
|
|
|
|
- this.initDelayPlay(event);
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .onDestroy(() => {
|
|
|
|
|
- })
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- // .width(this.videoWidth)
|
|
|
|
|
- .aspectRatio(this.videoAspectRatio)
|
|
|
|
|
- }
|
|
|
|
|
- .aspectRatio(this.videoAspectRatio)
|
|
|
|
|
- .justifyContent(FlexAlign.Center)
|
|
|
|
|
- .backgroundColor(Color.Transparent)
|
|
|
|
|
- .visibility(Visibility.Hidden)
|
|
|
|
|
- .height(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Image($r('app.media.icon_load'))
|
|
|
|
|
- .objectFit(ImageFit.Auto)
|
|
|
|
|
- .width('120px')
|
|
|
|
|
- .height('120px')
|
|
|
|
|
- .visibility(this.loadingVisible)
|
|
|
|
|
- .border({ width: 0 })
|
|
|
|
|
- .borderStyle(BorderStyle.Dashed)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Stack() {
|
|
|
|
|
- Progress({
|
|
|
|
|
- value: Math.floor(this.bright * CommonConstants.ONE_HUNDRED),
|
|
|
|
|
- type: ProgressType.Ring
|
|
|
|
|
- })
|
|
|
|
|
- .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- Image($r('app.media.ic_brightness'))
|
|
|
|
|
- .width(PlayConstants.PLAYER_IMAGE_WIDTH)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- }
|
|
|
|
|
- .width(55)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .visibility(this.brightShow ? Visibility.Visible : Visibility.Hidden)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- //音量控制
|
|
|
|
|
- Stack() {
|
|
|
|
|
- Progress({
|
|
|
|
|
- value: Math.floor(this.volume * CommonConstants.ONE_HUNDRED),
|
|
|
|
|
- type: ProgressType.Ring
|
|
|
|
|
- })
|
|
|
|
|
- .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- Image($r('app.media.ic_volume'))
|
|
|
|
|
- .width(PlayConstants.PLAYER_IMAGE_WIDTH)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- }
|
|
|
|
|
- .width(55)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .visibility(this.volumeShow ? Visibility.Visible : Visibility.Hidden)
|
|
|
|
|
- //手势拖动快进和快退
|
|
|
|
|
- Column(){
|
|
|
|
|
- Row(){
|
|
|
|
|
- Text(this.currentTime)
|
|
|
|
|
- .fontSize(18)
|
|
|
|
|
- .fontColor($r('app.color.title_bar_bg'))
|
|
|
|
|
- .margin({ top:5 })
|
|
|
|
|
- .fontWeight(80)
|
|
|
|
|
- .padding({top:8})
|
|
|
|
|
- Text('/')
|
|
|
|
|
- .margin({ top:5 })
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .padding({top:8})
|
|
|
|
|
- .fontWeight(80)
|
|
|
|
|
- Text(this.totalTime)
|
|
|
|
|
- .fontSize(14)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .margin({ top:5 })
|
|
|
|
|
- .padding({top:8})
|
|
|
|
|
- .fontWeight(80)
|
|
|
|
|
- }
|
|
|
|
|
- Slider({
|
|
|
|
|
- value: this.progressValue,
|
|
|
|
|
- min: 0,
|
|
|
|
|
- max: this.PROGRESS_MAX_VALUE,
|
|
|
|
|
- step: 1,
|
|
|
|
|
- style: SliderStyle.OutSet
|
|
|
|
|
- })
|
|
|
|
|
- .width(150)
|
|
|
|
|
- .blockColor(Color.Red)
|
|
|
|
|
- .trackColor($r('app.color.track_color'))
|
|
|
|
|
- .selectedColor($r('app.color.title_bar_bg'))
|
|
|
|
|
- .trackThickness(PlayConstants.PROGRESS_TRACK_THICKNESS)
|
|
|
|
|
- .margin({ left: 8,right:8 })
|
|
|
|
|
- .showSteps(true)
|
|
|
|
|
- .showTips(true)
|
|
|
|
|
- .enabled(this.slideEnable)
|
|
|
|
|
- .onChange((value: number, mode: SliderChangeMode) => {
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- .backgroundColor($r('app.color.pri_bg'))
|
|
|
|
|
- .backgroundBlurStyle(BlurStyle.BACKGROUND_ULTRA_THICK)
|
|
|
|
|
- .opacity(0.7)
|
|
|
|
|
- .borderRadius(22)
|
|
|
|
|
- .visibility(this.seekToShow ? Visibility.Visible : Visibility.Hidden)
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Column() {
|
|
|
|
|
-
|
|
|
|
|
- Column() {
|
|
|
|
|
- //播放标题
|
|
|
|
|
- Column() {
|
|
|
|
|
- this.PlayTitle()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .position({x:0,y:0})
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- .margin(this.isLandscape?{top:13}:{top:0})
|
|
|
|
|
- .height(PlayConstants.HEIGHT)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Swiper() {
|
|
|
|
|
- this.CoverInfo()
|
|
|
|
|
- this.PlayerLyrics()
|
|
|
|
|
- }
|
|
|
|
|
- .indicator(
|
|
|
|
|
- new DotIndicator()
|
|
|
|
|
- .top(10)
|
|
|
|
|
- .selectedColor($r('app.color.select_swiper'))
|
|
|
|
|
- .color($r('app.color.slider_track'))
|
|
|
|
|
- )
|
|
|
|
|
- .clip(false)
|
|
|
|
|
- .loop(false)
|
|
|
|
|
- .autoPlay(false)
|
|
|
|
|
- // .interval(8000)
|
|
|
|
|
- .position({x:0,y:22})
|
|
|
|
|
- .height('80%')
|
|
|
|
|
- .hitTestBehavior(HitTestMode.Transparent)
|
|
|
|
|
-
|
|
|
|
|
- // .backgroundColor('#000000')
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // Stack(){
|
|
|
|
|
- //手势拖动快进
|
|
|
|
|
- // Column()
|
|
|
|
|
- // .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- // .height('100%')
|
|
|
|
|
- // .gesture(
|
|
|
|
|
- // PanGesture(this.panOptionSeekTo)
|
|
|
|
|
- // .onActionStart((event?: GestureEvent) => {
|
|
|
|
|
- // this.onSeekToActionStart(event);
|
|
|
|
|
- // })
|
|
|
|
|
- // .onActionUpdate((event?: GestureEvent) => {
|
|
|
|
|
- // this.onSeekToActionUpdate(event);
|
|
|
|
|
- // })
|
|
|
|
|
- // .onActionEnd(() => {
|
|
|
|
|
- // this.onSeekToActionEnd();
|
|
|
|
|
- // })
|
|
|
|
|
- // )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // Row(){
|
|
|
|
|
- // //亮度控制
|
|
|
|
|
- // Column()
|
|
|
|
|
- // .width('50%')
|
|
|
|
|
- // .height('40%')
|
|
|
|
|
- // .gesture(
|
|
|
|
|
- // PanGesture(this.panOptionBright)
|
|
|
|
|
- // .onActionStart((event?: GestureEvent) => {
|
|
|
|
|
- // this.onBrightActionStart(event);
|
|
|
|
|
- // })
|
|
|
|
|
- // .onActionUpdate((event?: GestureEvent) => {
|
|
|
|
|
- // this.onBrightActionUpdate(event);
|
|
|
|
|
- // })
|
|
|
|
|
- // .onActionEnd(() => {
|
|
|
|
|
- // this.onActionEnd();
|
|
|
|
|
- // })
|
|
|
|
|
- // )
|
|
|
|
|
- //
|
|
|
|
|
- //
|
|
|
|
|
- //
|
|
|
|
|
- // //音量控制
|
|
|
|
|
- // Column()
|
|
|
|
|
- // .width('50%')
|
|
|
|
|
- // .height('40%')
|
|
|
|
|
- // .gesture(
|
|
|
|
|
- // PanGesture(this.panOptionVolume)
|
|
|
|
|
- // .onActionStart((event?: GestureEvent) => {
|
|
|
|
|
- //
|
|
|
|
|
- // this.onVolumeActionStart(event);
|
|
|
|
|
- // })
|
|
|
|
|
- // .onActionUpdate((event?: GestureEvent) => {
|
|
|
|
|
- // this.onVolumeActionUpdate(event);
|
|
|
|
|
- // })
|
|
|
|
|
- // .onActionEnd(() => {
|
|
|
|
|
- // this.onActionEnd();
|
|
|
|
|
- // })
|
|
|
|
|
- // )
|
|
|
|
|
- // }
|
|
|
|
|
- // .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- // .height('100%')
|
|
|
|
|
-
|
|
|
|
|
- // .hitTestBehavior(HitTestMode.Transparent)
|
|
|
|
|
- // }
|
|
|
|
|
- // .height('45%')
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Image($r('app.media.icon_replay'))
|
|
|
|
|
- .objectFit(ImageFit.Auto)
|
|
|
|
|
- .width('120px')
|
|
|
|
|
- .height('120px')
|
|
|
|
|
- .position({x:'45.1%',y:'47.5%'})
|
|
|
|
|
- // .visibility(this.replayVisible)
|
|
|
|
|
- .border({ width: 0 })
|
|
|
|
|
- .visibility(Visibility.None)
|
|
|
|
|
- .borderStyle(BorderStyle.Dashed)
|
|
|
|
|
- // .hitTestBehavior(HitTestMode.Transparent)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.startPlayOrResumePlay();
|
|
|
|
|
- })
|
|
|
|
|
- //播放 暂停,下一首,上一首
|
|
|
|
|
-
|
|
|
|
|
- Row() {
|
|
|
|
|
- Image($r('app.media.ic_previous'))
|
|
|
|
|
- .width(33)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .onClick(async () => {
|
|
|
|
|
- this.playPrevious()
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- Column() {
|
|
|
|
|
- Image(this.CONTROL_PlayStatus === PlayStatus.PLAY ?
|
|
|
|
|
- $r('app.media.ic_public_play') : $r('app.media.ic_public_pause'))
|
|
|
|
|
- .width(50)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .onClick(async () => {
|
|
|
|
|
- this.playOrPause()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
-
|
|
|
|
|
- Image($r('app.media.ic_next'))
|
|
|
|
|
- .width(33)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
-
|
|
|
|
|
- this.playNext();
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- .width(PlayConstants.CONTROL_ROW_WIDTH)
|
|
|
|
|
- .margin(10)
|
|
|
|
|
- .visibility(this.isHide?Visibility.None:Visibility.Visible)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- //播放进度条
|
|
|
|
|
- Row() {
|
|
|
|
|
- Column(){
|
|
|
|
|
- if (this.playType === 0) {
|
|
|
|
|
- Image($r('app.media.loop'))
|
|
|
|
|
- .width($r('app.float.control_image_width'))
|
|
|
|
|
- .margin(10)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- } else if (this.playType === 1) {
|
|
|
|
|
- Image($r('app.media.single'))
|
|
|
|
|
- .width($r('app.float.control_image_width'))
|
|
|
|
|
- .margin(10)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- } else if (this.playType === 2) {
|
|
|
|
|
- Image($r('app.media.play_nor'))
|
|
|
|
|
- .width($r('app.float.control_image_width'))
|
|
|
|
|
- .margin(10)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- }else if (this.playType === 3) {
|
|
|
|
|
- Image($r('app.media.random'))
|
|
|
|
|
- .width($r('app.float.control_image_width'))
|
|
|
|
|
- .margin(10)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- .onClick(async () => {
|
|
|
|
|
- let itype = this.playType+1
|
|
|
|
|
- if( itype >= 4 ){
|
|
|
|
|
- this.playType = 0
|
|
|
|
|
- ToastUtil.showToast('连续播放')
|
|
|
|
|
- }else if(itype ===1){
|
|
|
|
|
- this.playType = 1
|
|
|
|
|
- ToastUtil.showToast('单曲循环')
|
|
|
|
|
- }else if(itype ===2){
|
|
|
|
|
- this.playType = 2
|
|
|
|
|
- ToastUtil.showToast('正常播放')
|
|
|
|
|
- }else if(itype ===3){
|
|
|
|
|
- this.playType = 3
|
|
|
|
|
- ToastUtil.showToast('随机播放')
|
|
|
|
|
- }else if(itype ===0){
|
|
|
|
|
- this.playType = 0
|
|
|
|
|
- ToastUtil.showToast('连续播放')
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Text(this.currentTime)
|
|
|
|
|
- .fontSize($r('app.float.slider_font_size'))
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .margin(3)
|
|
|
|
|
- Slider({
|
|
|
|
|
- value: this.progressValue,
|
|
|
|
|
- min: 0,
|
|
|
|
|
- max: this.PROGRESS_MAX_VALUE,
|
|
|
|
|
- step: 1,
|
|
|
|
|
- style: SliderStyle.OutSet
|
|
|
|
|
- })
|
|
|
|
|
- .width('600px')
|
|
|
|
|
- .blockColor(Color.White)
|
|
|
|
|
- .trackColor($r('app.color.track_color'))
|
|
|
|
|
- .selectedColor(Color.White)
|
|
|
|
|
- .trackThickness(PlayConstants.PROGRESS_TRACK_THICKNESS)
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
- .margin({ left: PlayConstants.PROGRESS_MARGIN_LEFT })
|
|
|
|
|
- .showSteps(true)
|
|
|
|
|
- .showTips(true)
|
|
|
|
|
- .enabled(this.slideEnable)
|
|
|
|
|
- .onChange((value: number, mode: SliderChangeMode) => {
|
|
|
|
|
- // if (mode == 2) {
|
|
|
|
|
- this.isSeekTo = true;
|
|
|
|
|
- this.mDestroyPage = false;
|
|
|
|
|
- this.showLoadIng();
|
|
|
|
|
- LogUtils.getInstance().LOGI("slider-->seekValue start:" + value);
|
|
|
|
|
- let seekValue = value * (this.mIjkMediaPlayer.getDuration() / 100);
|
|
|
|
|
- this.seekTo(seekValue + "");
|
|
|
|
|
- // this.setProgress()
|
|
|
|
|
- LogUtils.getInstance().LOGI("slider-->seekValue end:" + seekValue);
|
|
|
|
|
- this.isSeekTo = false;
|
|
|
|
|
- // }
|
|
|
|
|
- })
|
|
|
|
|
- Text(this.totalTime)
|
|
|
|
|
- .fontSize($r('app.float.slider_font_size'))
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .margin(3)
|
|
|
|
|
- .margin({ left: PlayConstants.PROGRESS_MARGIN_LEFT })
|
|
|
|
|
- Text(this.multiple)
|
|
|
|
|
- .fontSize(16)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .margin({ right:25,left:18 })
|
|
|
|
|
- .visibility(this.isLandscape?Visibility.None:Visibility.None)
|
|
|
|
|
- .id('down_xid')
|
|
|
|
|
- .onClick(()=>{
|
|
|
|
|
- this.showMultipleDialog('down_xid')
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- //播放列表
|
|
|
|
|
- Image($r('app.media.playlist'))
|
|
|
|
|
- .width($r('app.float.control_image_width'))
|
|
|
|
|
- .margin({ right:10,left:20 })
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .onClick(async () => {
|
|
|
|
|
- this.showPlayList()
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .width(PlayConstants.PROGRESS_ROW_WIDTH)
|
|
|
|
|
- .visibility(this.isHide?Visibility.Hidden:Visibility.Visible)
|
|
|
|
|
- }
|
|
|
|
|
- .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- .height(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- .justifyContent(FlexAlign.End)
|
|
|
|
|
- }
|
|
|
|
|
- .justifyContent(FlexAlign.End)
|
|
|
|
|
- .margin({bottom:8})
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // .backgroundColor(Color.Black)
|
|
|
|
|
- .backgroundImage(this.imageLabelBg)
|
|
|
|
|
- .backgroundImageSize({ width: '180%', height: '180%' })
|
|
|
|
|
- .hitTestBehavior(HitTestMode.Transparent)
|
|
|
|
|
- .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 定义开始旋转的方法
|
|
|
|
|
- startRotation() {
|
|
|
|
|
-
|
|
|
|
|
- if (this.mIjkMediaPlayer.isPlaying()) {
|
|
|
|
|
- animateTo({
|
|
|
|
|
- duration: 9000,
|
|
|
|
|
- curve: Curve.Linear,
|
|
|
|
|
- iterations: -1,
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.rotateAngle = 360;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- animateTo ( {
|
|
|
|
|
- duration: 0,
|
|
|
|
|
- iterations: 1,
|
|
|
|
|
- curve:Curve.Linear
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.rotateAngle2 = 0
|
|
|
|
|
- } )
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 回调,暂停和播放按钮回调,下一首和上一首
|
|
|
|
|
- playChange( ){
|
|
|
|
|
-
|
|
|
|
|
- if(this.mIjkMediaPlayer.isPlaying()){
|
|
|
|
|
- this.startRotation()
|
|
|
|
|
- }else{
|
|
|
|
|
- this.stopRotation()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 定义停止旋转的方法
|
|
|
|
|
- stopRotation() {
|
|
|
|
|
-
|
|
|
|
|
- // 停止唱片旋转
|
|
|
|
|
- animateTo ( {
|
|
|
|
|
- duration: 0,
|
|
|
|
|
- iterations: 1,
|
|
|
|
|
- curve:Curve.Linear,
|
|
|
|
|
- onFinish: () => { this.rotateAngle = 0 }
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.rotateAngle = 0
|
|
|
|
|
- } )
|
|
|
|
|
- // 唱针以左上角为点选择逆时针40度
|
|
|
|
|
- animateTo({
|
|
|
|
|
- duration: 1000,
|
|
|
|
|
- curve: Curve.Linear,
|
|
|
|
|
- iterations: 1,
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.rotateAngle2 = -40;
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //歌词显示
|
|
|
|
|
- @Builder
|
|
|
|
|
- PlayerLyrics() {
|
|
|
|
|
-
|
|
|
|
|
- Column() {
|
|
|
|
|
- Image($r('app.media.lyric'))
|
|
|
|
|
- .width(25)
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .margin({top:45,bottom:3})
|
|
|
|
|
- .onClick(()=>{
|
|
|
|
|
- this.showSelectLyric()
|
|
|
|
|
- })
|
|
|
|
|
- LyricView2({ controller: this.lyricController,
|
|
|
|
|
- enableSeek: true, // 开启滑动歌词seek能力
|
|
|
|
|
- seekUIColor: "#ff0000",// 滑动定位的按钮和文本颜色
|
|
|
|
|
- seekLineColor: "#80ffffff",// 滑动定位线颜色
|
|
|
|
|
- seekUIStyle: "listItem",// 滑动定位样式(seekLine传统样式,listItem类似抖音汽水音乐样式)
|
|
|
|
|
- onSeekAction: (position:number) => { // 滑动歌词触发seek定位回调
|
|
|
|
|
- this.isSeekTo = true;
|
|
|
|
|
- this.mDestroyPage = false;
|
|
|
|
|
- this.showLoadIng();
|
|
|
|
|
- // LogUtils.getInstance().LOGI("onecold-->seekValue start:" + position);
|
|
|
|
|
- this.seekTo(position + "");
|
|
|
|
|
- // LogUtils.getInstance().LOGI("slider-->seekValue end:" + position);
|
|
|
|
|
- this.isSeekTo = false;
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .width("100%")
|
|
|
|
|
- .margin({top:8,bottom:15})
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
- }
|
|
|
|
|
- .width("80%")
|
|
|
|
|
- .alignItems(HorizontalAlign.Center)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Builder
|
|
|
|
|
- CoverInfo() {
|
|
|
|
|
- Column(){
|
|
|
|
|
-
|
|
|
|
|
- // 第一个
|
|
|
|
|
- Column({ space: 8 }) {
|
|
|
|
|
- Text(this.name)
|
|
|
|
|
- .fontSize(22)
|
|
|
|
|
- .fontWeight(FontWeight.Bold)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- Text(this.artist)
|
|
|
|
|
- .fontSize(15)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- }
|
|
|
|
|
- .margin({top:66})
|
|
|
|
|
- .justifyContent(FlexAlign.Center)
|
|
|
|
|
- .zIndex(1)
|
|
|
|
|
- // .translate({
|
|
|
|
|
- // x: this.randomShakenX,
|
|
|
|
|
- // y: this.randomShakenY
|
|
|
|
|
- // })
|
|
|
|
|
-
|
|
|
|
|
- Stack(){
|
|
|
|
|
- // 唱片旋转效果
|
|
|
|
|
- Image($r('app.media.ic_music_disc') )
|
|
|
|
|
- .width(250)
|
|
|
|
|
- .height(250)
|
|
|
|
|
- .margin({right:30,left:20,top:10})
|
|
|
|
|
- .aspectRatio(1)
|
|
|
|
|
- .borderRadius('100%')
|
|
|
|
|
- .align(Alignment.Center)
|
|
|
|
|
- .clip(true)
|
|
|
|
|
- .rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle })
|
|
|
|
|
- .onAppear(() => {
|
|
|
|
|
- // this.startRotation();
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- .shadow({
|
|
|
|
|
- radius: 30,
|
|
|
|
|
- color: this.randomColor
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Image(StrUtil.isEmpty(this.cover)||this.cover==undefined?this.imageLabel:this.cover )
|
|
|
|
|
- .width(162)
|
|
|
|
|
- .height(162)
|
|
|
|
|
- .margin({right:30,left:20,top:10})
|
|
|
|
|
- .aspectRatio(1)
|
|
|
|
|
- .borderRadius('100%')
|
|
|
|
|
- .align(Alignment.Center)
|
|
|
|
|
- .clip(true)
|
|
|
|
|
- .rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle })
|
|
|
|
|
- .onAppear(() => {
|
|
|
|
|
- this.startRotation();
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- .onClick(()=>{
|
|
|
|
|
- this.getImageColor()
|
|
|
|
|
- })
|
|
|
|
|
- // 唱针以左上角为点选择逆时针40度
|
|
|
|
|
- Image($r('app.media.ic_music_cover_hand'))
|
|
|
|
|
- .height(120)
|
|
|
|
|
- .margin({bottom:180})
|
|
|
|
|
- .align(Alignment.Top)
|
|
|
|
|
- .rotate({ angle: this.rotateAngle2 ,centerX:0,centerY:0})
|
|
|
|
|
- .onAppear(() => {
|
|
|
|
|
- this.startRotation();
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .margin({top:30})
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- .width(CommonConstants.FULL_PERCENT)
|
|
|
|
|
- .height('100%')
|
|
|
|
|
- .clip(true)
|
|
|
|
|
- }
|
|
|
|
|
- @Builder
|
|
|
|
|
- private PlayTitle() {
|
|
|
|
|
-
|
|
|
|
|
- Row() {
|
|
|
|
|
- Row(){
|
|
|
|
|
- Image($r('app.media.back'))
|
|
|
|
|
- .width($r('app.float.title_image_size'))
|
|
|
|
|
- .aspectRatio(CommonConstants.ASPECT_RATIO)
|
|
|
|
|
- .hitTestBehavior(HitTestMode.Transparent)
|
|
|
|
|
- // .visibility(this.isLandscape?Visibility.None:Visibility.Visible)
|
|
|
|
|
-
|
|
|
|
|
- Text(this.name+' '+this.artist)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .fontSize($r('app.float.title_font_size'))
|
|
|
|
|
- .textOverflow({overflow: TextOverflow.MARQUEE}) //超长滚动
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .visibility(Visibility.None)
|
|
|
|
|
- .margin({ left: 2,right:30 })
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
- .visibility(this.isHide?Visibility.Hidden:Visibility.Visible)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
-
|
|
|
|
|
- if(this.isLandscape){
|
|
|
|
|
- this.setOrientation(window.Orientation.USER_ROTATION_PORTRAIT);
|
|
|
|
|
- this.isLandscape = false
|
|
|
|
|
- }else{
|
|
|
|
|
- router.back();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- Text(this.multiple)
|
|
|
|
|
- .fontSize(16)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .margin({ right:15 })
|
|
|
|
|
- .visibility(this.isHide?Visibility.None:Visibility.Visible)
|
|
|
|
|
- .id('xid')
|
|
|
|
|
- .onClick(()=>{
|
|
|
|
|
- this.showMultipleDialog('xid')
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- Image(this.isYesFull?$r('app.media.not_full'):$r('app.media.yes_full'))
|
|
|
|
|
- .width($r('app.float.title_image_size'))
|
|
|
|
|
- .margin({left:6,right:8})
|
|
|
|
|
- .visibility(this.isLandscape?(this.isHide?Visibility.None:Visibility.Visible):Visibility.None)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- if(!this.isLandscape){
|
|
|
|
|
- ToastUtil.showToast('当前视频不支持撑满全屏')
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- let VideoWidth = this.mIjkMediaPlayer.getVideoWidth();
|
|
|
|
|
- let VideoHeight = this.mIjkMediaPlayer.getVideoHeight();
|
|
|
|
|
- if(VideoHeight > VideoWidth) { //竖屏视频
|
|
|
|
|
- ToastUtil.showToast('当前视频不支持撑满全屏')
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- this.isYesFull = !this.isYesFull
|
|
|
|
|
- if(this.isYesFull){
|
|
|
|
|
- ToastUtil.showToast('撑满全屏')
|
|
|
|
|
- }else{
|
|
|
|
|
- ToastUtil.showToast('恢复不撑满')
|
|
|
|
|
- }
|
|
|
|
|
- this.getVideoSize()
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Column() {
|
|
|
|
|
- AVCastPicker({
|
|
|
|
|
- normalColor: Color.White,
|
|
|
|
|
- onStateChange: this.onStateVastChange
|
|
|
|
|
- })
|
|
|
|
|
- .width(24)
|
|
|
|
|
- .height(24)
|
|
|
|
|
- }
|
|
|
|
|
- .visibility(this.isHide?Visibility.Hidden:Visibility.Visible)
|
|
|
|
|
- }
|
|
|
|
|
- .width(PlayConstants.ROW_WIDTH)
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 应用可以通过onStateChange接口监听组件显示/消失状态,当组件显示时建议不要销毁AVCastPicker的显示;当组件消失时,再根据业务隐藏AVCastPicker。
|
|
|
|
|
- private onStateVastChange(state: AVCastPickerState) {
|
|
|
|
|
- if (state == AVCastPickerState.STATE_APPEARING) {
|
|
|
|
|
- console.log('The picker starts showing.');
|
|
|
|
|
- } else if (state == AVCastPickerState.STATE_DISAPPEARING) {
|
|
|
|
|
- console.log('The picker finishes presenting.');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private showSelectLyric() {
|
|
|
|
|
- DialogHelper.showActionSheetDialog({
|
|
|
|
|
- title: "选择本地歌词",
|
|
|
|
|
- sheets: [ "选择本地歌词"],
|
|
|
|
|
- transition: AnimationHelper.transitionInDown(888),
|
|
|
|
|
- onAction: (index) => {
|
|
|
|
|
- switch (index){
|
|
|
|
|
- case 0:
|
|
|
|
|
- this.callFilePickerSelectFile()
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- // 拉起picker选择文件管理器
|
|
|
|
|
- async callFilePickerSelectFile(): Promise<void> {
|
|
|
|
|
- try {
|
|
|
|
|
- let DocumentSelectOptions = new picker.DocumentSelectOptions();
|
|
|
|
|
- DocumentSelectOptions.maxSelectNumber = 1
|
|
|
|
|
- DocumentSelectOptions.fileSuffixFilters = CommonConstants.LYRIC_FORMAT
|
|
|
|
|
- let documentPicker = new picker.DocumentViewPicker();
|
|
|
|
|
- documentPicker.select(DocumentSelectOptions).then((DocumentSelectResult) => {
|
|
|
|
|
- Logger.info(TAG,
|
|
|
|
|
- 'DocumentViewPicker.select successfully, DocumentSelectResult uri: ' + JSON.stringify(DocumentSelectResult));
|
|
|
|
|
-
|
|
|
|
|
- if (DocumentSelectResult !== null && DocumentSelectResult !== undefined) {
|
|
|
|
|
-
|
|
|
|
|
- this.saveVideoDatas(DocumentSelectResult)
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }).catch((err: BusinessError) => {
|
|
|
|
|
- Logger.error(TAG, 'DocumentViewPicker.select failed with err: ' + JSON.stringify(err));
|
|
|
|
|
- });
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- Logger.error(TAG, 'DocumentViewPicker failed with err: ' + JSON.stringify(err));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- async saveVideoDatas(uris:string[]){
|
|
|
|
|
- if(ArrayUtil.isEmpty(uris))
|
|
|
|
|
- return
|
|
|
|
|
- let newUris: string[] = [];
|
|
|
|
|
- for(let i=0;i<uris.length;i++){
|
|
|
|
|
- let filePath = getContext(this).filesDir +'/'+ Utility.getMediaNameByUri(uris[i])
|
|
|
|
|
- Logger.info(TAG,'filePath uri: ' + filePath);
|
|
|
|
|
- newUris.push(filePath)
|
|
|
|
|
- let file = fileIo.openSync(uris[i], fileIo.OpenMode.READ_ONLY)
|
|
|
|
|
- let file2 = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE)
|
|
|
|
|
- fileIo.copyFileSync(file.fd, file2.fd)
|
|
|
|
|
- fileIo.closeSync(file);
|
|
|
|
|
- fileIo.closeSync(file2);
|
|
|
|
|
- this.initLyric(filePath)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private initDelayPlay(context: object) {
|
|
|
|
|
- this.mContext = context;
|
|
|
|
|
- let that = this;
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- that.startPlayOrResumePlay();
|
|
|
|
|
- }, 200)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private startPlayOrResumePlay() {
|
|
|
|
|
- this.mDestroyPage = false;
|
|
|
|
|
- LogUtils.getInstance().LOGI("startPlayOrResumePlay start this.CONTROL_PlayStatus:" + this.CONTROL_PlayStatus)
|
|
|
|
|
- if (this.CONTROL_PlayStatus == PlayStatus.INIT) {
|
|
|
|
|
- this.stopProgressTask();
|
|
|
|
|
- this.startProgressTask();
|
|
|
|
|
- this.play(this.videoUrl.toString());
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- if (this.CONTROL_PlayStatus == PlayStatus.PAUSE) {
|
|
|
|
|
- this.mIjkMediaPlayer.start();
|
|
|
|
|
- this.setProgress()
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.PLAY
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- this.startRotation()
|
|
|
|
|
- this.updateSessionPlayState(true)
|
|
|
|
|
- this.watchStatus();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private completionNum(num: number): string | number {
|
|
|
|
|
- if (num < 10) {
|
|
|
|
|
- return '0' + num;
|
|
|
|
|
- } else {
|
|
|
|
|
- return num;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private stringForTime(timeMs: number): string {
|
|
|
|
|
- let totalSeconds: number | string = (timeMs / 1000);
|
|
|
|
|
- let newSeconds: number | string = totalSeconds % 60;
|
|
|
|
|
- let minutes: number | string = (totalSeconds / 60) % 60;
|
|
|
|
|
- let hours: number | string = totalSeconds / 3600;
|
|
|
|
|
- //LogUtils.getInstance().LOGI("stringForTime hours:" + hours + ",minutes:" + minutes + ",seconds:" + newSeconds);
|
|
|
|
|
- hours = this.completionNum(Math.floor(Math.floor(hours * 100) / 100));
|
|
|
|
|
- minutes = this.completionNum(Math.floor(Math.floor(minutes * 100) / 100));
|
|
|
|
|
- newSeconds = Math.floor(Math.floor(newSeconds * 100) / 100)
|
|
|
|
|
- if (this.isCurrentTime) {
|
|
|
|
|
- if (this.oldSeconds < newSeconds || newSeconds === 0 || this.isSeekTo) {
|
|
|
|
|
- this.oldSeconds = newSeconds
|
|
|
|
|
- } else {
|
|
|
|
|
- newSeconds = this.oldSeconds
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- newSeconds = this.completionNum(newSeconds);
|
|
|
|
|
- if (hours > 0) {
|
|
|
|
|
- return hours + ":" + minutes + ":" + newSeconds;
|
|
|
|
|
- } else {
|
|
|
|
|
- return minutes + ":" + newSeconds;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private setProgress() {
|
|
|
|
|
- let position = this.mIjkMediaPlayer.getCurrentPosition();
|
|
|
|
|
- let duration = this.mIjkMediaPlayer.getDuration();
|
|
|
|
|
- let pos = 0;
|
|
|
|
|
- if (duration > 0) {
|
|
|
|
|
- this.slideEnable = true;
|
|
|
|
|
- let curPercent = position / duration;
|
|
|
|
|
- pos = curPercent * 100;
|
|
|
|
|
- if (pos > this.PROGRESS_MAX_VALUE) {
|
|
|
|
|
- this.progressValue = this.PROGRESS_MAX_VALUE
|
|
|
|
|
- } else {
|
|
|
|
|
- this.progressValue = pos;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // LogUtils.getInstance()
|
|
|
|
|
- // .LOGI("setProgress position:" + position + ",duration:" + duration + ",progressValue:" + pos);
|
|
|
|
|
- this.totalTime = this.stringForTime(duration);
|
|
|
|
|
- if (position > duration) {
|
|
|
|
|
- position = duration;
|
|
|
|
|
- }
|
|
|
|
|
- this.isCurrentTime = true;
|
|
|
|
|
- this.lyricController.updatePosition(position)
|
|
|
|
|
- this.currentTime = this.stringForTime(position);
|
|
|
|
|
- this.isCurrentTime = false
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- if(this.mIjkMediaPlayer.isPlaying()){
|
|
|
|
|
- this.randomColor = `rgb(${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)})`
|
|
|
|
|
- // this.randomShakenX = 2 - Math.random() * 4
|
|
|
|
|
- // this.randomShakenY = 2 - Math.random() * 4
|
|
|
|
|
- }else{
|
|
|
|
|
- this.randomColor = 'rbg(0,0,0)'
|
|
|
|
|
- // this.randomShakenX = 0
|
|
|
|
|
- // this.randomShakenY = 0
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private startProgressTask() {
|
|
|
|
|
- let that = this;
|
|
|
|
|
- this.updateProgressTimer = setInterval(() => {
|
|
|
|
|
- //LogUtils.getInstance().LOGI("startProgressTask");
|
|
|
|
|
- if (!that.mDestroyPage) {
|
|
|
|
|
- that.setProgress();
|
|
|
|
|
- }
|
|
|
|
|
- }, 300);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private stopProgressTask() {
|
|
|
|
|
- LogUtils.getInstance().LOGI("stopProgressTask");
|
|
|
|
|
- clearInterval(this.updateProgressTimer);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private showLoadIng() {
|
|
|
|
|
- this.loadingVisible = Visibility.Visible;
|
|
|
|
|
- this.replayVisible = Visibility.None;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private hideLoadIng() {
|
|
|
|
|
- this.loadingVisible = Visibility.None;
|
|
|
|
|
- this.replayVisible = Visibility.None;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private showRePlay() {
|
|
|
|
|
- this.loadingVisible = Visibility.None;
|
|
|
|
|
- this.replayVisible = Visibility.Visible;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private async play(url: string) {
|
|
|
|
|
- let that = this;
|
|
|
|
|
- that.showLoadIng();
|
|
|
|
|
- //设置XComponent回调的context
|
|
|
|
|
- if (!!this.mContext) {
|
|
|
|
|
- this.mIjkMediaPlayer.setContext(this.mContext, 'xcomponentId');
|
|
|
|
|
- }
|
|
|
|
|
- if (this.CONTROL_PlayStatus == PlayStatus.INIT) {
|
|
|
|
|
- this.mIjkMediaPlayer.reset();
|
|
|
|
|
- }
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.PLAY;
|
|
|
|
|
- //设置debug模式
|
|
|
|
|
- this.mIjkMediaPlayer.setDebug(false);
|
|
|
|
|
- //初始化配置
|
|
|
|
|
- this.mIjkMediaPlayer.native_setup();
|
|
|
|
|
- // 初始化配置后需要重新设置音频流音量,否则音量为默认值1.0
|
|
|
|
|
- this.mIjkMediaPlayer.setVolume(this.volume.toString(), this.volume.toString());
|
|
|
|
|
- //设置视频源
|
|
|
|
|
- this.mIjkMediaPlayer.setDataSource(url);
|
|
|
|
|
- //设置视频源http请求头
|
|
|
|
|
- let headers = new Map([
|
|
|
|
|
- ["user_agent", "Mozilla/5.0 BiliDroid/7.30.0 (bbcallen@gmail.com)"],
|
|
|
|
|
- ["referer", "https://www.bilibili.com"]
|
|
|
|
|
- ]);
|
|
|
|
|
- this.mIjkMediaPlayer.setDataSourceHeader(headers);
|
|
|
|
|
- if(PreferencesUtil.getBooleanSync(SettingPage.IS_MIDIACODEC_OPEN,false)){
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", "1"); // 启用硬件解码,会导致无法顺序播放
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- //使用精确寻帧 例如,拖动播放后,会寻找最近的关键帧进行播放,很有可能关键帧的位置不是拖动后的位置,而是较前的位置.可以设置这个参数来解决问题
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", "1");
|
|
|
|
|
- const fileSize = await this.getFileSize(this.videoUrl);
|
|
|
|
|
- let bufferSize = 2 * 1024 * 1024; // 默认缓冲区大小为2MB
|
|
|
|
|
- if (fileSize > 3 * 1024 * 1024 * 1024) { // 文件大于3GB
|
|
|
|
|
- bufferSize = 25 * 1024 * 1024; // 设置缓冲区大小为25MB
|
|
|
|
|
- }
|
|
|
|
|
- //预读数据的缓冲区大小.修复大文件播放前几秒挂掉的bug,太大了会导致倍数播放失效
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", bufferSize +'');
|
|
|
|
|
- //停止预读的最小帧数
|
|
|
|
|
- // this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", "100");
|
|
|
|
|
-
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", '1');////重连模式,如果中途服务器断开了连接,让它重新连接
|
|
|
|
|
- // 设置其他缓冲相关选项
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", "100"); // 设置最小缓冲帧数
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-frames", "1000"); // 设置最大缓冲
|
|
|
|
|
- //启动预加载
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", "1");
|
|
|
|
|
- // 设置无缓冲,这是播放器的缓冲区,有数据就播放
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", "0");
|
|
|
|
|
- //跳帧处理,放CPU处理较慢时,进行跳帧处理,保证播放流程,画面和声音同步
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", "5");
|
|
|
|
|
- // 最大缓冲cache是3s, 有时候网络波动,会突然在短时间内收到好几秒的数据
|
|
|
|
|
- // 因此需要播放器丢包,才不会累积延时
|
|
|
|
|
- // 这个和第三个参数packet-buffering无关。
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", "3000");
|
|
|
|
|
- // 无限制收流
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", "1");
|
|
|
|
|
- this.mIjkMediaPlayer.setOptionLong(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", "1")
|
|
|
|
|
- // 屏幕常亮
|
|
|
|
|
- this.mIjkMediaPlayer.setScreenOnWhilePlaying(true);
|
|
|
|
|
- // 设置超时
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", "10000000");
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "connect_timeout", "10000000");
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "addrinfo_timeout", "10000000");
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", "10000000");
|
|
|
|
|
- // 变速播放
|
|
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", "1");
|
|
|
|
|
- this.mIjkMediaPlayer.setSpeed(this.playSpeed);
|
|
|
|
|
- let Speed = this.mIjkMediaPlayer.getSpeed()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getSpeed--' + Speed)
|
|
|
|
|
- //是否开启循环播放
|
|
|
|
|
- // this.mIjkMediaPlayer.setLoopCount(this.loop);
|
|
|
|
|
- let mOnVideoSizeChangedListener: OnVideoSizeChangedListener = {
|
|
|
|
|
- onVideoSizeChanged: (width: number, height: number, sar_num: number, sar_den: number) => {
|
|
|
|
|
- if (height === 0) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- const va = width / height;
|
|
|
|
|
- const vpa = that.videoParentAspectRatio;
|
|
|
|
|
- if (vpa > va) {
|
|
|
|
|
- that.videoWidth = (width / (height * vpa)) * 100 + '%';
|
|
|
|
|
- } else {
|
|
|
|
|
- that.videoWidth = '100%';
|
|
|
|
|
- }
|
|
|
|
|
- if (width && height) {
|
|
|
|
|
- that.videoAspectRatio = width / height;
|
|
|
|
|
- }
|
|
|
|
|
- LogUtils.getInstance()
|
|
|
|
|
- .LOGI("setOnVideoSizeChangedListener-->go:" + width + "," + height + "," + sar_num + "," + sar_den);
|
|
|
|
|
- that.getVideoSize();
|
|
|
|
|
- that.hideLoadIng();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
|
|
|
|
|
- let mOnPreparedListener: OnPreparedListener = {
|
|
|
|
|
- onPrepared: () => {
|
|
|
|
|
- this.cover = this.globalVideoList[this.curIndex].pixelMapPath
|
|
|
|
|
- this.artist = this.globalVideoList[this.curIndex].artist
|
|
|
|
|
- this.videoUrl = this.globalVideoList[this.curIndex].filePath
|
|
|
|
|
-
|
|
|
|
|
- let isBgCover = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_BG_COVER,false)
|
|
|
|
|
- if(isBgCover&&this.cover!=undefined&&StrUtil.isNotEmpty(this.cover)){
|
|
|
|
|
- this.setImageColor(this.cover)
|
|
|
|
|
- }else{
|
|
|
|
|
- this.getImageColor();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- this.startRotation()
|
|
|
|
|
- if(PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_MEMORY_PLAY,false)){
|
|
|
|
|
- this.restorePlaybackPosition()//读取播放记忆功能
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let lyricPath = this.videoUrl.substring(0,this.videoUrl.lastIndexOf('.'))+'.lrc'
|
|
|
|
|
- this.initLyric(lyricPath);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- LogUtils.getInstance().LOGI("setOnPreparedListener-->go");
|
|
|
|
|
- try{
|
|
|
|
|
- this.duration = this.mIjkMediaPlayer.getDuration()
|
|
|
|
|
-
|
|
|
|
|
- this.avSessionController.initAvSession(false);
|
|
|
|
|
- this.avSessionController.setAVMetadataMusic(this.globalVideoList[this.curIndex], this.duration);
|
|
|
|
|
- this.setAvSessionListener();
|
|
|
|
|
- this.updateSessionPlayState(true)
|
|
|
|
|
- }catch (error) {
|
|
|
|
|
- let err: BusinessError = error as BusinessError;
|
|
|
|
|
- console.error('onecold failed with err: ' + JSON.stringify(err));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnPreparedListener(mOnPreparedListener);
|
|
|
|
|
-
|
|
|
|
|
- let mOnTimedTextListener: OnTimedTextListener = {
|
|
|
|
|
- onTimedText: () => {
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnTimedTextListener(mOnTimedTextListener)
|
|
|
|
|
-
|
|
|
|
|
- let mOnCompletionListener: OnCompletionListener = {
|
|
|
|
|
- onCompletion: () => {
|
|
|
|
|
-
|
|
|
|
|
- LogUtils.getInstance().LOGI("OnCompletionListener-->go")
|
|
|
|
|
- if(this.playType == 0){//0:连续播放 1:单片重复播放 2:正常播放
|
|
|
|
|
- this.playNext()
|
|
|
|
|
- }else if(this.playType == 1){//1:单片重复播放
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.INIT
|
|
|
|
|
- that.startPlayOrResumePlay();
|
|
|
|
|
-
|
|
|
|
|
- }else if(this.playType == 2){//2:正常播放
|
|
|
|
|
-
|
|
|
|
|
- that.showRePlay();
|
|
|
|
|
- that.currentTime = that.stringForTime(this.mIjkMediaPlayer.getDuration());
|
|
|
|
|
- that.progressValue = this.PROGRESS_MAX_VALUE;
|
|
|
|
|
- that.slideEnable = false;
|
|
|
|
|
- that.stop();
|
|
|
|
|
- // ToastUtil.showToast('开始重新播放')
|
|
|
|
|
- }else if(this.playType == 3){//3:随机播放
|
|
|
|
|
- this.randomPlay()
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnCompletionListener(mOnCompletionListener);
|
|
|
|
|
-
|
|
|
|
|
- let mOnBufferingUpdateListener: OnBufferingUpdateListener = {
|
|
|
|
|
- onBufferingUpdate: (percent: number) => {
|
|
|
|
|
- LogUtils.getInstance().LOGI("OnBufferingUpdateListener-->go:" + percent);
|
|
|
|
|
- let MediaInfo = this.mIjkMediaPlayer.getMediaInfo()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getMediaInfo---' + MediaInfo);
|
|
|
|
|
- let VideoWidth = this.mIjkMediaPlayer.getVideoWidth()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getVideoWidth---' + VideoWidth);
|
|
|
|
|
-
|
|
|
|
|
- let VideoHeight = this.mIjkMediaPlayer.getVideoHeight()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getVideoHeight---' + VideoHeight);
|
|
|
|
|
-
|
|
|
|
|
- let VideoSarNum = this.mIjkMediaPlayer.getVideoSarNum()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getVideoSarNum---' + VideoSarNum);
|
|
|
|
|
-
|
|
|
|
|
- let VideoSarDen = this.mIjkMediaPlayer.getVideoSarDen()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getVideoSarDen---' + VideoSarDen);
|
|
|
|
|
-
|
|
|
|
|
- let AudioSessionId = this.mIjkMediaPlayer.getAudioSessionId()
|
|
|
|
|
- LogUtils.getInstance().LOGI('getAudioSessionId---' + AudioSessionId);
|
|
|
|
|
-
|
|
|
|
|
- let Looping = this.mIjkMediaPlayer.isLooping()
|
|
|
|
|
- LogUtils.getInstance().LOGI('isLooping---' + Looping);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
|
|
|
|
|
-
|
|
|
|
|
- let mOnSeekCompleteListener: OnSeekCompleteListener = {
|
|
|
|
|
- onSeekComplete: () => {
|
|
|
|
|
- LogUtils.getInstance().LOGI("OnSeekCompleteListener-->go");
|
|
|
|
|
-
|
|
|
|
|
- that.startPlayOrResumePlay();
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnSeekCompleteListener(mOnSeekCompleteListener);
|
|
|
|
|
-
|
|
|
|
|
- let mOnInfoListener: OnInfoListener = {
|
|
|
|
|
- onInfo: (what: number, extra: number) => {
|
|
|
|
|
- LogUtils.getInstance().LOGI("OnInfoListener-->go:" + what + "===" + extra);
|
|
|
|
|
- that.hideLoadIng();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.mIjkMediaPlayer.setOnInfoListener(mOnInfoListener);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- let mOnErrorListener: OnErrorListener = {
|
|
|
|
|
- onError: (what: number, extra: number) => {
|
|
|
|
|
- this.stopProgressTask();
|
|
|
|
|
- LogUtils.getInstance().LOGI("OnErrorListener-->go:" + what + "===" + extra)
|
|
|
|
|
- that.hideLoadIng();
|
|
|
|
|
- prompt.showToast({
|
|
|
|
|
- message: getContext().resourceManager.getStringByNameSync("Honey_the_video_is_playing_errant_The_system_is_wandering")
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- this.mIjkMediaPlayer.setOnErrorListener(mOnErrorListener);
|
|
|
|
|
-
|
|
|
|
|
- this.mIjkMediaPlayer.setMessageListener();
|
|
|
|
|
-
|
|
|
|
|
- this.mIjkMediaPlayer.prepareAsync();
|
|
|
|
|
-
|
|
|
|
|
- this.mIjkMediaPlayer.start();
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public async setAvSessionListener() {
|
|
|
|
|
- if (!this.avSessionController) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('play', this.sessionPlayCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('pause', this.sessionPauseCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('stop', this.sessionStopCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('playNext', this.sessionPlayNextCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('playPrevious', this.sessionPlayPreviousCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('fastForward', this.sessionFastForwardCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('rewind', this.sessionRewindCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('seek', this.sessionSeekCallback);
|
|
|
|
|
- this.avSessionController.getAvSession()?.on('outputDeviceChange', this.sessionOutputDeviceChange)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private sessionOutputDeviceChange = async (connectState: avSession.ConnectionState,
|
|
|
|
|
- device: avSession.OutputDeviceInfo) => {
|
|
|
|
|
- let currentDevice: avSession.DeviceInfo = device?.devices?.[0];
|
|
|
|
|
- if (currentDevice.castCategory === avSession.AVCastCategory.CATEGORY_REMOTE &&
|
|
|
|
|
- connectState === avSession.ConnectionState.STATE_CONNECTED) {
|
|
|
|
|
-
|
|
|
|
|
- await this.startCasting();
|
|
|
|
|
-
|
|
|
|
|
- } else if ((currentDevice.castCategory === avSession.AVCastCategory.CATEGORY_REMOTE &&
|
|
|
|
|
- connectState === avSession.ConnectionState.STATE_DISCONNECTED) ||
|
|
|
|
|
- (currentDevice.castCategory === avSession.AVCastCategory.CATEGORY_LOCAL &&
|
|
|
|
|
- connectState === avSession.ConnectionState.STATE_CONNECTED)) {
|
|
|
|
|
- if (device) {
|
|
|
|
|
- this.endCasting();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private async startCasting() {
|
|
|
|
|
- this.castController = await this.avSessionController.getAvSession()?.getAVCastController();
|
|
|
|
|
- this.setPlaybackStateChangeListener();
|
|
|
|
|
- this.pause();
|
|
|
|
|
- this.initQueueItem();
|
|
|
|
|
- this.prepare();
|
|
|
|
|
- let refToIsCasting: AbstractProperty<boolean> | undefined = AppStorage.ref('isCasting');
|
|
|
|
|
- refToIsCasting?.set(true);
|
|
|
|
|
- this.castSeek = true;
|
|
|
|
|
- this.isCastPlaying = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- async changeCasting() {
|
|
|
|
|
- this.castController = await this.avSessionController.getAvSession()?.getAVCastController();
|
|
|
|
|
- this.initQueueItem();
|
|
|
|
|
- this.prepare();
|
|
|
|
|
- this.setPlaybackStateChangeListener();
|
|
|
|
|
- this.isCastPlaying = true;
|
|
|
|
|
- this.castSeek = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public endCasting() {
|
|
|
|
|
- this.avSessionController.getAvSession()?.stopCasting();
|
|
|
|
|
- this.stopCast();
|
|
|
|
|
- this.isCastPlaying = false;
|
|
|
|
|
- let refToIsCasting: AbstractProperty<boolean> | undefined = AppStorage.ref('isCasting');
|
|
|
|
|
- refToIsCasting?.set(false);
|
|
|
|
|
- this.pause();
|
|
|
|
|
- this.setIsPlaying(false);
|
|
|
|
|
- // if (this.curIndex === this.curSource.index) {
|
|
|
|
|
- // this.play
|
|
|
|
|
- // this.seek(this.currentTime * 1000);
|
|
|
|
|
- // this.setIsPlaying(true);
|
|
|
|
|
- // } else {
|
|
|
|
|
- // this.pauseVideo();
|
|
|
|
|
- // this.setIsPlaying(false);
|
|
|
|
|
- // }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public setIsPlaying(isPlayer: boolean) {
|
|
|
|
|
- this.isPlaying = isPlayer;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private setPlaybackStateChangeListener(): void {
|
|
|
|
|
- this.castController?.on('playbackStateChange', 'all', this.playbackStateChangeListener);
|
|
|
|
|
- this.castController?.on('endOfStream', this.reloadCasting);
|
|
|
|
|
- this.castController?.on('playNext', this.playNextCallback);
|
|
|
|
|
- this.castController?.on('playPrevious', this.playPreviousCallback);
|
|
|
|
|
- }
|
|
|
|
|
- private updateSessionPlayState(isPlay: boolean): void {
|
|
|
|
|
- // if(!this.isBgPlayOpen)
|
|
|
|
|
- // return
|
|
|
|
|
- Logger.info(TAG, `updateIsPlay isPlay: ${isPlay}`);
|
|
|
|
|
- this.setAVSessionPlayState({
|
|
|
|
|
- state: isPlay ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
|
|
|
|
|
- position: {
|
|
|
|
|
- elapsedTime: this.mIjkMediaPlayer.getCurrentPosition(),
|
|
|
|
|
- updateTime: new Date().getTime()
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- private setAVSessionPlayState(playbackState: avSession.AVPlaybackState): void {
|
|
|
|
|
- this.avSessionController.setAvSessionPlayState(playbackState)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private positionChange(position: number) {
|
|
|
|
|
- this.currentTime2 = position / 1000;
|
|
|
|
|
- this.currentStringTime = secondToTime(Math.floor(position / 1000));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private playDurationChange(duration: number) {
|
|
|
|
|
- this.duration = duration;
|
|
|
|
|
- this.durationTime = Math.floor(this.duration / 1000);
|
|
|
|
|
- this.durationStringTime = secondToTime((this.durationTime));
|
|
|
|
|
- }
|
|
|
|
|
- private playbackStateChangeListener = (playbackState: avSession.AVPlaybackState) => {
|
|
|
|
|
- const duration = playbackState?.extras?.duration;
|
|
|
|
|
- if (typeof duration === 'number') {
|
|
|
|
|
- this.playDurationChange(duration as number);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (typeof playbackState?.position?.elapsedTime !== 'undefined') {
|
|
|
|
|
- this.positionChange(playbackState?.position?.elapsedTime);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (playbackState.state === CommonConstants2.PLAYBACK_STATE_PAUSE ||
|
|
|
|
|
- playbackState.state === CommonConstants2.PLAYBACK_STATE_STOP ||
|
|
|
|
|
- playbackState.state === CommonConstants2.PLAYBACK_STATE_PREPARE ||
|
|
|
|
|
- playbackState.state === CommonConstants2.PLAYBACK_STATE_INITIAL) {
|
|
|
|
|
- this.isCastPlaying = false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (playbackState.state === CommonConstants2.PLAYBACK_STATE_PLAY) {
|
|
|
|
|
- this.isCastPlaying = true;
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private reloadCasting = async () => {
|
|
|
|
|
-
|
|
|
|
|
- let item = this.globalVideoList[this.curIndex];
|
|
|
|
|
- // description.startPosition = 0;
|
|
|
|
|
- this.castItem = {
|
|
|
|
|
- itemId: this.curIndex,
|
|
|
|
|
- description: ({
|
|
|
|
|
- assetId: item.filePath,
|
|
|
|
|
- title: item.name,
|
|
|
|
|
- artist: '',
|
|
|
|
|
- // 网络资源投播,设置mediaUri; 本地资源投播,将本地文件打开后,相关的文件描述符设置到fdSrc
|
|
|
|
|
- mediaUri: item.filePath,
|
|
|
|
|
- // 该字段大写,音频'AUDIO',视频'VIDEO'
|
|
|
|
|
- mediaType: 'VIDEO',
|
|
|
|
|
- mediaSize: item.videoSize,
|
|
|
|
|
- //startPosition为投播当前进度,设置该字段可将本机播放进度同步到远端
|
|
|
|
|
- startPosition: this.mIjkMediaPlayer.getCurrentPosition(),
|
|
|
|
|
- // 投播资源播放时长,设置该字段可将本机播放时长同步到远端显示
|
|
|
|
|
- duration: this.duration,
|
|
|
|
|
- // albumCoverUri: 'https://www.example.jpeg',
|
|
|
|
|
- // albumTitle: '《ExampleAlbum》',
|
|
|
|
|
- appName: '看片神器',
|
|
|
|
|
- // DRM资源,需要配置支持的DRM类型, 以chinaDRM为例。
|
|
|
|
|
- // drmScheme: '3d5e6d35-9b9a-41e8-b843-dd3c6e72c42c',
|
|
|
|
|
- } as GeneratedObjectLiteralInterface_1)
|
|
|
|
|
- };
|
|
|
|
|
- this.prepare();
|
|
|
|
|
- this.isCastPlaying = true;
|
|
|
|
|
-
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- public playNextCallback = (): void => {
|
|
|
|
|
- this.playNext()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- public playPreviousCallback = (): void => {
|
|
|
|
|
- this.playPrevious()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- async prepare() {
|
|
|
|
|
- await this.castController?.prepare(this.castItem);
|
|
|
|
|
- await this.castController?.start(this.castItem);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public initQueueItem() {
|
|
|
|
|
- let item = this.globalVideoList[this.curIndex];
|
|
|
|
|
- // let description = this.urlVideoList[this.curIndex];
|
|
|
|
|
- let time = this.currentTime;
|
|
|
|
|
- // description.startPosition = time * 1000;
|
|
|
|
|
- this.castItem = {
|
|
|
|
|
- itemId: this.curIndex,
|
|
|
|
|
- description: {
|
|
|
|
|
- assetId: item.filePath,
|
|
|
|
|
- title: item.name,
|
|
|
|
|
- artist: '',
|
|
|
|
|
- // 网络资源投播,设置mediaUri; 本地资源投播,将本地文件打开后,相关的文件描述符设置到fdSrc
|
|
|
|
|
- mediaUri: item.filePath,
|
|
|
|
|
- // 该字段大写,音频'AUDIO',视频'VIDEO'
|
|
|
|
|
- mediaType: 'AUDIO',
|
|
|
|
|
- mediaSize: item.videoSize,
|
|
|
|
|
- //startPosition为投播当前进度,设置该字段可将本机播放进度同步到远端
|
|
|
|
|
- startPosition: this.mIjkMediaPlayer.getCurrentPosition(),
|
|
|
|
|
- // 投播资源播放时长,设置该字段可将本机播放时长同步到远端显示
|
|
|
|
|
- duration: this.duration,
|
|
|
|
|
- // albumCoverUri: 'https://www.example.jpeg',
|
|
|
|
|
- // albumTitle: '《ExampleAlbum》',
|
|
|
|
|
- appName: '看片神器',
|
|
|
|
|
- // DRM资源,需要配置支持的DRM类型, 以chinaDRM为例。
|
|
|
|
|
- // drmScheme: '3d5e6d35-9b9a-41e8-b843-dd3c6e72c42c',
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- async stopCast() {
|
|
|
|
|
- try {
|
|
|
|
|
- this.castController?.off('playbackStateChange');
|
|
|
|
|
- this.castController?.off('endOfStream');
|
|
|
|
|
- this.castController?.off('playNext');
|
|
|
|
|
- this.castController?.off('playPrevious');
|
|
|
|
|
- this.castController?.off('error');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.info(0x0000, TAG, `Failed to setAVCastController. code: ${error.code}, message: ${error.message}`);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private sessionPlayCallback = (): void => {
|
|
|
|
|
- this.playOrPause()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private sessionPauseCallback = (): void => {
|
|
|
|
|
- this.playOrPause()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private playOrPause(){
|
|
|
|
|
- if (this.CONTROL_PlayStatus === PlayStatus.PLAY) {
|
|
|
|
|
- this.pause();
|
|
|
|
|
- this.stopRotation()
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- this.startPlayOrResumePlay();
|
|
|
|
|
- this.startRotation()
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private sessionPlayNextCallback = (): void => {
|
|
|
|
|
- this.playNext()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private sessionPlayPreviousCallback = (): void => {
|
|
|
|
|
- this.playPrevious()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private sessionStopCallback = (): void => {
|
|
|
|
|
- this.stop()
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private sessionFastForwardCallback = (time?: number) => {
|
|
|
|
|
- if (!time) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (this.mIjkMediaPlayer!=null) {
|
|
|
|
|
- const curPosition = this.mIjkMediaPlayer.getCurrentPosition()
|
|
|
|
|
- let seeTime = curPosition + time* 1000;
|
|
|
|
|
- // 限制 seekValue 在合法范围内
|
|
|
|
|
- if (seeTime < 0) {
|
|
|
|
|
- seeTime = 0;
|
|
|
|
|
- } else if (seeTime > this.duration) {
|
|
|
|
|
- seeTime = this.duration;
|
|
|
|
|
- }
|
|
|
|
|
- Logger.info('onecold seeTime= ' + seeTime)
|
|
|
|
|
- this.setSeekToActionProgress(seeTime)
|
|
|
|
|
- this.seekTo(seeTime +"")
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private sessionRewindCallback = (time?: number) => {
|
|
|
|
|
- if (!time) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (this.mIjkMediaPlayer!=null) {
|
|
|
|
|
- const curPosition = this.mIjkMediaPlayer.getCurrentPosition()
|
|
|
|
|
- let seeTime = curPosition - time* 1000;
|
|
|
|
|
- // 限制 seekValue 在合法范围内
|
|
|
|
|
- if (seeTime < 0) {
|
|
|
|
|
- seeTime = 0;
|
|
|
|
|
- } else if (seeTime > this.duration) {
|
|
|
|
|
- seeTime = this.duration;
|
|
|
|
|
- }
|
|
|
|
|
- Logger.info('onecold seeTime= ' + seeTime)
|
|
|
|
|
- this.setSeekToActionProgress(seeTime)
|
|
|
|
|
- this.seekTo(seeTime +"")
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private sessionSeekCallback = (seekTime: number) => {
|
|
|
|
|
- if (this.mIjkMediaPlayer!=null) {
|
|
|
|
|
- const curPosition = this.mIjkMediaPlayer.getCurrentPosition()
|
|
|
|
|
- this.seekTo(seekTime+"")
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- private async getFileSize(filePath: string): Promise<number> {
|
|
|
|
|
- try {
|
|
|
|
|
- const stat = await fs.stat(filePath);
|
|
|
|
|
- return stat.size;
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- console.error('Failed to get file size: ' + err.message);
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //自动横屏功能
|
|
|
|
|
- private setAutoOrientation(){
|
|
|
|
|
- let VideoWidth = this.mIjkMediaPlayer.getVideoWidth();
|
|
|
|
|
- let VideoHeight = this.mIjkMediaPlayer.getVideoHeight();
|
|
|
|
|
- if(VideoHeight < VideoWidth) { //横屏屏视频
|
|
|
|
|
- this.setOrientation(window.Orientation.USER_ROTATION_LANDSCAPE);
|
|
|
|
|
- this.isLandscape = true;
|
|
|
|
|
- }else{
|
|
|
|
|
- this.setOrientation(window.Orientation.USER_ROTATION_PORTRAIT);
|
|
|
|
|
- this.isLandscape = false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private async getVideoSize() {
|
|
|
|
|
- if (this.mIjkMediaPlayer==null)
|
|
|
|
|
- return
|
|
|
|
|
- let VideoWidth = this.mIjkMediaPlayer.getVideoWidth();
|
|
|
|
|
- LogUtils.getInstance().LOGI("getVideoWidth---" + VideoWidth);
|
|
|
|
|
-
|
|
|
|
|
- let VideoHeight = this.mIjkMediaPlayer.getVideoHeight();
|
|
|
|
|
- LogUtils.getInstance().LOGI("getVideoHeight---" + VideoHeight);
|
|
|
|
|
- let scale = VideoHeight/VideoWidth//视频的长高比例
|
|
|
|
|
-
|
|
|
|
|
- let screenScale = this.screenHeight/ this.screenWidth//屏幕的长高比例
|
|
|
|
|
- let screenScale2 = (this.screenHeight-this.statusBarHeight)/ this.screenWidth//屏幕的长高比例:竖屏模式下用这个screenScale2 有去掉状态栏高度
|
|
|
|
|
- LogUtils.getInstance().LOGI("screenScale---" + screenScale);
|
|
|
|
|
-
|
|
|
|
|
- if(VideoHeight > VideoWidth){//竖屏视频
|
|
|
|
|
-
|
|
|
|
|
- if(this.isLandscape){
|
|
|
|
|
- this.videoWidth = (1/(screenScale*scale))*100+'%';
|
|
|
|
|
- // this.videoWidth = '26.5%';
|
|
|
|
|
- this.videoHeight = CommonConstants.FULL_PERCENT;;
|
|
|
|
|
- }else{
|
|
|
|
|
- this.videoWidth = CommonConstants.FULL_PERCENT;
|
|
|
|
|
- this.videoHeight = CommonConstants.FULL_PERCENT;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }else{//横屏视频
|
|
|
|
|
- if(this.isLandscape){
|
|
|
|
|
- if(this.isYesFull){
|
|
|
|
|
- this.videoWidth = '100%';
|
|
|
|
|
- this.videoHeight = '100%';
|
|
|
|
|
- }else{
|
|
|
|
|
- // this.videoWidth = '85.8%';
|
|
|
|
|
- this.videoWidth = (1/(screenScale*scale))*100+'%';
|
|
|
|
|
- this.videoHeight = '100%';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }else{
|
|
|
|
|
- this.videoWidth = '100%';
|
|
|
|
|
- // this.videoHeight = '27.5%';
|
|
|
|
|
- this.videoHeight = (scale/screenScale2)*100+'%';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private pause() {
|
|
|
|
|
- if (this.mIjkMediaPlayer.isPlaying()) {
|
|
|
|
|
- this.savePlaybackPosition();
|
|
|
|
|
- this.mIjkMediaPlayer.pause();
|
|
|
|
|
- this.setProgress();
|
|
|
|
|
- this.mDestroyPage = true;
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.PAUSE;
|
|
|
|
|
- this.updateSessionPlayState(false)
|
|
|
|
|
- this.playChange()
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private stop() {
|
|
|
|
|
- this.savePlaybackPosition();
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
|
|
- this.mIjkMediaPlayer.stop();
|
|
|
|
|
- this.mIjkMediaPlayer.release();
|
|
|
|
|
- this.stopProgressTask();
|
|
|
|
|
- this.updateSessionPlayState(false)
|
|
|
|
|
- this.playChange()
|
|
|
|
|
- this.watchStatus();
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //保持记忆播放功能
|
|
|
|
|
- private savePlaybackPosition() {
|
|
|
|
|
- if (this.mIjkMediaPlayer!=null) {
|
|
|
|
|
- const position = this.mIjkMediaPlayer.getCurrentPosition();
|
|
|
|
|
- // ToastUtil.showToast('保存记忆播放 = ' + position)
|
|
|
|
|
- const duration = this.mIjkMediaPlayer.getDuration();
|
|
|
|
|
- const threshold = 5000; // 阈值,单位为毫秒(这里设为5秒)
|
|
|
|
|
-
|
|
|
|
|
- // 如果播放位置接近视频末尾,则保存 position 为 0
|
|
|
|
|
- const playbackPosition = (duration - position < threshold) ? 0 : position;
|
|
|
|
|
- PreferencesUtil.putSync(this.videoUrl, playbackPosition);
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- //获取记忆播放功能
|
|
|
|
|
- private restorePlaybackPosition() {
|
|
|
|
|
- const position:number = PreferencesUtil.getNumberSync(this.videoUrl, 0);
|
|
|
|
|
- // ToastUtil.showToast('position = ' + position)
|
|
|
|
|
- if (this.mIjkMediaPlayer!=null && position > 0) {
|
|
|
|
|
- // ToastUtil.showToast('seekTo = ' + position)
|
|
|
|
|
- this.seekTo(position +"");
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private seekTo(value: string) {
|
|
|
|
|
- // this.stopProgressTask();
|
|
|
|
|
- this.mIjkMediaPlayer.seekTo(value);
|
|
|
|
|
- // this.startPlayOrResumePlay()
|
|
|
|
|
- // 在这里恢复计时器状态
|
|
|
|
|
- this.setProgress()
|
|
|
|
|
- // this.startProgressTask();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //下一个
|
|
|
|
|
- private playNext() {
|
|
|
|
|
- if (!this.debounce()) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if(ArrayUtil.isNotEmpty(this.globalVideoList)){
|
|
|
|
|
- if (this.curIndex == this.globalVideoList.length - 1) {
|
|
|
|
|
- this.curIndex = 0;
|
|
|
|
|
- } else {
|
|
|
|
|
- this.curIndex++;
|
|
|
|
|
- }
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
|
|
- this.stop();
|
|
|
|
|
- this.videoUrl = this.globalVideoList[this.curIndex].filePath;
|
|
|
|
|
- this.name = this.globalVideoList[this.curIndex].name
|
|
|
|
|
- this.startPlayOrResumePlay()
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //随机播放
|
|
|
|
|
- private randomPlay() {
|
|
|
|
|
- if (!this.debounce()) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if(ArrayUtil.isNotEmpty(this.globalVideoList)){
|
|
|
|
|
-
|
|
|
|
|
- this.curIndex=RandomUtil.getRandomNumber(0,this.globalVideoList.length - 1)
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
|
|
- this.stop();
|
|
|
|
|
- this.videoUrl = this.globalVideoList[this.curIndex].filePath;
|
|
|
|
|
- this.name = this.globalVideoList[this.curIndex].name
|
|
|
|
|
- this.startPlayOrResumePlay()
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private playIndex(index:number) {
|
|
|
|
|
- if (!this.debounce()) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if(ArrayUtil.isNotEmpty(this.globalVideoList)){
|
|
|
|
|
-
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
|
|
- this.stop();
|
|
|
|
|
- this.videoUrl = this.globalVideoList[index].filePath;
|
|
|
|
|
- this.name = this.globalVideoList[index].name
|
|
|
|
|
- this.curIndex = index;
|
|
|
|
|
- this.startPlayOrResumePlay()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //上一个
|
|
|
|
|
- private playPrevious() {
|
|
|
|
|
- if (!this.debounce()) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (this.curIndex == 0) {
|
|
|
|
|
- this.curIndex = this.globalVideoList.length-1;
|
|
|
|
|
- } else {
|
|
|
|
|
- this.curIndex--;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
|
|
- this.stop();
|
|
|
|
|
- this.videoUrl = this.globalVideoList[this.curIndex].filePath;
|
|
|
|
|
- this.name = this.globalVideoList[this.curIndex].name
|
|
|
|
|
- this.startPlayOrResumePlay()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- debounce() {
|
|
|
|
|
- const delay = 600;
|
|
|
|
|
- let cur = new Date().getTime();
|
|
|
|
|
- if (cur - this.last > delay) {
|
|
|
|
|
- this.last = cur;
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Sets whether the screen is a constant based on the playback status.
|
|
|
|
|
- */
|
|
|
|
|
- watchStatus() {
|
|
|
|
|
- // let windowClass = GlobalContext.getContext().getObject('windowClass') as window.Window;
|
|
|
|
|
- if (this.CONTROL_PlayStatus === PlayStatus.PLAY) {
|
|
|
|
|
- this.windowClass.setWindowKeepScreenOn(true);
|
|
|
|
|
- } else {
|
|
|
|
|
- this.windowClass.setWindowKeepScreenOn(false);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * Volume gesture method onActionStart.
|
|
|
|
|
- *
|
|
|
|
|
- * @param event Gesture event.
|
|
|
|
|
- */
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- onVolumeActionStart(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- if (!event) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- this.positionY = event.offsetY;
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * Gesture method onActionUpdate.
|
|
|
|
|
- *
|
|
|
|
|
- * @param event Gesture event.
|
|
|
|
|
- */
|
|
|
|
|
- onVolumeActionUpdate(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- if (!event) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (this.mIjkMediaPlayer === null) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!this.brightShow && !this.seekToShow ) {
|
|
|
|
|
- this.volumeShow = true;
|
|
|
|
|
- let changeVolume =(this.positionY - event.offsetY) / this.screenHeight;
|
|
|
|
|
- let volume: number = this.volume;
|
|
|
|
|
- let currentVolume = volume + changeVolume;
|
|
|
|
|
- let volumeMinFlag = currentVolume <= PlayConstants.MIN_VALUE;
|
|
|
|
|
- let volumeMaxFlag = currentVolume > PlayConstants.MAX_VALUE;
|
|
|
|
|
- this.volume = volumeMinFlag ? PlayConstants.MIN_VALUE :
|
|
|
|
|
- (volumeMaxFlag ? PlayConstants.MAX_VALUE : currentVolume);
|
|
|
|
|
- // Logger.info('onecold this.volume = ' + this.volume)
|
|
|
|
|
- this.mIjkMediaPlayer.setVolume(this.volume.toString(),this.volume.toString());
|
|
|
|
|
- this.positionY = event.offsetY;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private lastOffset: number = 0
|
|
|
|
|
- private accumulatedOffset: number = 0;//手势拖动的累计偏移量
|
|
|
|
|
- private initialPosition: number = 0;//初始拖动播放位置
|
|
|
|
|
- private DRAG_SPEED_FACTOR: number = 0.01; // 控制拖动速度的比例
|
|
|
|
|
- //手势拖动快进和快退
|
|
|
|
|
- onSeekToActionStart(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- if (!event) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- // 记录手势开始时的播放位置
|
|
|
|
|
- this.initialPosition = this.mIjkMediaPlayer.getCurrentPosition();
|
|
|
|
|
- this.lastOffset = event.offsetX;
|
|
|
|
|
- this.accumulatedOffset = 0; // 重置累计偏移量
|
|
|
|
|
- // 获取视频总时长
|
|
|
|
|
- const duration = this.mIjkMediaPlayer.getDuration();
|
|
|
|
|
- if (duration <= 5 * 60 * 1000) { // 小于5分钟
|
|
|
|
|
- this.DRAG_SPEED_FACTOR = 0.2;
|
|
|
|
|
- } else if (duration <= 20 * 60 * 1000) { // 大于5分钟小于20分钟
|
|
|
|
|
- this.DRAG_SPEED_FACTOR = 0.1;
|
|
|
|
|
- } else if (duration <= 30 * 60 * 1000) { // 大于20分钟小于30分钟
|
|
|
|
|
- this.DRAG_SPEED_FACTOR = 0.08;
|
|
|
|
|
- } else if (duration <= 40 * 60 * 1000) { // 大于30分钟小于40分钟
|
|
|
|
|
- this.DRAG_SPEED_FACTOR = 0.04;
|
|
|
|
|
- } else if (duration <= 90 * 60 * 1000) { // 大于40分钟小于90分钟
|
|
|
|
|
- this.DRAG_SPEED_FACTOR = 0.012;
|
|
|
|
|
- } else { // 大于90分钟
|
|
|
|
|
- this.DRAG_SPEED_FACTOR = 0.009;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- onSeekToActionUpdate(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- if (!event || this.mIjkMediaPlayer === null) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 当亮度和音量控制未显示时,进行快进/快退操作
|
|
|
|
|
- if (!this.brightShow && !this.volumeShow) {
|
|
|
|
|
- this.seekToShow = true;
|
|
|
|
|
-
|
|
|
|
|
- // 获取视频总时长
|
|
|
|
|
- const duration = this.mIjkMediaPlayer.getDuration();
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // 计算新的偏移量
|
|
|
|
|
- const newOffsetX = event.offsetX - this.lastOffset;
|
|
|
|
|
- this.lastOffset = event.offsetX;
|
|
|
|
|
-
|
|
|
|
|
- // 累积偏移量
|
|
|
|
|
- this.accumulatedOffset += newOffsetX;
|
|
|
|
|
-
|
|
|
|
|
- // 计算新的播放位置
|
|
|
|
|
- const offsetTime = this.accumulatedOffset * this.DRAG_SPEED_FACTOR * (duration / this.PROGRESS_MAX_VALUE);
|
|
|
|
|
- this.seekValue = this.initialPosition + offsetTime;
|
|
|
|
|
-
|
|
|
|
|
- // 限制 seekValue 在合法范围内
|
|
|
|
|
- if (this.seekValue < 0) {
|
|
|
|
|
- this.seekValue = 0;
|
|
|
|
|
- } else if (this.seekValue > duration) {
|
|
|
|
|
- this.seekValue = duration;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置快进/快退进度
|
|
|
|
|
- this.setSeekToActionProgress(this.seekValue);
|
|
|
|
|
-
|
|
|
|
|
- // 更新标志
|
|
|
|
|
- this.isSeekTo = true;
|
|
|
|
|
- this.mDestroyPage = false;
|
|
|
|
|
-
|
|
|
|
|
- LogUtils.getInstance().LOGI("slider-->seekValue: " + this.seekValue);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Gesture method onActionEnd.
|
|
|
|
|
- */
|
|
|
|
|
- onSeekToActionEnd(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- this.showLoadIng();
|
|
|
|
|
- LogUtils.getInstance().LOGI("slider-->seekValue end:" + this.seekValue);
|
|
|
|
|
- this.seekTo(this.seekValue + "");
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- this.isSeekTo = false;
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- this.volumeShow = false;
|
|
|
|
|
- this.brightShow = false;
|
|
|
|
|
- this.seekToShow = false;
|
|
|
|
|
- this.positionX = PlayConstants.POSITION_X;
|
|
|
|
|
- this.positionY = PlayConstants.POSITION_Y;
|
|
|
|
|
- }, PlayConstants.DISAPPEAR_TIME);
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * Gesture method onActionUpdate.
|
|
|
|
|
- *
|
|
|
|
|
- * @param event Gesture event.手势拖动设置快进和后退
|
|
|
|
|
- */
|
|
|
|
|
- private setSeekToActionProgress(position:number) {
|
|
|
|
|
- // let position = this.mIjkMediaPlayer.getCurrentPosition();
|
|
|
|
|
- let duration = this.mIjkMediaPlayer.getDuration();
|
|
|
|
|
- let pos = 0;
|
|
|
|
|
- if (duration > 0) {
|
|
|
|
|
- this.slideEnable = true;
|
|
|
|
|
- let curPercent = position / duration;
|
|
|
|
|
- pos = curPercent * 100;
|
|
|
|
|
- if (pos > this.PROGRESS_MAX_VALUE) {
|
|
|
|
|
- this.progressValue = this.PROGRESS_MAX_VALUE
|
|
|
|
|
- } else {
|
|
|
|
|
- this.progressValue = pos;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // LogUtils.getInstance()
|
|
|
|
|
- // .LOGI("setProgress position:" + position + ",duration:" + duration + ",progressValue:" + pos);
|
|
|
|
|
- this.totalTime = this.stringForTime(duration);
|
|
|
|
|
- if (position > duration) {
|
|
|
|
|
- position = duration;
|
|
|
|
|
- }
|
|
|
|
|
- this.isCurrentTime = true;
|
|
|
|
|
- this.currentTime = this.stringForTime(position);
|
|
|
|
|
- this.isCurrentTime = false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private initialBright: number = 0; // 手势开始时的初始亮度
|
|
|
|
|
- /**
|
|
|
|
|
- * Bright gesture method onActionStart.
|
|
|
|
|
- *
|
|
|
|
|
- * @param event Gesture event.
|
|
|
|
|
- */
|
|
|
|
|
- onBrightActionStart(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- if (!event) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- this.initialBright = this.bright; // 记录手势开始时的亮度
|
|
|
|
|
- this.positionY = event.offsetY;
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * Gesture method onActionUpdate.
|
|
|
|
|
- *
|
|
|
|
|
- * @param event Gesture event.手势拖动设置屏幕亮度值
|
|
|
|
|
- */
|
|
|
|
|
- onBrightActionUpdate(event?: GestureEvent) {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- if (!event) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (!this.seekToShow && !this.volumeShow) {
|
|
|
|
|
- // this.brightShow = true;
|
|
|
|
|
- // // Logger.info('onecold onBrightActionUpdate screenWidth = ' + this.screenWidth)
|
|
|
|
|
- // // Logger.info(' onecold onBrightActionUpdate screenHeight = ' + this.screenHeight)
|
|
|
|
|
- // let changeBright = (this.positionY - event.offsetY) / this.screenHeight;
|
|
|
|
|
- // let bright: number = this.bright;
|
|
|
|
|
- // let currentBright = bright + changeBright;
|
|
|
|
|
- // let brightMinFlag = currentBright <= PlayConstants.MIN_VALUE;
|
|
|
|
|
- // let brightMaxFlag = currentBright > PlayConstants.MAX_VALUE;
|
|
|
|
|
- // this.bright = brightMinFlag ? PlayConstants.MIN_VALUE :
|
|
|
|
|
- // (brightMaxFlag ? PlayConstants.MAX_VALUE : currentBright);
|
|
|
|
|
- // // Logger.info('onecold this.bright = ' + this.bright)
|
|
|
|
|
- // this.setBright()
|
|
|
|
|
- // this.positionY = event.offsetY;
|
|
|
|
|
-
|
|
|
|
|
- this.brightShow = true;
|
|
|
|
|
-
|
|
|
|
|
- // 计算亮度变化
|
|
|
|
|
- let changeBright = (this.positionY - event.offsetY) / this.screenHeight;
|
|
|
|
|
- let currentBright = this.initialBright + changeBright;
|
|
|
|
|
-
|
|
|
|
|
- // 确保亮度在允许的范围内
|
|
|
|
|
- if (currentBright < PlayConstants.MIN_VALUE) {
|
|
|
|
|
- currentBright = PlayConstants.MIN_VALUE;
|
|
|
|
|
- } else if (currentBright > PlayConstants.MAX_VALUE) {
|
|
|
|
|
- currentBright = PlayConstants.MAX_VALUE;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 更新亮度值
|
|
|
|
|
- this.bright = currentBright;
|
|
|
|
|
- this.setBright();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * Setting the brightness.设置屏幕亮度值
|
|
|
|
|
- */
|
|
|
|
|
- setBright() {
|
|
|
|
|
-
|
|
|
|
|
- // this.windowClass.setWindowBrightness(this.bright);
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- let promise = this.windowClass.setWindowBrightness(this.bright);
|
|
|
|
|
- promise.then(() => {
|
|
|
|
|
- console.info('Succeeded in setting the brightness.');
|
|
|
|
|
- }).catch((err: BusinessError) => {
|
|
|
|
|
- console.error('Failed to set the brightness. Cause: ' + JSON.stringify(err));
|
|
|
|
|
- });
|
|
|
|
|
- } catch (exception) {
|
|
|
|
|
- console.error('Failed to set the brightness. Cause: ' + JSON.stringify(exception));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Gesture method onActionEnd.
|
|
|
|
|
- */
|
|
|
|
|
- onActionEnd() {
|
|
|
|
|
- if(this.isVideoLock)
|
|
|
|
|
- return
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- this.volumeShow = false;
|
|
|
|
|
- this.brightShow = false;
|
|
|
|
|
- this.seekToShow = false;
|
|
|
|
|
- this.positionX = PlayConstants.POSITION_X;
|
|
|
|
|
- this.positionY = PlayConstants.POSITION_Y;
|
|
|
|
|
- }, PlayConstants.DISAPPEAR_TIME);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//视频气泡窗口的布局
|
|
|
|
|
-@Builder
|
|
|
|
|
-function customPopupBuilder(dataBu: BubbleBean) {
|
|
|
|
|
- List() {
|
|
|
|
|
- ForEach(dataBu.data, (item: string, index: number) => {
|
|
|
|
|
- ListItem() {
|
|
|
|
|
- Row(){
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- Text(item).padding({ top:12,bottom:12,right:10 ,left:10}).textAlign(TextAlign.Start).width("100%")
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }.onClick(() => {
|
|
|
|
|
- dataBu.onItemClick?.(index)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .width(72)
|
|
|
|
|
- .divider({
|
|
|
|
|
- strokeWidth:1,
|
|
|
|
|
- color:"#22FFFFFF"
|
|
|
|
|
- })
|
|
|
|
|
-}
|
|
|