蘑菇视频

第一次遇到这种情况,蘑菇视频app下载的横竖屏切换我试了三种方案,最后选了这一种

蘑菇视频252026-02-04 00:24:01

第一次遇到这种情况,蘑菇视频app下载的横竖屏切换我试了三种方案,最后选了这一种

第一次遇到这种情况,蘑菇视频app下载的横竖屏切换我试了三种方案,最后选了这一种

前言 第一次在蘑菇视频APP里遇到横竖屏切换的问题,场景是这样的:用户在列表里点开短视频,随手旋转手机希望横屏看大画面,但切换过程中播放器重启、UI错位、进度丢失或者状态栏和手势导航闪动,让体验很糟。为了兼顾流畅性和实现复杂度,我分别试了三种方案,最终选定了一个折衷最佳、体验也最自然的实现方法。下面把过程、优缺点和关键实现细节都写清楚,方便你直接拿去实现或参考。

问题拆解(为何会出问题)

  • Activity 随系统旋转会触发重建(onCreate),如果播放器没有做好状态保存就会重新加载。
  • 全屏切换、沉浸式状态栏、手势导航对布局和窗口 inset 的处理会产生冲突。
  • 有时只想旋转视频内容,而不是整个 Activity UI(比如保持评论区不动)。 因此要在“不卡顿、保状态、手势/状态栏不错乱、实现复杂度可控”之间权衡。

我尝试的三种方案(含优缺点)

方案一:强制 Activity 横/竖屏(Manifest 或 setRequestedOrientation) 做法简述:

  • 在打开视频的 Activity 里根据需求调用 setRequestedOrientation(ActivityInfo.SCREENORIENTATIONLANDSCAPE) 或在 Manifest 固定 orientation。 优点:
  • 最简单,实现最快;系统自动管理旋转、布局。 缺点:
  • Activity 会重建,播放器需要完整保存和恢复状态;在用户锁定屏幕方向时会失效或体验不佳;切换动画会显得突兀。 适用场景:
  • 产品对旋转体验要求不高、播放器可快速恢复或视频短小的场景。

方案二:拦截配置改变(configChanges)并在 onConfigurationChanged 中重排布局 做法简述:

  • 在 Manifest 的 Activity 上添加 configChanges="orientation|screenSize";
  • 覆写 onConfigurationChanged,按新方向调整播放器容器的 LayoutParams 和系统 UI(沉浸式/状态栏); 优点:
  • 避免 Activity 重建,可以平滑过渡;相对容易实现,兼容性良好。 缺点:
  • 需要自行处理所有窗口尺寸、inset、状态栏/导航变动逻辑;复杂场景下容易遗漏边界情况;部分设备或 OEM 行为差异需额外适配。 适用场景:
  • 想保留 Activity 状态但又不想做太复杂渲染变换的项目。

方案三(我最后选择的):保持 Activity 固定方向,仅旋转/变换视频渲染层(TextureView/SurfaceView) 做法简述:

  • Activity 保持竖屏(不触发重建),通过监听传感器或用户手动触发来决定视频渲染层的显示方向;
  • 使用 TextureView(或 SurfaceView + GLSurface)对视频画面做旋转矩阵或 setRotation,并动态调整宽高以保持正确的纵横比; 优点:
  • 用户界面(评论、控制栏、列表等)保持不动、状态不会丢失;旋转过程平滑,不引起 Activity 重建;可在锁屏方向情况下依然支持画面旋转(增强体验);更灵活地做过渡动画(旋转/缩放/平移)。 缺点:
  • 实现复杂度最高,需要处理触控映射(如果视频接受手势)、纵横比适配、系统 inset、不同设备的渲染差异;在某些设备上对 Surface 的旋转兼容性需测试。 适用场景:
  • 希望对用户体验做精细打磨、保持界面连续性、不想播放器重启的产品。

为什么我最终选方案三

  • 用户体验显著更好:观看过程中旋转不会丢失播放进度、不会让评论区和底部控制随之混乱;
  • 更灵活:可以实现画中画、局部旋转、动态缩放,满足后续更多交互需求;
  • 现实适配:蘑菇视频这种场景里,用户期待“无缝从竖屏切到横屏看大画面”,这点方案三最贴合。

关键实现思路(Android,基于 ExoPlayer + TextureView 的实现范例) 实现要点分步列出,兼顾可读性和可直接拿去用的代码思路(下面用 Kotlin 风格伪码说明,按需改成 Java):

1) 使用 TextureView 渲染视频(比 SurfaceView 更方便做旋转/缩放)

  • ExoPlayer 支持把渲染器输出到 TextureView。
  • TextureView 提供 setTransform(Matrix) 或 setRotation(float) 来做画面变换。

2) 锁定 Activity 方向,避免系统重建

  • Manifest/activity: 保持默认或固定竖屏,不使用 configChanges 来处理旋转(也可以同时处理,但我这边保持 Activity 不变更)。

3) 监听方向变化(两种常见方式)

  • 使用 OrientationEventListener 监听设备物理旋转(自动切横竖),或
  • 提供 UI 按钮让用户手动切换(更可控,避免传感器误判)。 示例: val orientationListener = object : OrientationEventListener(context) { override fun onOrientationChanged(degrees: Int) { // 判断横竖阈值,比如 45-135 为横向 // 简单阈值判断并去抖(比如需要连续 n 次)再触发切换 } } orientationListener.enable()

4) 计算并应用旋转矩阵(核心)

  • 如果视频本来是 16:9,竖屏容器是窄高的,横向时需要把 TextureView 宽高互换并保持纵横比。
  • 两种方式:直接 setRotation(90f/270f) 并调整 LayoutParams 宽高;或者使用 Matrix 做更精准的缩放和平移。 示例伪代码: fun rotateVideoTo(isLandscape: Boolean) { val tx = textureView if (isLandscape) { // 旋转90度并扩大宽度以填满屏幕(按策略:裁剪或适配) tx.rotation = 90f val params = tx.layoutParams params.width = ViewGroup.LayoutParams.MATCHPARENT params.height = calculateHeightForLandscape() // 可能需要屏幕宽度的某个值 tx.layoutParams = params } else { tx.rotation = 0f val params = tx.layoutParams params.width = ViewGroup.LayoutParams.MATCHPARENT params.height = calculateHeightForPortrait() tx.layoutParams = params } // 可在这里加过渡动画:tx.animate().rotation(…).setDuration(200).start() }

5) 处理触摸坐标映射(如果视频层有手势)

  • 当 TextureView 被旋转或变换后,触摸坐标需根据逆矩阵映射到原始视频坐标来处理缩放、拖拽等。
  • 可以通过 textureView.getMatrix() / invert 来完成。

6) 处理系统 UI 和沉浸式模式

  • 横屏时常需要隐藏状态栏和导航栏,记得在切横屏时调整 WindowInsets 或调用 WindowCompat.setDecorFitsSystemWindows,并在回竖屏时恢复。

7) 恢复播放状态、适配缓存与播放器 surface

  • 因为不重建 Activity,所以播放器不需要做太多恢复,但切换 surface 时要注意重新绑定 TextureView 到播放器(player.setVideoTextureView(textureView) 或对应 API)。

注意事项与坑

  • 某些 Android 设备在旋转 Surface 时会出现黑边或闪烁,测试范围要覆盖主流机型(小米、华为、三星、OPPO、vivo)。
  • 在横屏时,如果把评论区仍然保留在屏幕上,布局设计要小心(避免挤压或遮挡)。
  • 触摸映射和视频截图截图功能在旋转下要做额外映射处理。
  • 对于 iOS:思路类似,可使用 AVPlayer + AVPlayerLayer,调整 layer.transform 或用 UIView 的 transform,同时保持 ViewController 的方向不变。

一份可以直接参考的实现 checklist(方便复制到开发任务单)

  • [ ] 用 TextureView 渲染视频并确保 player 能在切换时重新绑定。
  • [ ] 在 Activity/Fragment 保持固定方向(不触发系统重建)。
  • [ ] 实现 OrientationEventListener 或提供手动切换按钮。
  • [ ] 实现 rotateVideoTo():用 rotation 或 Matrix 做平滑动画,并调整 LayoutParams 保持纵横比。
  • [ ] 处理触摸坐标映射(如果有手势交互)。
  • [ ] 横屏时隐藏系统 UI 并处理 WindowInsets;回竖屏时恢复。
  • [ ] 在若干机型上做回归测试,关注黑屏、闪烁、触摸偏移等问题。
  • [ ] 优化切换流畅度:动画时长、去抖逻辑、传感器阈值调优。

结语(为什么这个方案更适合蘑菇视频) 蘑菇视频这种消费型短视频/长视频混合的产品,用户希望“切换风格”时体验连贯、不要重复加载、也不要把评论和交互界面一起抖来抖去。保持 Activity 不变、只旋转渲染层不仅能保证播放连续性,还能在后续做更多增强交互(比如画中画、小窗拖拽、局部旋转)——这正是我最终选择这一方案的原因。

  • 不喜欢(1

猜你喜欢

网站分类
最新文章
最近发表
热门文章
随机文章
热门标签
标签列表