@hadss/react_native_adaptive_video
v1.0.0-rc.0
Published
RN framework-oriented multi-device adaptive video package
Downloads
9
Readme
@hadss/react_native_adaptive_video
介绍
这是一个旨在解决短视频多设备自适应问题的三方库,专为不同设备类型(包括折叠屏、平板、手机等)提供了便捷的支持。该库包含的接口和开箱即用的组件,使开发者能够轻松应对各种设备的布局适配需求。
- 自适应视频沉浸式:用于布局视频页面沉浸式体验,针对不同尺寸的窗口和不同尺寸的视频,本框架会为视频的非全屏页面提供沉浸建议。
- 自适应视频旋转:用于布局视频页面旋转体验,针对不同尺寸的窗口和不同尺寸的视频,本框架会自动设置视频的旋转属性。
工程目录
src
├── immersion // 自适应沉浸
│ ├── api
│ │ └── AdaptiveImmersion.ts // 沉浸接口类
│ ├── common
│ │ └── ImmersionConstants.ts // 常量类
│ └── rule
│ └── ImmersionRuleSet.ts // 沉浸规则
├── index.ts // 入口
└── rotation // 自适配旋转
├── api
│ └── AdaptiveRotation.ts // 旋转接口类
├── rule
│ ├── Breakpoint.ts // 断点规则
│ ├── HarmonyOrientation.ts // HarmonoyOS Orientation 旋转规则
│ └── RotationDatabase.ts // 旋转规则
└── utils
└── SensorUtil.ts // 传感器工具类使用说明
自适应沉浸库AdaptiveImmersion使用示例
import React from 'react';
import {StyleSheet, View, Text, StatusBar} from 'react-native';
import Video from 'react-native-video';
import {videoImmersionList} from '../../components/videos';
import {AdaptiveImmersion} from '@hadss/react_native_adaptive_video';
import {useFocusEffect} from '@react-navigation/native';
import {
SafeAreaView,
useSafeAreaInsets,
useSafeAreaFrame,
} from '@react-native-oh-tpl/react-native-safe-area-context';
const BOTTOM_TAB_HEIGHT = 50; // dp
const VideoDetail = ({route, navigation}) => {
const insets = useSafeAreaInsets();
const frame = useSafeAreaFrame();
console.log(
`窗口宽vp:${frame.width} 高vp:${frame.height} 宽高比:${(
frame.width / frame.height
).toFixed(2)} 状态栏高度vp:${
insets.top
} 底部栏高度vp:${BOTTOM_TAB_HEIGHT}`,
);
const {id} = route.params;
const video = videoImmersionList[id];
// 调用单例方法获取沉浸规则:传入视频宽高、当前窗口大小、状态栏高度和底部tab组件高度
const immersionInfo = AdaptiveImmersion.getInstance().getImmersionInfo(
{width: video.width, height: video.height},
{width: frame.width, height: frame.height},
insets.top,
BOTTOM_TAB_HEIGHT,
);
if (!immersionInfo) {
throw new Error('get immersionInfo failed');
}
// 获取视频播放组件的宽高
const {width: videoWidth, height: videoHeight} = immersionInfo.videoSize;
// 获取视频播放组件的位置 x,y (相对屏幕左上角)
const videoPosition = immersionInfo.videoPosition;
// 获取底部tab栏是否沉浸
const opacity = immersionInfo.immersionSetting.isBottomTabImmersive
? 0.5
: 1.0;
// 获取状态栏是否沉浸
const isStatusBarImmersive =
immersionInfo.immersionSetting.isStatusBarImmersive;
useFocusEffect(
React.useCallback(() => {
if (isStatusBarImmersive) {
// 进入页面时设置状态栏是否沉浸
StatusBar.setBarStyle('light-content');
StatusBar.setTranslucent(true);
StatusBar.setBackgroundColor('transparent');
}
return () => {
if (isStatusBarImmersive) {
// 退出页面时重置状态栏
StatusBar.setBarStyle('dark-content');
StatusBar.setTranslucent(false);
StatusBar.setBackgroundColor('#ffffff');
}
};
}, [isStatusBarImmersive]),
);
return (
<SafeAreaView style={{flex: 1, position: 'relative'}}>
<Video
style={{
position: 'absolute',
width: videoWidth, // 设置视频播放组件宽度
height: videoHeight, // 设置视频播放组件高度
left: videoPosition.x, // 设置视频播放组件 x 坐标
top: videoPosition.y, // 设置视频播放组件 y 坐标
zIndex: 1,
}}
source={{uri: `assets://${video.source}`}}
resizeMode="contain"
controls={false}
onError={error => console.log('Video error:', error)}
repeat={true}
/>
<View
style={{
height: BOTTOM_TAB_HEIGHT,
width: '100%',
opacity: opacity,
backgroundColor: '#999',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
bottom: 0,
zIndex: 2,
}}>
<Text style={styles.myTabText}>底部Tab栏</Text>
</View>
</SafeAreaView>
);
};自适应旋转库AdaptiveRotation使用示例
import React, {useEffect, useMemo} from 'react';
import {View, StyleSheet, Dimensions, Button} from 'react-native';
import Video from 'react-native-video';
import {videoRotationList as videos} from '../../components/videos';
import {AdaptiveRotation} from '@hadss/react_native_adaptive_video';
import Fold from '@hadss/react_native_adaptive_layout/src';
const VideoSwiper = ({navigation}) => {
useEffect(() => {
AdaptiveRotation.getInstance().start(); // 进入播放界面时开启重力监听
return () => {
AdaptiveRotation.getInstance().stop(); // 退出页面停止重力监听
};
}, []);
return (
<View style={{flex: 1}}>
<Swiper loop={false} horizontal={false} showsPagination={false}>
{videoRotationList.map(video => (
<View key={video.id} style={styles.slide}>
<Video
source={{uri: `assets://${videos[id].source}`}}
style={styles.video}
resizeMode="contain"
muted={true}
repeat={true}
/>
<Button
title="进入全屏"
onPress={() => {
navigation.navigate('Details', {id: video.id});
// 调用单例方法进入全屏旋转:传入视频的宽高
AdaptiveRotation.getInstance().setOrientationFullScreen({
width: video.width,
height: video.height,
});
}}
/>
</View>
))}
</Swiper>
</View>
);
};
// 退出全屏时调用:传入视频的宽高
AdaptiveRotation.getInstance().setOrientationNotFullScreen({
width: video.width,
height: video.height,
});link
本库依赖以下三方库,请查看对应文档:
@react-native-oh-tpl/react-native-orientation-locker @react-native-ohos/react-native-sensors
接口说明
- 自适应沉浸
AdaptiveImmersion类: 自适应视频沉浸单例类
| 方法名称 | 参数 | 返回值类型 | 说明 | |-------------------------------|-----------------------------------------------------------------------------------|-------------------|------------------------------------| | AdaptiveImmersion.getInstance | / | AdaptiveImmersion | 静态方法,获取AdaptiveImmersion单例对象 | | getImmersionInfo | videoSize: Size,windowSize:Size, statusBarHeight: number, bottomTabHeight: number | ImmersionInfo | 根据视频宽高、显示窗口大小、状态栏高度和下Tab组件高度获取沉浸信息 |
ImmersionInfo接口: 沉浸状态下的视频页面信息
| 参数名称 | 类型 | 说明 | |------------------|------------------|-----------------------| | videoSize | Size | 视频播放组件的尺寸大小 | | windowSize | Size | 显示窗口大小 | | videoPosition | Position | 视频播放组件的位置(以窗口左上角作为锚点) | | immersionSetting | ImmersionSetting | 状态栏和下Tab栏的沉浸建议 |
ImmersionSetting接口: 状态栏和下tab栏的沉浸建议
| 参数名称 | 类型 | 说明 | |----------------------|---------|-----------| | isStatusBarImmersive | boolean | 状态栏是否沉浸 | | isBottomTabImmersive | boolean | 下tab栏是否沉浸 |
videoSize: Size 作为入参,表示视频的宽高
| 参数名称 | 类型 | 说明 | |----------------------|---------|---------| | width | number | 输入视频的宽度 | | height | number | 输入视频的高度 |
videoSize: Size 作为返回值,表示视频播放组件的宽高
| 参数名称 | 类型 | 说明 | |----------------------|---------|-----------| | width | number | 视频播放组件的宽度 | | height | number | 视频播放组件的高度 |
windowSize: Size 显示窗口大小
| 参数名称 | 类型 | 说明 | |----------------------|---------|-------| | width | number | 窗口的宽度 | | height | number | 窗口的高度 |
videoPosition: Position 表示视频播放组件的布局坐标
| 参数名称 | 类型 | 说明 | |----|---------|--------------| | x | number | 视频播放组件的x坐标(相对屏幕左上角) | y | number | 视频播放组件的y坐标(相对屏幕左上角)
- 自适应旋转
AdaptiveRotation类: 自适应视频旋转单例类
| 方法名称 | 参数 | 返回值类型 | 说明 |
|------------------------------|-----------------|------------------|-----------------------------|
| AdaptiveRotation.getInstance | / | AdaptiveRotation | 静态方法,获取AdaptiveRotation单例对象 |
| start | | | 开启自适应旋转重力监听 |
| stop | | | 结束自适应旋转重力监听 |
| setOrientationNotFullScreen | videoSize: Size | / | 非全屏、退出全屏时调用,根据视频宽高自动设置旋转属性 |
| setOrientationFullScreen | videoSize: Size | / | 进入全屏时调用,根据视频宽高自动设置旋转属性 |
| reset | | / | 重置到初始默认旋转方向 |
videoSize: Size 表示输入视频的宽高
| 参数名称 | 类型 | 说明 | |----------------------|---------|---------| | width | number | 输入视频的宽度 | | height | number | 输入视频的高度 |
自适应规则说明
- 沉浸规则
- 自适应沉浸式规则适用于视频滑动播放页面,为用户提供沉浸式视频播放效果。
具体规则如下:
沉浸效果图

沉浸式规则
| 序号 | 视频宽高比 z | 窗口宽高比 x | 沉浸规则描述 | |----|---------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 | 9:16 | 0 <= x < 9:20 | 窗口高度减去底部导航栏高度,状态栏高度后,等比例缩放视频至视频可视区域宽高比为9:17.8,并居中显示在剩余区域,左右超出窗口部分自适应裁剪 | | 2 | 9:16 | 9:20 <= x < 9:18 | 窗口高度减去底部导航栏高度后,1、剩余区域宽高比y >= 9:16,视频将窗口宽撑满,上下超出窗口部分自适应裁剪; 2、剩余区域宽高比y < 9:16,视频从窗口顶部将剩余区域高撑满,等比例缩放视频,最大缩放至可视区域宽高比为9:17.8,若剩余区域还有未被覆盖的区域,不做处理,左右超出窗口部分自适应裁剪 | | 3 | 9:16 | 9:18 <= x < 9:14.4 | 1、9:18 <= x < 9:16:视频将窗口高撑满,左右根据窗口大小决定是否裁剪;2、9:16 <= x < 9:14.4:视频将窗口宽撑满,上下根据窗口大小决定是否裁剪 | | 4 | 9:16 | 9:14.4 <= x < 9.9 | 视频将窗口高撑满,视频宽自适应等比例缩放 | | 5 | 9:16 | 9.9 <= x | 视频将窗口高撑满,视频宽自适应等比例缩放 | | 6 | 非9:16 | | 默认沉浸规则: 窗口高度减去底部导航栏高度和状态栏高度后, 1、剩余显示区域宽高比 y >= z,视频将剩余区域高撑满,视频宽自适应等比例缩放;2、剩余显示区域宽高比 y < z,视频将剩余区域宽撑满,视频高自适应等比例缩放 |
- 旋转规则
- 自适应旋转规则适用于视频滑动播放页面、视频全屏播放页面,可自动设置全屏、非全屏页面下的窗口旋转属性。
- 本框架接口在被调用时将会根据传入的视频宽高自动判定视频类型:横屏视频(宽>高)、竖屏视频(宽<=高)。
- 视频页面的旋转属性基于视频所在窗口的屏幕类型(根据断点区间判定)、视频类型(横向视频、竖向视频)、屏幕方向(重力判定)综合判定。
- 使用时可选择是否自动监听可折叠设备的形态变化,如选择监听,可自动适配可折叠设备在播放视频时设备形态改变后的旋转属性。
- 2in1、PC、TV、车机暂定不支持旋转。
具体规则如下:
断点区间图

依据断点区间判定屏幕类型
| 序号 | 横向断点 | 纵向断点 | 屏幕类型 | |----|-----------|-----------|------------------| | 1 | 0(XSmall) | 0(Small) | XSmall_Landscape | | 2 | 0(XSmall) | 1(Medium) | XSmall_Square | | 3 | 0(XSmall) | 2(Large) | XSmall_Portrait | | 4 | 1(Small) | 0(Small) | Small_Landscape | | 5 | 1(Small) | 1(Medium) | Small_Square | | 6 | 1(Small) | 2(Large) | Small_Portrait | | 7 | 2(Medium) | 0(Small) | Medium_Landscape | | 8 | 2(Medium) | 1(Medium) | Medium_Square | | 9 | 2(Medium) | 2(Large) | Medium_Portrait | | 10 | 3(Large) | 0(Small) | Large_Landscape | | 11 | 3(Large) | 1(Medium) | Large_Square | | 12 | 3(Large) | 2(Large) | Large_Portrait | | 13 | 4(XLarge) | 0(Small) | XLarge_Landscape | | 14 | 4(XLarge) | 1(Medium) | XLarge_Square | | 15 | 4(XLarge) | 2(Large) | XLarge_Portrait |
依据屏幕类型、视频类型、屏幕方向判定旋转属性
屏幕方向(0 - 竖屏, 1 - 反向横屏, 2 - 反向竖屏, 3 - 横屏)
| 序号 | 屏幕类型 | 视频类型 | 进入全屏/退出全屏 | 旋转属性(视频方向:属性) | 旋转属性描述 |
|----|------------------------------------------------------------------------------------------------------|------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 | Small_Portrait, Medium_Landscape | 横向视频 | 进入全屏(横屏) | 0:window.Orientation.USER_ROTATION_LANDSCAPE,1:window.Orientation.USER_ROTATION_LANDSCAPE_INVERTED,2:window.Orientation.USER_ROTATION_LANDSCAPE,3:window.Orientation.USER_ROTATION_LANDSCAPE | USER_ROTATION_LANDSCAPE: 调用时临时旋转到横屏,之后跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。USER_ROTATION_LANDSCAPE_INVERTED: 调用时临时旋转到反向横屏,之后跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。 |
| 2 | Small_Portrait, Medium_Landscape, Small_Square | 竖向视频 | 进入全屏(竖屏) | 0:window.Orientation.PORTRAIT,1:window.Orientation.PORTRAIT,2:window.Orientation.PORTRAIT,3:window.Orientation.PORTRAIT | PORTRAIT: 表示竖屏显示模式。 |
| 3 | Small_Portrait, Medium_Landscape | 横向视频 | 非全屏 | 0:window.Orientation.USER_ROTATION_PORTRAIT,1:window.Orientation.USER_ROTATION_PORTRAIT,2:window.Orientation.USER_ROTATION_PORTRAIT,3:window.Orientation.USER_ROTATION_PORTRAIT | USER_ROTATION_PORTRAIT:调用时临时旋转到竖屏,之后跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。 |
| 4 | Small_Portrait, Medium_Landscape, Small_Square | 竖向视频 | 非全屏 | 0:window.Orientation.PORTRAIT,1:window.Orientation.PORTRAIT,2:window.Orientation.PORTRAIT,3:window.Orientation.PORTRAIT | PORTRAIT: 表示竖屏显示模式。 |
| 5 | Small_Square | 横向视频 | 非全屏 | 0:window.Orientation.PORTRAIT,1:window.Orientation.PORTRAIT,2:window.Orientation.PORTRAIT,3:window.Orientation.PORTRAIT | PORTRAIT: 表示竖屏显示模式。 |
| 6 | Small_Square | 横向视频 | 全屏 | 0:window.Orientation.PORTRAIT,1:window.Orientation.PORTRAIT,2:window.Orientation.PORTRAIT,3:window.Orientation.PORTRAIT | PORTRAIT: 表示竖屏显示模式。 |
| 7 | Medium_Portrait, Medium_Square, Large_Portrait, Large_Landscape, Large_Square, XLarge_Landscape | 横向视频 | 进入全屏(横屏) | 0:window.Orientation.AUTO_ROTATION_UNSPECIFIED,1:window.Orientation.AUTO_ROTATION_UNSPECIFIED,2:window.Orientation.AUTO_ROTATION_UNSPECIFIED,3:window.Orientation.AUTO_ROTATION_UNSPECIFIED | AUTO_ROTATION_UNSPECIFIED :跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。 |
| 8 | Medium_Portrait, Medium_Square, Large_Portrait, Large_Landscape, Large_Square, XLarge_Landscape | 竖向视频 | 进入全屏(竖屏) | 0:window.Orientation.AUTO_ROTATION_UNSPECIFIED,1:window.Orientation.AUTO_ROTATION_UNSPECIFIED,2:window.Orientation.AUTO_ROTATION_UNSPECIFIED,3:window.Orientation.AUTO_ROTATION_UNSPECIFIED | AUTO_ROTATION_UNSPECIFIED :跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。 |
| 9 | Medium_Portrait, Medium_Square, Large_Portrait, Large_Landscape, Large_Square, XLarge_Landscape | 横向视频 | 非全屏 | 0:window.Orientation.AUTO_ROTATION_UNSPECIFIED,1:window.Orientation.AUTO_ROTATION_UNSPECIFIED,2:window.Orientation.AUTO_ROTATION_UNSPECIFIED,3:window.Orientation.AUTO_ROTATION_UNSPECIFIED | AUTO_ROTATION_UNSPECIFIED :跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。 |
| 10 | Medium_Portrait, Medium_Square, Large_Portrait, Large_Landscape, Large_Square, XLarge_Landscape | 竖向视频 | 非全屏 | 0:window.Orientation.AUTO_ROTATION_UNSPECIFIED,1:window.Orientation.AUTO_ROTATION_UNSPECIFIED,2:window.Orientation.AUTO_ROTATION_UNSPECIFIED,3:window.Orientation.AUTO_ROTATION_UNSPECIFIED | AUTO_ROTATION_UNSPECIFIED :跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定(如在某种设备,可以旋转到竖屏、横屏、反向横屏三个方向,无法旋转到反向竖屏)。 |
约束与限制
本示例仅支持标准系统上运行,支持设备:华为手机。 DevEco Studio版本:DevEco Studio NEXT Developer Beta5及以上。 SDK版本:API13及以上。
