• Home
Name Date Size #Lines LOC

..--

AppScope/22-Oct-2025-3432

entry/22-Oct-2025-1,7311,598

hvigor/22-Oct-2025-3736

.gitignoreD22-Oct-2025133 1212

README.mdD22-Oct-20259.6 KiB219197

build-profile.json5D22-Oct-20251.3 KiB5656

code-linter.json5D22-Oct-2025957 3434

hvigorfile.tsD22-Oct-2025842 215

oh-package.json5D22-Oct-2025808 2524

ohosTest.mdD22-Oct-2025667 86

README.md

1# 短视频切换案例
2
3### 介绍
4
5本示例介绍了[@ohos.multimedia.media](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-media-kit/js-apis-media.md)组件和[@ohos.window](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/js-apis-window.md)接口以及使用[触摸热区](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-universal-attributes-touch-target.md)实现视频横竖屏切换及进度条热区拖动的功能。
6该场景多用于横竖屏视频等媒体播放。
7
8### 效果图预览
9
10<img src="./entry/src/main/resources/base/media/video_screen_direction_switching.gif" width="300">
11
12**使用说明**:
13
14* 点击全屏观看按钮,切换横屏窗口。
15* 点击左上角返回按钮,恢复竖屏窗口。
16* 在进度条上方位置横向拖动可带动进度条移动。
17
18## 实现步骤
19
201. 初始化[@ohos.multimedia.media](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-media-kit/js-apis-media.md)的AVPlayer。
21  ```ts
22  async Init(): Promise<void> {
23    await this.release();
24    const context = getContext(this);
25    // 获取fdSrc用于注册AVPlayer
26    context.resourceManager.getRawFd(this.fileName).then(async (value: resourceManager.RawFileDescriptor) => {
27      this.avPlayer = await media.createAVPlayer();
28      this.isCreate = true;
29      this.setSourceInfo(); // 视频信息上报函数
30      this.setStateChangeCallback(); // 状态机上报回调函数
31      this.avPlayer.fdSrc = {
32        fd: value.fd,
33        offset: value.offset,
34        length: value.length
35      };
36    });
37  }
38  ```
392. 当AVPlayer初始化完毕进入initialized状态时,将XComponent和AVPlayer通过surfaceId绑定,这样可以在XComponent组件内实现视频播放功能。比起Video组件,AVPlayer可以更方便自定义全屏动画效果。
40  ```ts
41  // TODO 知识点:XComponent和AVPlayer通过surfaceId绑定
42  setSurfaceID(): void {
43    logger.info('play video: surfaceID is:' + this.surfaceID);
44    this.avPlayer.surfaceId = this.surfaceID;
45  }
46  ```
473. 使用[AVPlayer](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-media-kit/js-apis-media.md#avplayer9)中的width和height属性判断是横屏视频还是竖屏视频,方便判断是否需要展示**全屏观看**按钮。
48```ts
49  case 'prepared':
50    logger.info('state prepared called');
51    this.isPlaying = true; // 准备完成阶段 开始播放
52    this.totalDuration = this.avPlayer.duration; // 获取视频时长
53    this.aspect_ratio = this.avPlayer.width / this.avPlayer.height; // 获取视频宽高比
54    if(this.avPlayer.width >= this.avPlayer.height) { // 判断是横屏视频还是竖屏视频
55      this.verticalVideo = false;
56    } else {
57      this.verticalVideo = true;
58    }
59    this.getPlay();
60    break;
61```
624. 调用[@ohos.window](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/js-apis-window.md)的 getLastWindow 方法获取当前应用内最上层的子窗口,若无应用子窗口,则返回应用主窗口。
635. 利用获取到的窗口对象,调用 setWindowSystemBarEnable 方法设置窗口是否显示导航栏和状态栏。
646. 调用窗口对象的 setPreferredOrientation 方法设置窗口旋转方向以及是否应用重力感应。
657. 调用窗口对象的setWindowLayoutFullScreen方法实现沉浸式布局。
66  ```ts
67  changeOrientation() {
68    // 获取UIAbility实例的上下文信息
69    let context = getContext(this);
70    // 调用该接口手动改变设备横竖屏状态(设置全屏模式,先强制横屏,再加上传感器模式)
71    window.getLastWindow(context).then((lastWindow) => {
72      if (this.isLandscape) {
73        // 设置窗口的布局是否为沉浸式布局
74        lastWindow.setWindowLayoutFullScreen(true, () => {
75          // 设置窗口全屏模式时导航栏、状态栏的可见模式
76          lastWindow.setWindowSystemBarEnable([]);
77          // 设置窗口的显示方向属性,AUTO_ROTATION_LANDSCAPE表示传感器自动横向旋转模式
78          lastWindow.setPreferredOrientation(window.Orientation.AUTO_ROTATION_LANDSCAPE);
79        });
80      } else {
81        // 设置窗口的显示方向属性,UNSPECIFIED表示未定义方向模式,由系统判定
82        lastWindow.setPreferredOrientation(window.Orientation.UNSPECIFIED, () => {
83          // 设置窗口全屏模式时导航栏、状态栏的可见模式
84          lastWindow.setWindowSystemBarEnable(WINDOW_SYSTEM_BAR, () => {
85            // 设置窗口的布局是否为沉浸式布局
86            lastWindow.setWindowLayoutFullScreen(false, () => {
87              setTimeout(() => {
88                // 设置退出全屏动画
89                animateTo({
90                  duration: ANIMATE_DURATION,
91                  onFinish: () => {
92                    this.fileName = '';
93                  }
94                }, () => {
95                  this.isFullScreen = !this.isFullScreen;
96                });
97              }, TIMEOUT_DURATION);
98            });
99          });
100        });
101      }
102    });
103  }
104  ```
1058. 对进度条整个组件设置[触摸热区](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-universal-attributes-touch-target.md)106  ```ts
107  Row() {
108    // ...
109    Slider({
110      value: Math.round(this.currentTime / this.totalDuration * 100)
111    })
112      .onChange((value: number, mode: SliderChangeMode) => {
113        if (this.isCreate) {
114          this.currentTime = this.totalDuration * value / 100;
115          this.avPlayer.seek(this.currentTime);
116          if (mode === SliderChangeMode.Moving) {
117            if (this.avPlayer.state === 'playing') {
118              this.getPause();
119            }
120          } else if (mode === SliderChangeMode.End) {
121            if (this.avPlayer.state === 'paused' && this.isPlaying) {
122              this.getPlay();
123            }
124          }
125        }
126      })
127    // ...
128  }
129  .hitTestBehavior(HitTestMode.Transparent) // 将组件的触摸测试类型设置为自身和子节点都响应触摸测试,不会阻塞兄弟节点的触摸测试,不会影响祖先节点的触摸测试。
130  .responseRegion( // 设置多个触摸热区
131    [
132      {
133        x: 0,
134        y: 0,
135        width: $r('app.string.video_screen_direction_switching_layout_100'),
136        height: $r('app.string.video_screen_direction_switching_layout_100')
137      },
138      {
139        x: 0,
140        y: $r('app.string.video_screen_direction_switching_layout_negative_200'),
141        width: $r('app.string.video_screen_direction_switching_layout_100'),
142        height: $r('app.string.video_screen_direction_switching_layout_200')
143      }
144    ]
145  )
146  .gesture( // 设置拖动手势,将距离变量与进度条变量进行绑定计算
147    PanGesture(new PanGestureOptions({
148      direction: PanDirection.Left | PanDirection.Right
149    }))
150      .onActionStart(() => {
151        this.flagValue = this.currentTime;
152      })
153      .onActionUpdate((event?: GestureEvent) => {
154        if (event) {
155          if (this.isCreate) {
156            if (this.avPlayer.state === 'playing') {
157              this.getPause();
158            }
159            this.currentTime =  (this.flagValue + this.totalDuration * (event.offsetX / 3) / 100) > this.totalDuration ? this.totalDuration : (this.flagValue + this.totalDuration * (event.offsetX / 3) / 100);
160          }
161        }
162      })
163      .onActionEnd(() => {
164        if (this.isCreate) {
165          this.avPlayer.seek(this.currentTime);
166          if (this.avPlayer.state === 'paused' && this.isPlaying) {
167            this.getPlay();
168          }
169        }
170      })
171  )
172  ```
173
174### 高性能知识点
175
1761. 本示例使用了[LazyForEach](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/quick-start/arkts-rendering-control-lazyforeach.md) 进行数据懒加载优化,以降低内存占用和渲染开销。
177
178### 工程结构&模块类型
179
180   ```
181   VideoSwitching                                     // hap
182   |---component
183   |   |---VideoComponent.ets                         // AVPlayer组件页面
184   |---model
185   |   |---BasicDataSource.ets                        // 数据类型文件
186   |---pages
187   |   |---Index.ets                                  // 入口文件
188   |---util
189   |   |---TimeTools.ets                              // 时间轴组件页面
190   |---view
191   |   |---VideoScreenDirectionSwitching.ets          // 视频横竖屏切换容器页面
192   ```
193
194### 参考资料
195
196[LazyForEach](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/quick-start/arkts-rendering-control-lazyforeach.md)
197
198[@ohos.multimedia.media](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-media-kit/js-apis-media.md)
199
200[@ohos.window](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/js-apis-window.md)
201
202### 约束与限制
203
2041.本示例仅支持在标准系统上运行。
205
2062.本示例仅支持API12版本SDK,版本号:5.0.0.71。
207
2082.本示例需要使用DevEco Studio 5.0.0 Release 才可编译运行。
209
210### 下载
211
212如需单独下载本工程,执行如下命令:
213```typescript
214git init
215git config core.sparsecheckout true
216echo /code/BasicFeature/Media/VideoSwitching/ > .git/info/sparse-checkout
217git remote add origin https://gitee.com/openharmony/applications_app_samples.git
218git pull origin master
219```