zhenghy

直播入口修改与添加竖屏直播页面

Showing 23 changed files with 972 additions and 22 deletions
@@ -26,6 +26,7 @@ export class Size { @@ -26,6 +26,7 @@ export class Size {
26 export class WindowModel { 26 export class WindowModel {
27 private windowStage?: window.WindowStage; 27 private windowStage?: window.WindowStage;
28 private windowClass?: window.Window; 28 private windowClass?: window.Window;
  29 + private isFullScreen: boolean = false
29 static shared: WindowModel = new WindowModel() 30 static shared: WindowModel = new WindowModel()
30 static TAG = "WindowModel"; 31 static TAG = "WindowModel";
31 32
@@ -129,7 +130,15 @@ export class WindowModel { @@ -129,7 +130,15 @@ export class WindowModel {
129 this.windowClass?.setWindowSystemBarProperties(systemBarProperties, (err: BusinessError) => { 130 this.windowClass?.setWindowSystemBarProperties(systemBarProperties, (err: BusinessError) => {
130 callback && callback(err) 131 callback && callback(err)
131 }) 132 })
  133 + }
  134 +
  135 + setWindowLayoutFullScreen(isFullScreen: boolean) {
  136 + this.isFullScreen = isFullScreen
  137 + this.windowClass?.setWindowLayoutFullScreen(isFullScreen)
  138 + }
132 139
  140 + getIsFullScreen(): boolean {
  141 + return this.isFullScreen
133 } 142 }
134 } 143 }
135 144
@@ -50,13 +50,17 @@ export function registerRouter() { @@ -50,13 +50,17 @@ export function registerRouter() {
50 50
51 Action2Page.register("JUMP_DETAIL_PAGE", (action: Action) => { 51 Action2Page.register("JUMP_DETAIL_PAGE", (action: Action) => {
52 if (action.params?.detailPageType == 2 || action.params?.detailPageType == 6) { 52 if (action.params?.detailPageType == 2 || action.params?.detailPageType == 6) {
  53 + if (action.params?.liveStyle === 0) {
53 return WDRouterPage.detailPlayLivePage 54 return WDRouterPage.detailPlayLivePage
  55 + } else {
  56 + return WDRouterPage.detailPlayVLivePage
  57 + }
54 } else if (action.params?.detailPageType == 7 || action.params?.detailPageType == 8) { 58 } else if (action.params?.detailPageType == 7 || action.params?.detailPageType == 8) {
55 return WDRouterPage.detailVideoListPage 59 return WDRouterPage.detailVideoListPage
56 - }else if(action.params?.detailPageType == 9){ 60 + } else if (action.params?.detailPageType == 9) {
57 //图集详情页 61 //图集详情页
58 return WDRouterPage.multiPictureDetailPage 62 return WDRouterPage.multiPictureDetailPage
59 - }else if(action.params?.detailPageType == 14 || action.params?.detailPageType == 15){ 63 + } else if (action.params?.detailPageType == 14 || action.params?.detailPageType == 15) {
60 //动态详情页 64 //动态详情页
61 return WDRouterPage.dynamicDetailPage 65 return WDRouterPage.dynamicDetailPage
62 } else if (action.params?.detailPageType == 17) { 66 } else if (action.params?.detailPageType == 17) {
@@ -12,4 +12,5 @@ export interface ExtraDTO extends ItemDTO { @@ -12,4 +12,5 @@ export interface ExtraDTO extends ItemDTO {
12 sourcePage: string; 12 sourcePage: string;
13 relId: string; 13 relId: string;
14 relType: string; 14 relType: string;
  15 + liveStreamType?: number
15 } 16 }
@@ -18,5 +18,6 @@ export interface Params { @@ -18,5 +18,6 @@ export interface Params {
18 // 8.专辑竖屏详情页 18 // 8.专辑竖屏详情页
19 // 13.音频详情页 19 // 13.音频详情页
20 // 17.多图(图集)详情页 20 // 17.多图(图集)详情页
21 - detailPageType?:number; // 详情页类型 21 + detailPageType?: number; // 详情页类型
  22 + liveStyle?: number; // 直播类型:0横屏,1竖屏
22 } 23 }
@@ -164,6 +164,7 @@ export interface LiveDetailsBean { @@ -164,6 +164,7 @@ export interface LiveDetailsBean {
164 //迁移id 164 //迁移id
165 oldNewsId: string 165 oldNewsId: string
166 reLInfo: ReLInfo 166 reLInfo: ReLInfo
  167 + rmhInfo: RmhInfo
167 } 168 }
168 169
169 export interface LiveInfo { 170 export interface LiveInfo {
@@ -189,8 +190,18 @@ export interface Vlive { @@ -189,8 +190,18 @@ export interface Vlive {
189 liveUrl: string 190 liveUrl: string
190 //直播回看地址,多路直播录制文件URL 191 //直播回看地址,多路直播录制文件URL
191 replayUri: string 192 replayUri: string
  193 + // 画面兼容 0-横屏流画面,1-竖屏流画面(仅竖屏直播使用)【前端使用, 可能竖屏模式但是直播流画面是横屏流,前端使用该字段】
  194 + liveStreamType: number | null
192 } 195 }
193 196
194 export interface ReLInfo { 197 export interface ReLInfo {
195 relId: string 198 relId: string
196 } 199 }
  200 +
  201 +export interface RmhInfo {
  202 + rmhName: string;
  203 + rmhHeadUrl: string;
  204 + rmhId: string;
  205 + userId: string;
  206 + userType: string;
  207 +}
@@ -4,6 +4,7 @@ import { Logger } from 'wdKit'; @@ -4,6 +4,7 @@ import { Logger } from 'wdKit';
4 import { StringUtils } from 'wdKit/src/main/ets/utils/StringUtils'; 4 import { StringUtils } from 'wdKit/src/main/ets/utils/StringUtils';
5 import { WDRouterRule } from 'wdRouter'; 5 import { WDRouterRule } from 'wdRouter';
6 import { ContentConstants } from '../constants/ContentConstants'; 6 import { ContentConstants } from '../constants/ContentConstants';
  7 +import { LiveModel } from '../viewmodel/LiveModel';
7 8
8 const TAG = 'ProcessUtils'; 9 const TAG = 'ProcessUtils';
9 10
@@ -71,7 +72,7 @@ export class ProcessUtils { @@ -71,7 +72,7 @@ export class ProcessUtils {
71 params: { 72 params: {
72 detailPageType: 14, 73 detailPageType: 14,
73 contentID: content?.objectId, 74 contentID: content?.objectId,
74 - extra:{ 75 + extra: {
75 relType: content?.relType, 76 relType: content?.relType,
76 relId: content?.relId, 77 relId: content?.relId,
77 } as ExtraDTO 78 } as ExtraDTO
@@ -91,7 +92,7 @@ export class ProcessUtils { @@ -91,7 +92,7 @@ export class ProcessUtils {
91 params: { 92 params: {
92 detailPageType: 17, 93 detailPageType: 17,
93 contentID: content?.objectId, 94 contentID: content?.objectId,
94 - extra:{ 95 + extra: {
95 relType: content?.relType, 96 relType: content?.relType,
96 relId: content?.relId, 97 relId: content?.relId,
97 } as ExtraDTO 98 } as ExtraDTO
@@ -111,6 +112,7 @@ export class ProcessUtils { @@ -111,6 +112,7 @@ export class ProcessUtils {
111 }; 112 };
112 WDRouterRule.jumpWithAction(taskAction) 113 WDRouterRule.jumpWithAction(taskAction)
113 } 114 }
  115 +
114 private static gotoWeb(content: ContentDTO) { 116 private static gotoWeb(content: ContentDTO) {
115 // // topicId 117 // // topicId
116 // content.channelId; 118 // content.channelId;
@@ -126,7 +128,7 @@ export class ProcessUtils { @@ -126,7 +128,7 @@ export class ProcessUtils {
126 params: { 128 params: {
127 contentID: content?.objectId, 129 contentID: content?.objectId,
128 pageID: 'IMAGE_TEXT_DETAIL', 130 pageID: 'IMAGE_TEXT_DETAIL',
129 - extra:{ 131 + extra: {
130 relType: content?.relType, 132 relType: content?.relType,
131 relId: content?.relId, 133 relId: content?.relId,
132 channelId: content?.channelId, 134 channelId: content?.channelId,
@@ -144,7 +146,7 @@ export class ProcessUtils { @@ -144,7 +146,7 @@ export class ProcessUtils {
144 params: { 146 params: {
145 detailPageType: 7, 147 detailPageType: 7,
146 contentID: content?.objectId, 148 contentID: content?.objectId,
147 - extra:{ 149 + extra: {
148 relType: content?.relType, 150 relType: content?.relType,
149 relId: content?.relId, 151 relId: content?.relId,
150 } as ExtraDTO 152 } as ExtraDTO
@@ -153,13 +155,23 @@ export class ProcessUtils { @@ -153,13 +155,23 @@ export class ProcessUtils {
153 WDRouterRule.jumpWithAction(taskAction) 155 WDRouterRule.jumpWithAction(taskAction)
154 Logger.debug(TAG, `gotoVod, ${content.objectId}`); 156 Logger.debug(TAG, `gotoVod, ${content.objectId}`);
155 } 157 }
156 - private static gotoLive(content: ContentDTO) { 158 +
  159 + private static async gotoLive(content: ContentDTO) {
  160 + const liveDetail = await LiveModel.getLiveDetails(content?.objectId || '', content?.relId || '', content?.relType || '')
  161 + const liveStyle = liveDetail[0].liveInfo.liveStyle
  162 + const liveState = liveDetail[0].liveInfo.liveState
  163 +
  164 +
  165 + console.error('liveDetail===', liveDetail)
  166 +
  167 +
157 let taskAction: Action = { 168 let taskAction: Action = {
158 type: 'JUMP_DETAIL_PAGE', 169 type: 'JUMP_DETAIL_PAGE',
159 params: { 170 params: {
160 detailPageType: 2, 171 detailPageType: 2,
161 contentID: content?.objectId, 172 contentID: content?.objectId,
162 - extra:{ 173 + liveStyle: liveState === 'wait' ? 0 : liveStyle,
  174 + extra: {
163 relType: content?.relType, 175 relType: content?.relType,
164 relId: content?.relId, 176 relId: content?.relId,
165 } as ExtraDTO 177 } as ExtraDTO
@@ -168,13 +180,14 @@ export class ProcessUtils { @@ -168,13 +180,14 @@ export class ProcessUtils {
168 WDRouterRule.jumpWithAction(taskAction) 180 WDRouterRule.jumpWithAction(taskAction)
169 Logger.debug(TAG, `gotoLive, ${content.objectId}`); 181 Logger.debug(TAG, `gotoLive, ${content.objectId}`);
170 } 182 }
  183 +
171 private static gotoAudio(content: ContentDTO) { 184 private static gotoAudio(content: ContentDTO) {
172 let taskAction: Action = { 185 let taskAction: Action = {
173 type: 'JUMP_DETAIL_PAGE', 186 type: 'JUMP_DETAIL_PAGE',
174 params: { 187 params: {
175 detailPageType: 13, 188 detailPageType: 13,
176 contentID: content?.objectId, 189 contentID: content?.objectId,
177 - extra:{ 190 + extra: {
178 relType: content?.relType, 191 relType: content?.relType,
179 relId: content?.relId, 192 relId: content?.relId,
180 } as ExtraDTO 193 } as ExtraDTO
@@ -183,5 +196,4 @@ export class ProcessUtils { @@ -183,5 +196,4 @@ export class ProcessUtils {
183 WDRouterRule.jumpWithAction(taskAction) 196 WDRouterRule.jumpWithAction(taskAction)
184 Logger.debug(TAG, `gotoAudio, ${content.objectId}`); 197 Logger.debug(TAG, `gotoAudio, ${content.objectId}`);
185 } 198 }
186 -  
187 } 199 }
  1 +import HashMap from '@ohos.util.HashMap';
  2 +import { HttpUrlUtils, ResponseDTO } from 'wdNetwork';
  3 +import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest';
  4 +import { Logger } from 'wdKit';
  5 +import { LiveDetailsBean } from 'wdBean/Index';
  6 +
  7 +const TAG = 'LiveModel'
  8 +
  9 +export class LiveModel {
  10 + /**
  11 + * 直播内容详情
  12 + * @param contentId
  13 + * @param relId 关系id
  14 + * @param relType 关系类型;1.频道关系;2.专题关系;
  15 + * @returns
  16 + */
  17 + static getLiveDetails(contentId: string, relId: string, relType: string) {
  18 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  19 + return new Promise<Array<LiveDetailsBean>>((success, fail) => {
  20 + HttpRequest.get<ResponseDTO<Array<LiveDetailsBean>>>(
  21 + HttpUrlUtils.getLiveDetailsUrl() + `?relId=${relId}&relType=${relType}&contentId=${contentId}`,
  22 + headers).then((data: ResponseDTO<Array<LiveDetailsBean>>) => {
  23 + if (!data || !data.data) {
  24 + fail("数据为空")
  25 + return
  26 + }
  27 + if (data.code != 0) {
  28 + fail(data.message)
  29 + return
  30 + }
  31 + success(data.data)
  32 + }, (error: Error) => {
  33 + fail(error.message)
  34 + Logger.debug(TAG + ":error ", error.toString())
  35 + })
  36 + })
  37 + }
  38 +}
  39 +
1 -import { BottomComponent } from '../widgets/details/BottomComponent';  
2 -import { TopPlayComponent } from '../widgets/details/video/TopPlayComponet';  
3 -import { TopPlayVComponent } from '../widgets/details/video/TopPlayVComponet'; 1 +import { Action, LiveDetailsBean, LiveRoomDataBean } from 'wdBean/Index';
  2 +import { LiveViewModel } from '../viewModel/LiveViewModel';
  3 +import router from '@ohos.router';
  4 +import { WindowModel } from 'wdKit/Index';
  5 +import { PlayerComponent } from '../widgets/vertical/PlayerComponent';
  6 +import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent';
  7 +import { WDPlayerController } from 'wdPlayer/Index';
4 8
  9 +const storage = LocalStorage.getShared();
5 10
  11 +@Entry(storage)
6 @Component 12 @Component
7 export struct DetailPlayVLivePage { 13 export struct DetailPlayVLivePage {
  14 + TAG: string = 'DetailPlayLivePage';
  15 + private liveViewModel: LiveViewModel = new LiveViewModel()
  16 + private playerController: WDPlayerController = new WDPlayerController();
  17 + private swiperController: SwiperController = new SwiperController()
  18 + @Provide bottomSafeHeight: number = AppStorage.get<number>('bottomSafeHeight') || 0
  19 + @Provide topSafeHeight: number = AppStorage.get<number>('topSafeHeight') || 0
  20 + @Provide liveDetailsBean: LiveDetailsBean = {} as LiveDetailsBean
  21 + @Provide liveRoomDataBean: LiveRoomDataBean = {} as LiveRoomDataBean
  22 + @Provide isMenuVisible: boolean = false
  23 + @State relId: string = ''
  24 + @State contentId: string = ''
  25 + @State relType: string = ''
  26 + @State swiperIndex: number = 1
  27 +
8 aboutToAppear(): void { 28 aboutToAppear(): void {
  29 + WindowModel.shared.setWindowLayoutFullScreen(true)
  30 + WindowModel.shared.setWindowSystemBarProperties({ statusBarContentColor: '#ffffff', })
  31 +
  32 + //https://pdapis.pdnews.cn/api/rmrb-bff-display-zh/content/zh/c/content/detail?relId=500005302448&relType=1&contentId=20000016340
  33 + let par: Action = router.getParams() as Action;
  34 + let params = par?.params;
  35 + this.relId = params?.extra?.relId || '';
  36 + this.relType = params?.extra?.relType || '';
  37 + this.contentId = params?.contentID || '';
  38 + this.getLiveDetails()
  39 + this.getLiveRoomData()
  40 + }
  41 +
  42 + aboutToDisappear(): void {
  43 + WindowModel.shared.setWindowLayoutFullScreen(false)
  44 + WindowModel.shared.setWindowSystemBarProperties({ statusBarContentColor: '#000000', })
9 45
10 } 46 }
11 47
12 build() { 48 build() {
13 Column() { 49 Column() {
14 - TopPlayVComponent()  
15 - // TabComponent()  
16 - BottomComponent() 50 + Stack() {
  51 + PlayerComponent({
  52 + playerController: this.playerController
  53 + })
  54 + .onClick(() => {
  55 + this.isMenuVisible = !this.isMenuVisible
  56 + })
  57 +
  58 + PlayerInfoComponent({
  59 + playerController: this.playerController,
  60 + swiperController: this.swiperController,
  61 + swiperIndex: $swiperIndex
  62 + })
  63 +
  64 + Image($r('app.media.icon_live_more'))
  65 + .width(40)
  66 + .aspectRatio(1)// .visibility(this.swiperIndex === 0 ? Visibility.Visible : Visibility.Hidden)
  67 + .animation({ duration: 500 })
  68 + .position({ x: '95%', y: '95%' })
  69 + .onClick(() => {
  70 + this.swiperController.showNext()
  71 + })
  72 + }
  73 + .height('100%')
  74 + .width('100%')
  75 +
17 } 76 }
18 .height('100%') 77 .height('100%')
19 .width('100%') 78 .width('100%')
@@ -23,7 +82,29 @@ export struct DetailPlayVLivePage { @@ -23,7 +82,29 @@ export struct DetailPlayVLivePage {
23 82
24 } 83 }
25 84
26 - aboutToDisappear(): void { 85 + getLiveDetails() {
  86 + this.liveViewModel.getLiveDetails(this.contentId, this.relId, this.relType)
  87 + .then(
  88 + (data) => {
  89 + if (data.length > 0) {
  90 + this.liveDetailsBean = data[0]
  91 + console.error('liveDetailsBean===', JSON.stringify((this.liveDetailsBean)))
  92 + }
  93 + },
  94 + () => {
27 95
  96 + })
  97 + }
  98 +
  99 + getLiveRoomData() {
  100 + this.liveViewModel.getLiveRoomData(this.contentId)
  101 + .then(
  102 + (data) => {
  103 + this.liveRoomDataBean = data
  104 + },
  105 + () => {
  106 +
  107 + })
28 } 108 }
29 } 109 }
  110 +
  1 +import { window } from '@kit.ArkUI'
  2 +import { NumberFormatterUtils, WindowModel } from 'wdKit/Index'
  3 +
  4 +import { devicePLSensorManager } from 'wdDetailPlayApi/Index'
  5 +import { DateFormatUtil, WDPlayerController } from 'wdPlayer/Index'
  6 +import { LiveDetailsBean, LiveRoomDataBean } from 'wdBean/Index'
  7 +
  8 +@Entry
  9 +@Component
  10 +export struct PlayVUIComponent {
  11 + playerController: WDPlayerController = new WDPlayerController();
  12 + //菜单键是否可见
  13 + @State isMenuVisible: boolean = true
  14 + @State isFullScreen: boolean = false
  15 + @Consume liveDetailsBean: LiveDetailsBean
  16 + @Consume liveRoomDataBean: LiveRoomDataBean
  17 + @State currentTime: string = ''
  18 + @State totalTime: string = ''
  19 + @State progressVal: number = 0;
  20 + //是否处于播放状态中
  21 + @State isPlayStatus: boolean = true
  22 +
  23 + aboutToAppear(): void {
  24 + //播放进度监听
  25 + this.playerController.onTimeUpdate = (position: number, duration: number) => {
  26 + this.currentTime = DateFormatUtil.secondToTime(Math.floor(position / 1000));
  27 + this.totalTime = DateFormatUtil.secondToTime(Math.floor(duration / 1000));
  28 + this.progressVal = Math.floor(position * 100 / duration);
  29 + }
  30 + }
  31 +
  32 + build() {
  33 + Column() {
  34 + this.getTopUIComponent()
  35 + this.getMiddleUIComponent()
  36 + this.getBottomUIComponent()
  37 + }
  38 + .width('100%')
  39 + .height('100%')
  40 + .alignItems(HorizontalAlign.Start)
  41 + }
  42 +
  43 + @Builder
  44 + getTopUIComponent() {
  45 + Column() {
  46 + Row() {
  47 + Image($r('app.media.icon_arrow_left_white'))
  48 + .width(24)
  49 + .aspectRatio(1)
  50 + .visibility(Visibility.None)
  51 + .margin({
  52 + right: 10
  53 + })
  54 + if (this.liveDetailsBean.liveInfo?.liveState != 'wait') {
  55 + Text(this.liveDetailsBean.newsTitle)
  56 + .maxLines(1)
  57 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  58 + .fontSize('16fp')
  59 + .fontWeight(500)
  60 + .fontColor(Color.White)
  61 + .textAlign(TextAlign.Start)
  62 + .layoutWeight(1)
  63 + } else {
  64 + Blank()
  65 + }
  66 + Image($r('app.media.icon_share'))
  67 + .width(24)
  68 + .aspectRatio(1)
  69 + .visibility(Visibility.None)
  70 + }
  71 + .width('100%')
  72 + .alignItems(VerticalAlign.Center)
  73 + .margin({
  74 + bottom: 10
  75 + })
  76 +
  77 + this.getLiveStatusView()
  78 + }.width('100%')
  79 + .padding({
  80 + top: 20,
  81 + bottom: 6,
  82 + left: 10,
  83 + right: 10
  84 + })
  85 + .alignItems(HorizontalAlign.Start)
  86 + .visibility(this.isMenuVisible ? Visibility.Visible : Visibility.None)
  87 + }
  88 +
  89 + @Builder
  90 + getLiveStatusView() {
  91 + // 直播新闻-直播状态 wait待开播running直播中end已结束cancel已取消paused暂停
  92 + // 预约
  93 + if (this.liveDetailsBean.liveInfo?.liveState == 'wait') {
  94 + Row() {
  95 + Image($r('app.media.icon_live_status_wait'))
  96 + .width(22)
  97 + .height(18)
  98 + Text('预约')
  99 + .fontSize('11fp')
  100 + .fontWeight(400)
  101 + .fontColor(Color.White)
  102 + }
  103 + .backgroundColor('#4D000000')
  104 + .padding({
  105 + top: 1,
  106 + right: 4,
  107 + bottom: 1
  108 + })
  109 + }
  110 + // 直播中
  111 + else if (this.liveDetailsBean.liveInfo?.liveState == 'running') {
  112 + Row() {
  113 + Image($r('app.media.icon_live_status_running'))
  114 + .width(22)
  115 + .height(18)
  116 + Text('直播中')
  117 + .fontSize('11fp')
  118 + .fontWeight(400)
  119 + .fontColor(Color.White)
  120 + Image($r('app.media.icon_live_player_status_end'))
  121 + .width(12)
  122 + .height(12)
  123 + Text(`${NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean.pv)}人参与`)
  124 + .fontSize('11fp')
  125 + .fontWeight(400)
  126 + .fontColor(Color.White)
  127 + }
  128 + .backgroundColor('#4D000000')
  129 + .padding({
  130 + top: 1,
  131 + right: 4,
  132 + bottom: 1
  133 + })
  134 + }
  135 + //回看
  136 + else if (this.liveDetailsBean.liveInfo?.liveState == 'end') {
  137 + Row() {
  138 + Text('回看')
  139 + .fontSize('11fp')
  140 + .fontWeight(400)
  141 + .fontColor(Color.White)
  142 + Image($r('app.media.icon_live_player_status_end'))
  143 + .width(12)
  144 + .height(12)
  145 + Text(`${NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean.pv)}人参与`)
  146 + .fontSize('11fp')
  147 + .fontWeight(400)
  148 + .fontColor(Color.White)
  149 + }
  150 + .backgroundColor('#4D000000')
  151 + .padding({
  152 + left: 4,
  153 + top: 1,
  154 + right: 4,
  155 + bottom: 1
  156 + })
  157 + }
  158 + }
  159 +
  160 + @Builder
  161 + getMiddleUIComponent() {
  162 + Stack()
  163 + .layoutWeight(1)
  164 + .width('100%')
  165 + .onClick(() => {
  166 + this.isMenuVisible = !this.isMenuVisible
  167 + })
  168 + }
  169 +
  170 + @Builder
  171 + getBottomUIComponent() {
  172 + Row() {
  173 + if (this.liveDetailsBean?.liveInfo?.liveState == 'end') {
  174 + this.playOrPauseBtn()
  175 + Text(this.currentTime)
  176 + .fontColor(Color.White)
  177 + .fontWeight(600)
  178 + .fontSize('12fp')
  179 + .margin({
  180 + left: 16
  181 + })
  182 +
  183 + this.playProgressView()
  184 +
  185 + Text(this.totalTime)
  186 + .fontColor(Color.White)
  187 + .fontWeight(600)
  188 + .fontSize('12fp')
  189 + .margin({
  190 + right: 16
  191 + })
  192 + } else {
  193 + Blank()
  194 + }
  195 + Image($r('app.media.icon_live_player_full_screen'))
  196 + .width(24)
  197 + .height(24)
  198 + .onClick(() => {
  199 + this.isFullScreen = !this.isFullScreen
  200 + WindowModel.shared.setPreferredOrientation(this.isFullScreen ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT);
  201 + devicePLSensorManager.devicePLSensorOn(this.isFullScreen ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT);
  202 + })
  203 + }
  204 + .alignItems(VerticalAlign.Center)
  205 + .linearGradient({ angle: 0, colors: [['#99000000', 0], ['#00000000', 1]] })
  206 + .width('100%')
  207 + .padding({
  208 + left: 10,
  209 + right: 10,
  210 + top: 15,
  211 + bottom: 15
  212 + })
  213 + .visibility(this.isMenuVisible ? Visibility.Visible : Visibility.None)
  214 + }
  215 +
  216 + @Builder
  217 + playOrPauseBtn() {
  218 + //暂停、播放
  219 + Image(this.isPlayStatus ? $r('app.media.icon_live_player_pause') : $r('app.media.player_play_ic'))
  220 + .width(24)
  221 + .height(24)
  222 + .onClick(() => {
  223 + if (this.isPlayStatus) {
  224 + this.isPlayStatus = false
  225 + this.playerController.pause()
  226 + } else {
  227 + this.isPlayStatus = true
  228 + this.playerController.play()
  229 + }
  230 + })
  231 + }
  232 +
  233 + @Builder
  234 + playProgressView() {
  235 + Slider({
  236 + value: this.progressVal,
  237 + step: 1,
  238 + style: SliderStyle.OutSet
  239 + })
  240 + .blockSize({
  241 + width: 18,
  242 + height: 12
  243 + })// .blockStyle({
  244 + // type: SliderBlockType.IMAGE,
  245 + // image: $r('app.media.ic_player_block')
  246 + // })
  247 + .blockColor(Color.White)
  248 + .trackColor('#4DFFFFFF')
  249 + .selectedColor('#FFED2800')
  250 + .height(14)
  251 + .trackThickness(1)
  252 + .layoutWeight(1)
  253 + .margin({
  254 + left: 8,
  255 + right: 8
  256 + })
  257 + .onChange((value: number, mode: SliderChangeMode) => {
  258 + this.playerController?.setSeekTime(value, mode);
  259 + })
  260 + }
  261 +}
  1 +@Component
  2 +export struct PlayerCommentComponent {
  3 + build() {
  4 + }
  5 +}
  1 +import { LiveDetailsBean } from 'wdBean/Index';
  2 +import { WDPlayerController, WDPlayerRenderVLiveView, WDPlayerRenderView } from 'wdPlayer/Index';
  3 +import componentUtils from '@ohos.arkui.componentUtils';
  4 +
  5 +
  6 +@Component
  7 +export struct PlayerComponent {
  8 + private playerController?: WDPlayerController;
  9 + // playerController: WDPlayerController = new WDPlayerController();
  10 + @Consume @Watch('updateData') liveDetailsBean: LiveDetailsBean
  11 + @State bottomSafeHeight: number = AppStorage.get<number>('bottomSafeHeight') || 0
  12 + @State topSafeHeight: number = AppStorage.get<number>('topSafeHeight') || 0
  13 + @State imgUrl: string = ''
  14 + @State isWait: boolean = false
  15 + @State liveStreamType: number | null = -1
  16 +
  17 + aboutToAppear(): void {
  18 + if (this.playerController) {
  19 + this.playerController.onCanplay = () => {
  20 + console.log('可以播放了')
  21 + this.playerController?.play()
  22 + // this.playerController.selfSize
  23 + }
  24 + }
  25 +
  26 + }
  27 +
  28 + aboutToDisappear(): void {
  29 + this.playerController?.pause()
  30 + this.playerController?.stop()
  31 + this.playerController?.release()
  32 + }
  33 +
  34 + updateData() {
  35 + console.error('updateData=============')
  36 + //直播新闻-直播状态 wait待开播running直播中end已结束cancel已取消paused暂停
  37 + if (this.liveDetailsBean.fullColumnImgUrls && this.liveDetailsBean.fullColumnImgUrls.length > 0) {
  38 + this.imgUrl = this.liveDetailsBean.fullColumnImgUrls[0].url
  39 + }
  40 + this.isWait = this.liveDetailsBean?.liveInfo?.liveState == 'wait'
  41 + if (this.liveDetailsBean.liveInfo && this.liveDetailsBean.liveInfo.vlive.length > 0) {
  42 + let playUrl = ''
  43 + let liveStreamType: number | null = null
  44 + if (this.liveDetailsBean.liveInfo.liveState == 'running') {
  45 + playUrl = this.liveDetailsBean.liveInfo.vlive[0].liveUrl
  46 + liveStreamType = this.liveDetailsBean.liveInfo.vlive[0].liveStreamType
  47 + } else if (this.liveDetailsBean.liveInfo.liveState == 'end') {
  48 + playUrl = this.liveDetailsBean.liveInfo.vlive[0].replayUri
  49 + liveStreamType = this.liveDetailsBean.liveInfo.vlive[0].liveStreamType
  50 + }
  51 + this.liveStreamType = liveStreamType
  52 + this.playerController?.firstPlay(playUrl);
  53 + }
  54 + }
  55 +
  56 + build() {
  57 + Column() {
  58 + Stack() {
  59 + Image(this.imgUrl)
  60 + .height('100%')
  61 + .width('100%')
  62 + .blur(100)
  63 +
  64 + // TODO:判断横竖屏,liveStreamType=1竖屏铺满屏幕,liveStreamType=0横屏正常展示
  65 + if (this.liveStreamType == null) {
  66 + WDPlayerRenderVLiveView({
  67 + playerController: this.playerController,
  68 + onLoad: () => {
  69 + }
  70 + }).height('100%')
  71 + .width('100%')
  72 + } else if (this.liveStreamType == 0) {
  73 + WDPlayerRenderView({
  74 + playerController: this.playerController,
  75 + onLoad: () => {
  76 + }
  77 + }).padding({ top: 195 })
  78 + }
  79 + }
  80 + .height('100%')
  81 + .width('100%')
  82 + .align(Alignment.Top)
  83 + .alignContent(Alignment.Top)
  84 + }
  85 + .height('100%')
  86 + .width('100%')
  87 + }
  88 +}
  1 +import { WDPlayerController } from 'wdPlayer/Index'
  2 +import { PlayerUIComponent } from './PlayerUIComponent'
  3 +
  4 +@Component
  5 +export struct PlayerInfoComponent {
  6 + swiperController?: SwiperController
  7 + @Prop playerController: WDPlayerController
  8 + @Consume bottomSafeHeight: number
  9 + @Consume topSafeHeight: number
  10 + @Link swiperIndex: number
  11 +
  12 + build() {
  13 + Column() {
  14 + Swiper(this.swiperController) {
  15 + Text('')
  16 + PlayerUIComponent({ playerController: this.playerController }).margin({
  17 + bottom: this.bottomSafeHeight + 'px',
  18 + top: this.topSafeHeight + 'px'
  19 + })
  20 +
  21 + }
  22 + .cachedCount(2)
  23 + .indicator(false)
  24 + .loop(false)
  25 + .width('100%')
  26 + .height('100%')
  27 + .index(this.swiperIndex)
  28 + .onChange((index) => {
  29 + this.swiperIndex = index
  30 + })
  31 + }
  32 + .height('100%')
  33 + .width('100%')
  34 + }
  35 +}
  1 +import { LiveDetailsBean, LiveRoomDataBean } from 'wdBean/Index'
  2 +import { NumberFormatterUtils } from 'wdKit/Index'
  3 +
  4 +@Component
  5 +export struct PlayerTitleComponent {
  6 + @Consume liveDetailsBean: LiveDetailsBean
  7 + @Consume liveRoomDataBean: LiveRoomDataBean
  8 +
  9 + build() {
  10 + Column() {
  11 + Row() {
  12 + Image($r('app.media.icon_arrow_left_white'))
  13 + .width(24)
  14 + .aspectRatio(1)
  15 + .visibility(Visibility.None)
  16 + .margin({
  17 + right: 10
  18 + })
  19 + if (this.liveDetailsBean.liveInfo?.liveState != 'wait') {
  20 + Text(this.liveDetailsBean.newsTitle)
  21 + .maxLines(1)
  22 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  23 + .fontSize('16fp')
  24 + .fontWeight(500)
  25 + .fontColor(Color.White)
  26 + .textAlign(TextAlign.Start)
  27 + .layoutWeight(1)
  28 + } else {
  29 + Blank()
  30 + }
  31 + Image($r('app.media.icon_share'))
  32 + .width(24)
  33 + .aspectRatio(1)
  34 + .visibility(Visibility.None)
  35 + }
  36 + .width('100%')
  37 + .alignItems(VerticalAlign.Center)
  38 + .margin({
  39 + bottom: 10
  40 + })
  41 +
  42 + this.getLiveStatusView()
  43 + }.width('100%')
  44 + .padding({
  45 + top: 20,
  46 + bottom: 6,
  47 + left: 10,
  48 + right: 10
  49 + })
  50 + .alignItems(HorizontalAlign.Start)
  51 + .visibility(Visibility.Visible)
  52 + }
  53 +
  54 + @Builder
  55 + getLiveStatusView() {
  56 + Row() {
  57 + Image(this.liveDetailsBean.rmhInfo.rmhHeadUrl)
  58 + .width(22)
  59 + .height(18)
  60 + Text(this.liveDetailsBean.rmhInfo.rmhName)
  61 + .fontSize('11fp')
  62 + .fontWeight(400)
  63 + .fontColor(Color.White)
  64 + }
  65 + .backgroundColor('#4D000000')
  66 + .padding({
  67 + top: 1,
  68 + right: 4,
  69 + bottom: 1
  70 + })
  71 +
  72 +
  73 + // 直播新闻-直播状态 wait待开播running直播中end已结束cancel已取消paused暂停
  74 + // 预约
  75 + if (this.liveDetailsBean.liveInfo?.liveState == 'wait') {
  76 + Row() {
  77 + Image($r('app.media.icon_live_status_wait'))
  78 + .width(22)
  79 + .height(18)
  80 + Text('预约')
  81 + .fontSize('11fp')
  82 + .fontWeight(400)
  83 + .fontColor(Color.White)
  84 + }
  85 + .backgroundColor('#4D000000')
  86 + .padding({
  87 + top: 1,
  88 + right: 4,
  89 + bottom: 1
  90 + })
  91 + }
  92 + // 直播中
  93 + else if (this.liveDetailsBean.liveInfo?.liveState == 'running') {
  94 + Row() {
  95 + Image($r('app.media.icon_live_status_running'))
  96 + .width(22)
  97 + .height(18)
  98 + Text('直播中')
  99 + .fontSize('11fp')
  100 + .fontWeight(400)
  101 + .fontColor(Color.White)
  102 + Image($r('app.media.icon_live_player_status_end'))
  103 + .width(12)
  104 + .height(12)
  105 + Text(`${NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean.pv)}人参与`)
  106 + .fontSize('11fp')
  107 + .fontWeight(400)
  108 + .fontColor(Color.White)
  109 + }
  110 + .backgroundColor('#4D000000')
  111 + .padding({
  112 + top: 1,
  113 + right: 4,
  114 + bottom: 1
  115 + })
  116 + }
  117 + //回看
  118 + else if (this.liveDetailsBean.liveInfo?.liveState == 'end') {
  119 + Row() {
  120 + Text('回看')
  121 + .fontSize('11fp')
  122 + .fontWeight(400)
  123 + .fontColor(Color.White)
  124 + Image($r('app.media.icon_live_player_status_end'))
  125 + .width(12)
  126 + .height(12)
  127 + Text(`${NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean.pv)}人参与`)
  128 + .fontSize('11fp')
  129 + .fontWeight(400)
  130 + .fontColor(Color.White)
  131 + }
  132 + .backgroundColor('#4D000000')
  133 + .padding({
  134 + left: 4,
  135 + top: 1,
  136 + right: 4,
  137 + bottom: 1
  138 + })
  139 + }
  140 + }
  141 +}
  1 +import { WDPlayerController } from 'wdPlayer/Index';
  2 +
  3 +@Component
  4 +export struct PlayerUIComponent {
  5 + playerController: WDPlayerController = new WDPlayerController();
  6 +
  7 + build() {
  8 + }
  9 +}
  1 +import { window } from '@kit.ArkUI'
  2 +import { NumberFormatterUtils, WindowModel } from 'wdKit/Index'
  3 +
  4 +import { devicePLSensorManager } from 'wdDetailPlayApi/Index'
  5 +import { DateFormatUtil, WDPlayerController } from 'wdPlayer/Index'
  6 +import { LiveDetailsBean, LiveRoomDataBean } from 'wdBean/Index'
  7 +
  8 +
  9 +@Component
  10 +export struct PlayerVideoControlComponent {
  11 + playerController: WDPlayerController = new WDPlayerController();
  12 + @Consume liveDetailsBean: LiveDetailsBean
  13 + @Consume liveRoomDataBean: LiveRoomDataBean
  14 + //菜单键是否可见
  15 + @State isMenuVisible: boolean = true
  16 + @State isFullScreen: boolean = false
  17 + @State currentTime: string = ''
  18 + @State totalTime: string = ''
  19 + @State progressVal: number = 0;
  20 + //是否处于播放状态中
  21 + @State isPlayStatus: boolean = true
  22 +
  23 + aboutToAppear(): void {
  24 + //播放进度监听
  25 + this.playerController.onTimeUpdate = (position: number, duration: number) => {
  26 + this.currentTime = DateFormatUtil.secondToTime(Math.floor(position / 1000));
  27 + this.totalTime = DateFormatUtil.secondToTime(Math.floor(duration / 1000));
  28 + this.progressVal = Math.floor(position * 100 / duration);
  29 + }
  30 + }
  31 +
  32 + build() {
  33 + Row() {
  34 + this.getBottomUIComponent()
  35 + }
  36 + }
  37 +
  38 + @Builder
  39 + getBottomUIComponent() {
  40 + Row() {
  41 + if (this.liveDetailsBean?.liveInfo?.liveState == 'end') {
  42 + this.playOrPauseBtn()
  43 + Text(this.currentTime)
  44 + .fontColor(Color.White)
  45 + .fontWeight(600)
  46 + .fontSize('12fp')
  47 + .margin({
  48 + left: 16
  49 + })
  50 +
  51 + this.playProgressView()
  52 +
  53 + Text(this.totalTime)
  54 + .fontColor(Color.White)
  55 + .fontWeight(600)
  56 + .fontSize('12fp')
  57 + .margin({
  58 + right: 16
  59 + })
  60 + } else {
  61 + Blank()
  62 + }
  63 + Image($r('app.media.icon_live_player_full_screen'))
  64 + .width(24)
  65 + .height(24)
  66 + .onClick(() => {
  67 + this.isFullScreen = !this.isFullScreen
  68 + WindowModel.shared.setPreferredOrientation(this.isFullScreen ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT);
  69 + devicePLSensorManager.devicePLSensorOn(this.isFullScreen ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT);
  70 + })
  71 + }
  72 + .alignItems(VerticalAlign.Center)
  73 + .linearGradient({ angle: 0, colors: [['#99000000', 0], ['#00000000', 1]] })
  74 + .width('100%')
  75 + .padding({
  76 + left: 10,
  77 + right: 10,
  78 + top: 15,
  79 + bottom: 15
  80 + })
  81 + .visibility(this.isMenuVisible ? Visibility.Visible : Visibility.None)
  82 + }
  83 +
  84 + @Builder
  85 + playOrPauseBtn() {
  86 + //暂停、播放
  87 + Image(this.isPlayStatus ? $r('app.media.icon_live_player_pause') : $r('app.media.player_play_ic'))
  88 + .width(24)
  89 + .height(24)
  90 + .onClick(() => {
  91 + if (this.isPlayStatus) {
  92 + this.isPlayStatus = false
  93 + this.playerController.pause()
  94 + } else {
  95 + this.isPlayStatus = true
  96 + this.playerController.play()
  97 + }
  98 + })
  99 + }
  100 +
  101 + @Builder
  102 + playProgressView() {
  103 + Slider({
  104 + value: this.progressVal,
  105 + step: 1,
  106 + style: SliderStyle.OutSet
  107 + })
  108 + .blockSize({
  109 + width: 18,
  110 + height: 12
  111 + })// .blockStyle({
  112 + // type: SliderBlockType.IMAGE,
  113 + // image: $r('app.media.ic_player_block')
  114 + // })
  115 + .blockColor(Color.White)
  116 + .trackColor('#4DFFFFFF')
  117 + .selectedColor('#FFED2800')
  118 + .height(14)
  119 + .trackThickness(1)
  120 + .layoutWeight(1)
  121 + .margin({
  122 + left: 8,
  123 + right: 8
  124 + })
  125 + .onChange((value: number, mode: SliderChangeMode) => {
  126 + this.playerController?.setSeekTime(value, mode);
  127 + })
  128 + }
  129 +}
1 { 1 {
2 "src": [ 2 "src": [
3 - "pages/DetailPlayLivePage" 3 + "pages/DetailPlayLivePage",
  4 + "pages/DetailPlayVLivePage"
4 ] 5 ]
5 } 6 }
@@ -179,7 +179,6 @@ export struct DetailPlayShortVideoPage { @@ -179,7 +179,6 @@ export struct DetailPlayShortVideoPage {
179 }) 179 })
180 .height('100%') 180 .height('100%')
181 .width('100%') 181 .width('100%')
182 - .margin({ top: this.contentDetailData?.videoInfo[0]?.videoLandScape === 1 ? 218 : 0 })  
183 .onClick(() => { 182 .onClick(() => {
184 console.error('WDPlayerRenderView=== onClick') 183 console.error('WDPlayerRenderView=== onClick')
185 this.playerController?.switchPlayOrPause(); 184 this.playerController?.switchPlayOrPause();
@@ -166,8 +166,7 @@ export struct DetailVideoListPage { @@ -166,8 +166,7 @@ export struct DetailVideoListPage {
166 }) 166 })
167 }.width('100%') 167 }.width('100%')
168 .height('100%') 168 .height('100%')
169 - // 扩展至所有非安全区域  
170 - .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) 169 +
171 }, (item: ContentDetailDTO) => item.newsId + '') 170 }, (item: ContentDetailDTO) => item.newsId + '')
172 } 171 }
173 .clip(false) 172 .clip(false)
@@ -61,6 +61,7 @@ export struct PlayerDetailContainer { @@ -61,6 +61,7 @@ export struct PlayerDetailContainer {
61 61
62 build() { 62 build() {
63 RelativeContainer() { 63 RelativeContainer() {
  64 + Row() {
64 Stack() { 65 Stack() {
65 Row() { 66 Row() {
66 this.playerView() 67 this.playerView()
@@ -68,6 +69,7 @@ export struct PlayerDetailContainer { @@ -68,6 +69,7 @@ export struct PlayerDetailContainer {
68 .height('100%') 69 .height('100%')
69 .width('100%') 70 .width('100%')
70 .zIndex(0) 71 .zIndex(0)
  72 + .margin({ top: this.videoLandScape === 1 ? 218 : 0 })
71 73
72 Row() { 74 Row() {
73 this.playControlView() 75 this.playControlView()
@@ -87,6 +89,7 @@ export struct PlayerDetailContainer { @@ -87,6 +89,7 @@ export struct PlayerDetailContainer {
87 // middle: { anchor: '__container__', align: HorizontalAlign.Center } 89 // middle: { anchor: '__container__', align: HorizontalAlign.Center }
88 }) 90 })
89 .id('stk_player_container') 91 .id('stk_player_container')
  92 + }.height('100%').layoutWeight(1)
90 93
91 if (this.isShowBottomView()) { 94 if (this.isShowBottomView()) {
92 Row() { 95 Row() {
@@ -4,6 +4,8 @@ export { WDPlayerRenderView } from "./src/main/ets/pages/WDPlayerRenderView" @@ -4,6 +4,8 @@ export { WDPlayerRenderView } from "./src/main/ets/pages/WDPlayerRenderView"
4 4
5 export { WDPlayerRenderLiveView } from "./src/main/ets/pages/WDPlayerRenderLiveView" 5 export { WDPlayerRenderLiveView } from "./src/main/ets/pages/WDPlayerRenderLiveView"
6 6
  7 +export { WDPlayerRenderVLiveView } from "./src/main/ets/pages/WDPlayerRenderVLiveView"
  8 +
7 export { PlayerConstants } from "./src/main/ets/constants/PlayerConstants" 9 export { PlayerConstants } from "./src/main/ets/constants/PlayerConstants"
8 10
9 export { SpeedBean } from "./src/main/ets/bean/SpeedBean" 11 export { SpeedBean } from "./src/main/ets/bean/SpeedBean"
  1 +import componentUtils from '@ohos.arkui.componentUtils';
  2 +import { WDPlayerController } from '../controller/WDPlayerController'
  3 +import { WindowModel } from 'wdKit';
  4 +import { Logger } from '../utils/Logger';
  5 +
  6 +class Size {
  7 + width: Length = "100%";
  8 + height: Length = "100%";
  9 +
  10 + constructor(width: Length, height: Length) {
  11 + this.width = width;
  12 + this.height = height;
  13 + }
  14 +}
  15 +
  16 +let insIndex: number = 0;
  17 +const TAG = 'WDPlayerRenderView'
  18 +
  19 +class MGPlayRenderViewIns {
  20 + static intCount: number = 0;
  21 +
  22 + static add() {
  23 + MGPlayRenderViewIns.intCount++;
  24 + WindowModel.shared.setWindowKeepScreenOn(true);
  25 + console.log("add-- +1")
  26 + }
  27 +
  28 + static del() {
  29 + console.log("del-- -1")
  30 + MGPlayRenderViewIns.intCount--;
  31 + if (MGPlayRenderViewIns.intCount <= 0) {
  32 + WindowModel.shared.setWindowKeepScreenOn(false);
  33 + }
  34 + }
  35 +}
  36 +
  37 +/**
  38 + * 播放窗口组件
  39 + */
  40 +@Component
  41 +export struct WDPlayerRenderVLiveView {
  42 + private playerController?: WDPlayerController;
  43 + private xComponentController: XComponentController = new XComponentController();
  44 + private insId: string = "WDPlayRenderView" + insIndex;
  45 + onLoad?: ((event?: object) => void);
  46 + @State videoWidth: number = 0
  47 + @State videoHeight: number = 0
  48 + @State selfSize: Size = new Size('100%', '100%');
  49 +
  50 + aboutToAppear() {
  51 + MGPlayRenderViewIns.add();
  52 +
  53 + insIndex++;
  54 + if (!this.playerController) {
  55 + return
  56 + }
  57 +
  58 + this.playerController.onVideoSizeChange = (width: number, height: number) => {
  59 + // console.log(`WDPlayerRenderView onVideoSizeChange width:${width} videoTop:${height}`)
  60 + Logger.info(TAG, ` onVideoSizeChange width:${width} videoTop:${height}`)
  61 + this.videoWidth = width;
  62 + this.videoHeight = height;
  63 + this.updateLayout()
  64 + }
  65 + }
  66 +
  67 + aboutToDisappear() {
  68 + Logger.info(TAG, `aboutToDisappear`)
  69 + MGPlayRenderViewIns.del();
  70 + }
  71 +
  72 + build() {
  73 + Row() {
  74 + // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。
  75 + XComponent({
  76 + id: 'xComponentId',
  77 + type: 'surface',
  78 + controller: this.xComponentController
  79 + })
  80 + .onLoad(async (event) => {
  81 + Logger.info(TAG, 'onLoad')
  82 + // const surfaceId = this.xComponentController.getXComponentSurfaceId()
  83 + this.xComponentController.setXComponentSurfaceSize({
  84 + surfaceWidth: 1920,
  85 + surfaceHeight: 1080
  86 + });
  87 + this.playerController?.setXComponentController(this.xComponentController)
  88 + if (this.onLoad) {
  89 + this.onLoad(event)
  90 + }
  91 + })// .width(this.selfSize.width)
  92 + // .height(this.selfSize.height)
  93 + .height('100%')
  94 + .width('100%')
  95 + }
  96 + .id(this.insId)
  97 + .onAreaChange(() => {
  98 + // this.updateLayout()
  99 + })
  100 + .backgroundColor("#000000")
  101 + .height('100%')
  102 + .width('100%')
  103 + }
  104 +
  105 + updateLayout() {
  106 + let info = componentUtils.getRectangleById(this.insId);
  107 + if (info.size.width > 0 && info.size.height > 0 && this.videoHeight > 0 && this.videoWidth > 0) {
  108 + if (info.size.width / info.size.height > this.videoWidth / this.videoHeight) {
  109 + let scale = info.size.height / this.videoHeight;
  110 + this.selfSize = new Size((this.videoWidth * scale / info.size.width) * 100 + "%", '100%');
  111 + } else {
  112 + let scale = info.size.width / this.videoWidth;
  113 + this.selfSize = new Size('100%', (this.videoHeight * scale / info.size.height) * 100 + "%");
  114 + }
  115 + }
  116 + }
  117 +}
@@ -97,6 +97,9 @@ export struct WDPlayerRenderView { @@ -97,6 +97,9 @@ export struct WDPlayerRenderView {
97 // this.updateLayout() 97 // this.updateLayout()
98 }) 98 })
99 .backgroundColor("#000000") 99 .backgroundColor("#000000")
  100 +
  101 + // .height('100%')
  102 + // .width('100%')
100 } 103 }
101 104
102 updateLayout() { 105 updateLayout() {