@hadss/react_native_adaptive_layout
v1.0.0-rc.2
Published
RN framework-oriented multi-device layout scenario package
Readme
@hadss/react_native_adaptive_layout
介绍
这是一个旨在解决 React Native多设备适配问题的三方库,专为不同设备类型(包括折叠屏、平板、手机等)提供了便捷的支持。该库包含的接口和开箱即用的组件,使开发者能够轻松应对各种设备的布局适配需求。
目前该库提供的组件如下:
- 断点相关组件:使用ArkUI断点能力开发的断点管理组件,能够让开发者直接使用ArkUI断点能力。
- 折叠屏相关组件:基于ArkUI折叠屏相关接口开发的RN获取折叠屏信息的接口,包括折叠屏状态、是否是折叠屏、折叠屏避让区域信息及监听折叠屏变化等能力。
- 自适应显隐容器:对标ArkUI的自适应显隐布局开发的容器,使开发者能够轻松的完成自适应显隐布局能力的开发。
- 侧边栏组件:对标ArkUI的SideBarContainer组件开发的RN侧边栏组件,使开发者能够轻松的完成侧边栏相关布局能力的开发。
- 自适应分栏组件:参考ArkUI的Navigation组件开发的RN分栏组件,使开发者能够轻松的完成分栏及路由跳转能力的开发。
- 栅格组件:对标ArkUI的GridRow/GridCol开发的RN栅格组件,提供基础的栅格布局能力,使开发能够直接使用ArkUI栅格布局能力。
工程目录
.
├─harmony
│ ├─adaptive_layout.har // Turbo Modules接口har包
│ └─adaptive_layout
│ └─src
│ └─main
│ └─ets
│ ├─LayoutModule.ets // Turbo Modules接口ArkTS实现
│ ├─LayoutModulePackage.ets // LayoutModulesFactory
│ ├─LayoutModuleSpec.ts // Turbo Modules接口
│ └─core
│ └─FoldConfig.ts
├─src
│ ├─index.ts // RN模块导出
│ ├─component
│ │ ├─FoldSplitContainer.tsx // 折叠屏高阶组件
| | ├─FoldStack.tsx // 折叠屏高阶组件
| | ├─DisplayPriorityBox.tsx // 自适应隐藏容器
| | └─SideBarContainer.tsx // 侧边栏容器
│ ├─config
│ │ └─breakpoints.ts // 断点配置类
│ ├─hooks
│ │ ├─BreakpointManager.ts // 纵向断点管理类
│ │ └─useBreakpointValue.ts // 横向断点hook
│ └─turbo
│ └─NativeLayoutModule.ts // Turbo Modules接口安装与使用
进入到工程目录并输入以下命令:
npm
npm install @hadss/react_native_adaptive_layoutyarn
yarn add @hadss/react_native_adaptive_layout下面的代码展示了这个库的基本使用场景:
横向断点&&FoldSplitContainer使用示例
import { Fold, setBreakpoints, useBreakpointValue, ExpandedRegionLayoutOptions, ExtraRegionPosition, HoverModeRegionLayoutOptions, FoldSplitContainer } from "@hadss/react_native_adaptive_layout";
import { getBreakpoints } from "@hadss/react_native_adaptive_layout/src/config/breakpoints";
import React, { useState, useEffect } from "react";
import { View, Text, Button, StyleSheet } from "react-native";
const TestSample = () => {
const [foldCreaseRegion, setFoldCreaseRegion] = useState<number[]>([]);
const [foldStatus, setFoldStatus] = useState('');
const [breakpoints, setBreakpointsState] = useState({});
const [isDeviceFoldable, setIsDeviceFoldable] = useState(false);
useEffect(() => {
const checkFoldable = () => {
// 判断当前设备是否可折叠
const foldable = Fold.isFoldable();
setIsDeviceFoldable(foldable);
if (foldable) {
// 获取折痕区域
setFoldCreaseRegion(Fold?.getFoldCreaseRegion()==null ?[]:Fold?.getFoldCreaseRegion()[0]);
// 获取当前折叠屏状态
setFoldStatus(Fold.getFoldStatus());
}
};
checkFoldable();
// 监听折叠屏状态变化
Fold.addFoldListener((foldStatus) => {
console.log('折叠屏状态发生变化', foldStatus);
});
return () => {
// 销毁监听折叠屏状态变化
Fold.removeFoldListener();
};
}, []);
const handleGetBreakpoints = () => {
setBreakpointsState(getBreakpoints());
};
const handleSetBreakpoints = () => {
// 设置断点区间
setBreakpoints({
base: 320,
md: 768,
lg: 1024,
});
};
const handleGetFoldStatus = () => {
if (isDeviceFoldable) {
// 获取当前折叠屏状态
setFoldStatus(Fold.getFoldStatus());
}
};
const color = useBreakpointValue({
// 根据不同断点设置不同的颜色
base: 'red',
xs: 'blue',
sm: 'green',
md: 'yellow',
lg: 'purple',
xl: 'orange',
});
// FoldSplitContainer 主要区域
const primaryRender = () => (
<View style={{ flex: 1 }}>
<Text style={{ color }}>Responsive Color Text</Text>
<Text>Is Device Foldable: {isDeviceFoldable ? 'Yes' : 'No'}</Text>
{isDeviceFoldable && (
<>
<Text>Fold Crease Region: {JSON.stringify(foldCreaseRegion)}</Text>
<Button title="Get Fold Status" onPress={handleGetFoldStatus} />
{foldStatus && <Text>Fold Status: {foldStatus}</Text>}
</>
)}
<Button title="Get Breakpoints" onPress={handleGetBreakpoints} />
{Object.keys(breakpoints).length > 0 && (
<Text>Breakpoints: {JSON.stringify(breakpoints)}</Text>
)}
<Button title="Set Custom Breakpoints" onPress={handleSetBreakpoints} />
</View>
);
// FoldSplitContainer 次要区域
const secondRender = () => (
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text style={{ fontSize: 20 }}>secondRender</Text>
</View>
);
// FoldSplitContainer 扩展区域
const extraRender = () => (
<View style={{ flex: 1, backgroundColor: 'red' }}>
<Text style={{ fontSize: 20 }}>extraRender</Text>
</View>
);
// 折叠屏展开态配置
const expandedLayoutOptions: ExpandedRegionLayoutOptions = {
isExtraRegionPerpendicular: false,
extraRegionPosition: ExtraRegionPosition.BOTTOM,
};
// 折叠屏悬停态配置
const hoverModeRegionLayoutOptions: HoverModeRegionLayoutOptions = {
showExtraRegion: true,
};
return (
<View style={styles.container}>
// 折叠屏高阶组件
<FoldSplitContainer
primary={primaryRender()}
secondary={secondRender()}
extra={extraRender()}
expandedLayoutOptions={expandedLayoutOptions}
hoverModeLayoutOptions={hoverModeRegionLayoutOptions}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default TestSample;纵向断点BreakpointManager使用示例
import React, {useState, useEffect} from 'react';
import {
View,
Text,
useWindowDimensions,
StyleSheet,
FlatList,
} from 'react-native';
import {BreakpointManager} from '@hadss/react_native_adaptive_layout/src/hooks/BreakpointManager';
const BreakpointDemo = () => {
const {width: cwidth, height: cheight} = useWindowDimensions();
const [itemNum, setItemNum] = useState<number>(12);
const [itemColor, setItemColor] = useState<string>('red');
// 获取 BreakpointManager 的实例
const breakpointManager = BreakpointManager.getInstance();
// 获取当前宽度和高度的断点值
const currentWidthBp = breakpointManager.getCurrentWidthBreakpoint();
const currentHeightBp = breakpointManager.getCurrentHeightBreakpoint();
// 根据高度断点值计算每行的元素数量,并根据宽度断点值设置颜色
useEffect(() => {
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(
(width, height) => {
// 根据高度断点设置每行元素数量
switch (height) {
case 'sm':
setItemNum(12); // 一行展示 12 个元素
break;
case 'md':
setItemNum(6); // 两行展示,每行 6 个元素
break;
case 'lg':
setItemNum(4); // 三行展示,每行 4 个元素
break;
default:
setItemNum(12); // 默认一行展示 12 个元素
}
// 根据宽度断点设置颜色
switch (width) {
case 'sm':
setItemColor('red'); // 红色
break;
case 'md':
setItemColor('orange'); // 橙色
break;
case 'lg':
setItemColor('green'); // 绿色
break;
case 'xl':
setItemColor('blue'); // 蓝色
break;
default:
setItemColor('red'); // 默认红色
}
},
);
// 在组件卸载时移除订阅
return () => {
unsubscribe();
};
}, [breakpointManager]);
// 生成 12 个元素的列表数据
const data = Array.from({length: 12}, (_, index) => ({id: index + 1}));
// 渲染列表项
const renderItem = ({item}) => (
<View
style={[
styles.item,
{width: cwidth / itemNum - 10, backgroundColor: itemColor},
]}>
<Text style={styles.itemText}>{item.id}</Text>
</View>
);
return (
<View style={{padding: 20}}>
<Text>Current Width Breakpoint: {currentWidthBp}</Text>
<Text>Current Height Breakpoint: {currentHeightBp}</Text>
<Text>Current Width : {cwidth}</Text>
<Text>Current Height : {cheight}</Text>
<Text>Current Height / Width : {cheight / cwidth}</Text>
{/* 横向列表区域 */}
<View style={styles.listContainer}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
numColumns={itemNum} // 动态设置每行的元素数量
scrollEnabled={false} // 禁用滚动
contentContainerStyle={styles.listContent}
key={itemNum} // 强制重新渲染 FlatList
/>
</View>
</View>
);
};
// 样式定义
const styles = StyleSheet.create({
listContainer: {
marginTop: 20,
width: '100%', // 确保容器宽度占满屏幕
},
listContent: {
justifyContent: 'center', // 内容居中
},
item: {
height: 50, // 固定高度
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: '#ccc',
},
itemText: {
fontSize: 16,
},
});
export default BreakpointDemo;
自适应隐藏容器DisplayPriorityBox使用示例
import React, { useState } from 'react';
import { Text, View } from 'react-native';
import { DisplayPriorityBox } from '@hadss/react_native_adaptive_layout/src';
import Slider from '@react-native-community/slider';
const App = () => {
const [sliderHeight, setSliderHeight] = useState(350);
return (
<View style={{ alignItems: 'center', justifyContent: 'center', gap: 20, width: '100%', height: '100%' }}>
<DisplayPriorityBox
style={{
width: 300,
height: sliderHeight,
borderWidth: 1,
gap: 10,
alignSelf: 'center',
paddingTop: 10,
}}
>
{[{ priority: 3, color: 'lightblue', height: 60 },
{ priority: 5, color: 'lightcoral', height: 60 },
{ priority: 4, color: 'lightgreen', height: 60 },
{ priority: 2, color: 'lightgray', height: 30 },
{ priority: 6, color: 'red', height: 60 },
{ priority: 2, color: 'lightgray', height: 30 }].map(({ priority, color, height }, index) => (
<View
key={index}
displayPriority={priority}
style={{
backgroundColor: color,
width: 150,
height: height,
alignSelf: 'center',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text style={{ fontWeight: 'bold', color: 'white' }}>优先级: {priority}</Text>
</View>
))}
</DisplayPriorityBox>
<Slider
style={{ width: 200, height: 40, position: 'absolute', alignSelf: 'center', top: 50 }}
minimumValue={50}
maximumValue={600}
step={1}
value={sliderHeight}
onValueChange={(value) => setSliderHeight(value)}
minimumTrackTintColor="#000000"
maximumTrackTintColor="#000000"
thumbTintColor="#000000"
/>
</View>
);
};
export default App;
栅格使用示例
import React from "react";
import { View } from "react-native";
import { BreakpointsReference, GridCol, GridRow, GridRowDirection } from '@hadss/react_native_adaptive_layout/src'
const App = () => {
return (
<View style={{ width: '100%', height: '100%', paddingTop: 38 }}>
<GridRow
style={{ backgroundColor: 'grey', alignItems: 'flex-end' }}
columns={12}
gutter={10}
breakpoints={{
value: [400, 600, 840],
reference: BreakpointsReference.WindowSize,
}}
direction={GridRowDirection.Row}
onBreakpointChange={(bp) => console.log('Current BP:', bp)}
>
<GridCol span={6} >
<View style={{ backgroundColor: 'red', height: 100 }} />
</GridCol>
<GridCol span={6} >
<View style={{ backgroundColor: 'blue', height: 200 }} />
</GridCol>
</GridRow>
</View>
);
};
export default App;侧边栏使用示例
import React from 'react';
import {View, Text, Button, StyleSheet, Image} from 'react-native';
import {SideBarContainer, SideBarContainerType} from '@hadss/react_native_adaptive_layout';
const SideBarSample = () => {
return (
<SideBarContainer
sideBarWidth={360}
sideBarContainerType={SideBarContainerType.Embed}
onChange={newVisibility => {
console.log('onChange1: ', newVisibility);
}}
minSideBarWidth={240}
maxSideBarWidth={480}
minContentWidth={600}
showSideBar={true}
showControlButton={true}
sideBarPosition={'Start'}
autoHide={true}
controlButton={{
left: 10,
top: 10,
width: 50,
height: 50,
icon: {
shown: require('../asserts/pic1.png'),
hidden: require('../asserts/pic2.png'),
switching: require('../asserts/pic3.png'),
},
}}
divider={{
strokeWidth: 10,
color: 'blue',
startMargin: 10,
endMargin: 10,
}}>
{/* 侧边栏 */}
<View style={styles.sideBarContent}>
<Button
title={'Button 1'}
onPress={() => console.log('Button 1 Pressed')}
/>
<Button
title={'Button 2'}
onPress={() => console.log('Button 2 Pressed')}
/>
<Button
title={'Button 3'}
onPress={() => console.log('Button 3 Pressed')}
/>
</View>
<View style={styles.content}>
<View style={styles.view1} />
<Image source={require('../asserts/pic3.png')} style={styles.image} />
<Text numberOfLines={1}>
实时数据展示:22222222222222222222222222
</Text>
</View>
</SideBarContainer>
);
};
const styles = StyleSheet.create({
sideBarContent: {
justifyContent: 'space-evenly',
alignItems: 'center',
backgroundColor: '#f1f3f5',
},
content: {
flex: 1,
justifyContent: 'center',
alignItems: 'start',
borderWidth: 1,
},
image: {
width: 600,
height: 300,
resizeMode: 'contain',
},
view1: {
width: 240,
height: 10,
borderWidth: 1,
},
});
export default SideBarSample;
FoldSatck使用示例
import React from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
import { FolderStack } from '@hadss/react_native_adaptive_layout';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgb(39, 135, 217)'
},
videoContainer: {
width: '100%',
height: '100%',
justifyContent: 'center',
backgroundColor: 'rgb(100, 135, 217)'
},
videoText: {
fontSize: 25,
color: 'white',
textAlign: 'center'
},
controlBar: {
height: '100%',
width: '100%',
},
controlText: {
fontSize: 25,
textAlign: 'center',
width: '100%',
height: 50
}
});
const FolderStackDemo = () => {
return (
<View style={[styles.videoContainer]}>
<FolderStack
upperItems={["upperitemsId"]}
enableAnimation={true}
autoHalfFold={true}
alignContent='End'
onFolderStateChange={(foldStatus) => {
console.log(`onFolderStateChange params is ${JSON.stringify(foldStatus)}`)
}
}
onHoverStatusChange={(HoverStatus) => {
console.log(`onHoverStatusChange params is ${JSON.stringify(HoverStatus)}`)
}
}
>
{/* 上半屏视频区域 */}
<View style={[styles.videoContainer, { backgroundColor: 'rgb(0, 74, 175)' }]} id="upperitemsId">
<Text style={styles.videoText}>video zone</Text>
</View>
{/* 下半屏操作区域 */}
<View style={[styles.controlBar, { justifyContent: 'flex-start' }]} id="2">
<Text style={[styles.controlText, { backgroundColor: 'rgb(213, 213, 213)' }]}>video title</Text>
</View>
<View style={[styles.controlBar, { justifyContent: 'flex-end', zIndex: 5 }]} id="3">
<Text style={[styles.controlText, { backgroundColor: 'rgb(213, 213, 213)' }]}>video bar</Text>
</View>
</FolderStack>
</View>
);
};
export default FolderStackDemo;
分栏使用示例
import React from 'react';
import {View, Text, Button, StyleSheet} from 'react-native';
import {
NavigationSplitContainer,
NavigationMode,
NavBarPosition,
} from '@hadss/react_native_adaptive_layout';
if (__DEV__) {
console.error = () => {};
}
const HomeScreen = props => (
<View style={styles.container}>
<Text style={styles.text}>Home Screen</Text>
<Button
title={'Button 1'}
onPress={() => {
props.navigateTo(2);
console.log('Button 1 Pressed');
}}
/>
<Button
title={'Button 2'}
onPress={() => {
props.onBack();
console.log('Button 2 Pressed');
}}
/>
</View>
);
const ProfileScreen = () => (
<View style={styles.container}>
<Text style={styles.text}>Profile Screen</Text>
</View>
);
const SettingsScreen = () => (
<View style={styles.container}>
<Text style={styles.text}>Settings Screen</Text>
</View>
);
const styles = StyleSheet.create({
container: {
marginTop: 250,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f0f0f0',
},
text: {
fontSize: 24,
marginBottom: 20,
},
});
// 主组件
const NavigationSplitDemo = () => {
return (
<NavigationSplitContainer
mode={NavigationMode.Auto}
navBarPosition={NavBarPosition.Start}
navBarWidth={400}
navBarWidthRange={[240, 400]}
minContentWidth={200}
onNavBarStateChange={newState => {
console.log('onNavBarStateChange: ', newState);
}}
onNavigationModeChange={newMode => {
console.log('onNavigationModeChange: ', newMode);
}}
navBarItemStyle={{
paddingVertical: 30,
paddingHorizontal: 30,
marginBottom: 5,
backgroundColor: 'red',
borderRadius: 5,
activeBackgroundColor: 'yellow',
}}>
<NavigationSplitContainer.Screen name="Home" component={HomeScreen} />
<NavigationSplitContainer.Screen
name="Profile"
component={ProfileScreen}
/>
<NavigationSplitContainer.Screen
name="Settings"
component={SettingsScreen}
/>
{/* <Text>-----------FIRST</Text>
<Text>---------2TH</Text>
<Text>3RD</Text> */}
</NavigationSplitContainer>
);
};
export default NavigationSplitDemo;Link
本库依赖以下三方库,请查看对应文档: @react-native-oh-tpl/react-native-orientation @react-native-oh-tpl/react-native-reanimated
目前OpenHarmony暂不支持AutoLink,所以Link步骤需要手动配置。
首先需要使用DevEco Studio打开项目里的OpenHarmony工程,在工程根目录的oh-package.json5添加overrides字段:
{
...
"overrides": {
"@rnoh/react-native-openharmony" : "./react_native_openharmony"
}
}引入原生端代码
目前有两种方法:
通过har包引入(在IDE完善相关功能后该方法会被遗弃,目前首选此方法)。
说明: har包位于三方库安装路径的
harmony文件夹下。a. 打开
entry/oh-package.json5,添加以下依赖:"dependencies": { "@rnoh/react-native-openharmony": "file:../react_native_openharmony", "@hadss/react_native_adaptive_layout": "file:../../node_modules/@hadss/react_native_adaptive_layout/harmony/adaptive_layout.har", }b. 配置CMakeLists和引入RNOHGeneratedPackage:
打开
entry/src/main/cpp/CMakeLists.txt,添加:project(rnapp) cmake_minimum_required(VERSION 3.4.1) set(CMAKE_SKIP_BUILD_RPATH TRUE) set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules") set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp") set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated") set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments") set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie") add_compile_definitions(WITH_HITRACE_SYSTRACE) set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use + file(GLOB GENERATED_CPP_FILES "./generated/*.cpp") add_subdirectory("${RNOH_CPP_DIR}" ./rn) add_library(rnoh_app SHARED + ${GENERATED_CPP_FILES} "./PackageProvider.cpp" "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp" ) target_link_libraries(rnoh_app PUBLIC rnoh)c. 打开
entry/src/main/cpp/PackageProvider.cpp,添加:#include "RNOH/PackageProvider.h" + #include "generated/RNOHGeneratedPackage.h" using namespace rnoh; std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) { return { + std::make_shared<RNOHGeneratedPackage>(ctx) }; }d. 在ArkTs侧引入LayoutModulePackage:
打开
entry/src/main/ets/RNPackagesFactory.ts,添加:... + import { LayoutModulePackage } from '@hadss/react_native_adaptive_layout/ts'; export function createRNPackages(ctx: RNPackageContext): RNPackage[] { return [ + new LayoutModulePackage(ctx), ]; }e. 运行:
点击右上角的
sync按钮或者在终端执行:
cd entry ohpm install然后编译、运行即可。
说明 若项目启动时报错:can not find record '&@rnoh/react-native-openharmony/generated/ts&X.X.X'。需在entry\oh_modules@rnoh\react-native-openharmony\ts.ts文件中添加export * from './generated/ts',并删除.cxx文件夹、build文件夹,然后执行sync操作同步代码。
直接链接源码。
如需使用直接链接源码,请参考直接链接源码说明。
API
说明: "Platform"列表示支持的平台,All表示支持所有平台。
自适应隐藏容器
DisplayPriorityBox | Name | Description | Type | Platform | | ------------------ | ------------------------------------------------------------ | --------- | -------- | | DisplayPriorityBox | 自适应隐藏容器,容器组件内的子组件,按照其预设的displayPriority优先级,随容器组件尺寸变化显示或隐藏,displayPriority数值越大,优先级越高。若容器空间不足,隐藏低优先级子组件,其中相同优先级的子组件同时显示或隐藏。 | component | All | | displayPriority | 设置组件优先级,仅在DisplayPriorityBox容器组件中生效。小数点后的数字不作优先级区分,即区间为[x, x + 1)内的数字视为相同优先级。例如:1.0与1.9为同一优先级。当displayPriority < 1或为非number类型时,默认为1 | any | All |
约束:
- DisplayPriorityBox中子组件不支持position: 'absolute'布局。
- DisplayPriorityBox容器仅在单行/列生效。
- DisplayPriorityBox嵌套DisplayPriorityBox场景不适用。
栅格
GridRow:栅格容器组件,仅可以和栅格子组件(GridCol)在栅格布局场景中使用,属性如下:
| Name | Description | Type | Platform | | ------------------ | ------------------------------------------------------------ | ----------------------------- | -------- | | columns | 设置布局列数。默认值:12 | number | GridRowColumnOption | All | | gutter | 栅格布局间距。默认值:0 | Length | GutterOption | All | | breakpoints | 设置断点值的断点数列以及基于窗口或容器尺寸的相应参照。默认值:{ value: [320, 600, 840], reference: BreakpointsReference.WindowSize } | BreakPoints | All | | direction | 栅格布局排列方向。默认值:GridRowDirection.Row | GridRowDirection | All | | onBreakpointChange | 断点发生变化时触发回调。 | (breakpoint: string) => void | All |
GridCol:栅格子组件,必须作为栅格容器组件(GridCol)的子组件使用,属性如下:
| Name | Description | Type | Platform | | ------ | ------------------------------------------------------------ | ----------------------------- | -------- | | span | 设置占用列数。span为0,意味着该元素不参与布局计算,即不会被渲染。默认值:1 | number | GridColColumnOption | All | | offset | 栅格布局间距。默认值:0 | number | GridColColumnOption | All | | order | 元素的序号,根据栅格子组件的序号,从小到大对栅格子组件做排序。默认值:0 | number | GridColColumnOption | All |
GridRowColumnOption
| Name | Description | Type | Platform | | :--- | :------------------------------------------------ | :----- | :------- | | xs | 在栅格大小为xs的设备上,栅格容器组件的栅格列数。 | number | All | | sm | 在栅格大小为sm的设备上,栅格容器组件的栅格列数。 | number | All | | md | 在栅格大小为md的设备上,栅格容器组件的栅格列数。 | number | All | | lg | 在栅格大小为lg的设备上,栅格容器组件的栅格列数。 | number | All | | xl | 在栅格大小为xl的设备上,栅格容器组件的栅格列数。 | number | All | | xxl | 在栅格大小为xxl的设备上,栅格容器组件的栅格列数。 | number | All |
Length
| Name | Description | Type | Platform | | :----- | :--------------------------- | :--------------- | :------- | | Length | 长度类型,用于描述尺寸单位。 | string | number | All |
GutterOption
| Name | Description | Type | Platform | | :--- | :----------------------- | :------------------------- | :------- | | x | 栅格子组件水平方向间距。 | Length| GridRowSizeOption | All | | y | 栅格子组件竖直方向间距。 | Length| GridRowSizeOption | All |
GridRowSizeOption
| Name | Description | Type | Platform | | :--- | :--------------------------------------- | :----- | :------- | | xs | 在最小宽度类型设备上,栅格子组件的间距。 | Length | All | | sm | 在小宽度类型设备上,栅格子组件的间距。 | Length | All | | md | 在中等宽度类型设备上,栅格子组件的间距。 | Length | All | | lg | 在大宽度类型设备上,栅格子组件的间距。 | Length | All | | xl | 在特大宽度类型设备上,栅格子组件的间距。 | Length | All | | xxl | 在超大宽度类型设备上,栅格子组件的间距。 | Length | All |
BreakPoints
| Name | Description | Type | Platform | | :-------- | :----------------------------------------------------------- | :------------------- | :------- | | value | 设置断点位置的单调递增数组。默认值:[320, 600, 840] | number[] | All | | reference | 断点切换参照物。默认值:BreakpointsReference.WindowSize | BreakpointsReference | All |
GridRowDirection
| Name | Description | Platform | | :--------- | :--------------------------- | :------- | | Row | 栅格元素按照行方向排列。 | All | | RowReverse | 栅格元素按照逆序行方向排列。 | All |
BreakpointsReference
| Name | Description | Platform | | :------------ | :------------- | :------- | | WindowSize | 以窗口为参照。 | All | | ComponentSize | 以容器为参照。 | All |
GridColColumnOption
| Name | Description | Type | Platform | | :--- | :------------------------------------------------ | :----- | :------- | | xs | 在栅格大小为xs的设备上,栅格容器组件的栅格列数。 | number | All | | sm | 在栅格大小为sm的设备上,栅格容器组件的栅格列数。 | number | All | | md | 在栅格大小为md的设备上,栅格容器组件的栅格列数。 | number | All | | lg | 在栅格大小为lg的设备上,栅格容器组件的栅格列数。 | number | All | | xl | 在栅格大小为xl的设备上,栅格容器组件的栅格列数。 | number | All | | xxl | 在栅格大小为xxl的设备上,栅格容器组件的栅格列数。 | number | All |
侧边栏组件
SideBarContainer | 名称 | 类型 | 是否必填 | 说明 | | -------------------- | ------------------------------------------------------------ | ---- | :----------------------------------------------------------- | | type | SideBarContainerType | 是 | 设置侧边栏的显示类型 | | showSideBar | boolean | 否 | 设置是否显示侧边栏 | | controlButton | ButtonStyle | 否 | 设置侧边栏控制按钮的属性 | | showControlButton | boolean | 否 | 设置是否显示控制按钮 | | sideBarWidth | number|Length | 否 | 设置侧边栏的宽度。设置为小于0的值时按默认值显示。受最小宽度和最大宽度限制,不在限制区域内取最近的点。 | | minSideBarWidth | number|Length | 否 | 设置侧边栏最小宽度。设置为小于0的值时按默认值显示。值不能超过侧边栏容器本身宽度,超过使用侧边栏容器本身宽度。 | | maxSideBarWidth | number|Length | 否 | 设置侧边栏最大宽度。设置为小于0的值时按默认值显示。值不能超过侧边栏容器本身宽度,超过使用侧边栏容器本身宽度。 | | autoHide | boolean | 否 | 设置当侧边栏拖拽到小于最小宽度后,是否自动隐藏。受minSideBarWidth属性方法影响,minSideBarWidth属性方法未设置值使用默认值。拖拽过程中判断是否要自动隐藏。小于最小宽度时需要阻尼效果触发隐藏(越界一段距离)。 | | sideBarPosition | SideBarPosition | 否 | 设置侧边栏显示位置。 | | divider | DividerStyle | 否 | 设置分割线的样式。 | | minContentWidth | number|Length | 否 | 设置SideBarContainer组件内容区可显示的最小宽度。 | | onChange | function | 否 | 当侧边栏的状态在显示和隐藏之间切换时触发回调。 |
SideBarContainerType
| 名称 | 描述 | | ------- | ------------------------------------------------------------ | | Embed | 侧边栏嵌入到组件内,和内容区并列显示。组件尺寸小于minContentWidth + minSideBarWidth,并且未设置showSideBar时,侧边栏自动隐藏。未设置minSideBarWidth或者minContentWidth采用未设置接口的默认值进行计算。组件在自动隐藏后,如果通过点击控制按钮唤出侧边栏,则侧边栏悬浮在内容区上显示。 | | Overlay | 侧边栏浮在内容区上面。 | | AUTO | 组件尺寸大于等于minSideBarWidth+minContentWidth时,采用Embed模式显示。组件尺寸小于minSideBarWidth+minContentWidth时,采用Overlay模式显示。未设置minSideBarWidth或minContentWidth时,会使用未设置接口的默认值进行计算,若计算的值小于600,则使用600做为模式切换的断点值。 |
ButtonStyle
| 名称 | 类型 | 是否必填 | 说明 | | -------- | ------------------------------------------------------------ | -------- | ------------------------------------------------------------ | | left | number | 否 | 设置侧边栏控制按钮距离容器左界限的间距。 默认值:16 | | top | number | 否 | 设置侧边栏控制按钮距离容器上界限的间距。 默认值:48 | | width | number | 否 | 设置侧边栏控制按钮的宽度。 默认值:24 | | height | number | 否 | 设置侧边栏控制按钮的高度。 默认值:24 | | icons | { shown: string | TexImageSource ; hidden: string | TexImageSource; switching?: string | TexImageSource } | 否 | 设置侧边栏控制按钮的图标: - shown: 设置侧边栏显示时控制按钮的图标。 说明: 资源获取错误时,使用默认图标。 - hidden: 设置侧边栏隐藏时控制按钮的图标。 - switching:设置侧边栏显示和隐藏状态切换时控制按钮的图标。 |
SideBarPosition | 名称 | 描述 | | -------- | -------------------- | | Start | 侧边栏位于容器左侧。 | | End | 侧边栏位于容器右侧。 |
DividerStyle
| 名称 | 类型 | 是否必填 | 说明 | | ----------- | ------------------------------------------------------------ | -------- | ------------------------------------- | | strokeWidth | Length | 是 | 分割线的线宽。 默认值:1 | | color | string | 否 | 分割线的颜色。 默认值:#000000,3% | | startMargin | Length | 否 | 分割线与侧边栏顶端的距离。 默认值:0 | | endMargin | Length | 否 | 分割线与侧边栏底端的距离。 默认值:0 |
断点(横向断点 )
| Name | Description | Type | Platform | | ------------------ | ------------------------------------------------------------ | -------- | -------- | | setBreakpoints | 设置自定义的横向响应式布局断点值。 | function | All | | setHeightBreakpoints | 设置自定义的纵向响应式布局断点值。 | function | All | | useBreakpointValue | 允许开发者为特定的横向断点定义不同的值,并动态返回与当前屏幕宽度相对应的值。 | hook | All | | useHeightBreakpointValue | 允许开发者为特定的纵向断点定义不同的值,并动态返回与当前屏幕宽度相对应的值。 | hook | All |
断点(BreakpointManager横向纵向断点)
| Name | Description | Type | Platform | | ------------------ | ------------------------------------------------------------ | -------- | -------- | | getInstance | 获取 BreakpointManager 的单例 | function | All | | getCurrentWidthBreakpoint | 获取当前的横向断点 | function | All | | getCurrentHeightBreakpoint | 获取当前的纵向断点 | function | All | | subscribeToBreakpoint | 订阅断点变化 | function | All | | destroy | 注销监听 | function | All |
自适应分栏
NavigationSplitContainer
| 名称 | 类型 | 是否必填 | 说明 | | ---------------------- | ------------------------------------------------------------ | -------- | ------------------------------------------------------------ | | navBarWidth | Length | 否 | 设置导航栏宽度。仅在Navigation组件分栏时生效。 | | navBarPosition | NavBarPosition | 否 | 导航栏位置。默认值:NavBarPosition.Start。 | | mode | NavigationMode | 否 | 设置导航栏的显示模式,支持单栏(Stack)、分栏(Split)和自适应(Auto)。 | | navBarWidthRange | Length[] | 否 | 设置导航栏最小和最大宽度(双栏模式下生效)默认值:最小默认值 240,最大默认值为组件宽度的40% ,且不大于 432,如果只设置一个值,则未设置的值按照默认值计算。 | | minContentWidth | Length | 否 | 内容区最小宽度。默认值为360。 | | navBarStyle | ViewStyle | 否 | 导航栏样式,可以覆盖导航栏默认样式。 | | navBarItemStyle | ViewStyle | 否 | 导航栏里各个子项目的样式。仅NavigationSplitContainer.Screen子组件存在时生效。 | | contentStyle | ViewStyle | 否 | 内容区样式,可以覆盖内容区默认样式。 | | onNavBarStateChange | onNavBarStateChange(callback: (isVisible: boolean) => void) | 否 | 导航栏显示状态切换时触发该回调。isVisible为true时表示显示,为false时表示隐藏。 | | onNavigationModeChange | onNavigationModeChange(callback: (mode: NavigationMode) => void) | 否 | 当Navigation首次显示或者单双栏状态发生变化时触发该回调。NavigationMode.Split:当前Navigation显示为双栏;NavigationMode.Stack:当前Navigation显示为单栏。 |
子组件NavigationSplitContainer.Screen
| 名称 | 类型 | 是否必填 | 说明 | | ---------- | ---------------------------------- | -------- | ------------------------------------------------------------ | | name | string | 是 | 导航路由名称 | | component | object | 是 | 导航路由页面组件 | | onBack | function:() => void | 否 | 提供内容区返回到导航栏的方法,仅在Stack模式生效。 | | navigateTo | function: (index: number) => void | 否 | 提供内容区相互跳转的路由设置,index为目标页面的序号,序号从0开始。 |
NavBarPosition
| 名称 | 说明 | | :---- | :------------------------------- | | Start | 双栏显示时,主列在主轴方向首部。 | | End | 双栏显示时,主列在主轴方向尾部。 |
NavigationMode
| 名称 | 说明 | | :---- | :----------------------------------------------------------- | | Stack | 导航栏与内容区独立显示,相当于两个页面。 | | Split | 导航栏与内容区分两栏显示。以下navBarWidthRange的值用[minNavBarWidth,maxNavBarWidth]表示1.当navBarWidth属性的值,在navBarWidthRange属性的值范围以外时,navBarWidth按如下规则显示:navBarWidth < minNavBarWidth时,navBarWidth修正为minNavBarWidth;navBarWidth > maxNavBarWidth,且组件宽度 - minContentWidth - 分割线宽度(1) > maxNavBarWidth时,navBarWidth修正为maxNavBarWidth;navBarWidth > maxNavBarWidth,且组件宽度 - minContentWidth - 分割线宽度(1) < minNavBarWidth时,navBarWidth修正为minNavBarWidth;navBarWidth > maxNavBarWidth,且组件宽度 - minContentWidth - 分割线宽度(1)在navBarWidthRange范围内,navBarWidth修正为组件宽度 - 分割线宽度(1) - minContentWidth。2.当navBarWidth属性的值,在navBarWidthRange属性的值范围以内时,navBarWidth按如下规则显示:minNavBarWidth + minContentWidth + 分割线宽度(1) >= 组件宽度时,navBarWidth修正为minNavBarWidth;minNavBarWidth + minContentWidth + 分割线宽度(1) < 组件宽度,且navBarWidth + minContentWidth + 分割线宽度(1) >= 组件宽度时,navBarWidth修正为组件宽度 - 分割线宽度(1) - minContentWidth;minNavBarWidth + minContentWidth + 分割线宽度(1) < 组件宽度,且navBarWidth + minContentWidth + 分割线宽度(1) < 组件宽度时,navBarWidth为设置的值。3.缩小组件尺寸时,先缩小内容区的尺寸至minContentWidth,然后再缩小导航栏的尺寸至minNavBarWidth。若继续缩小,先缩小内容区,内容区消失后再缩小导航栏。4.设置导航栏为固定尺寸时,若持续缩小组件尺寸,导航栏最后压缩显示。5.若只设置了navBarWidth属性,则导航栏宽度为navBarWidth,且分割线不可拖动。 | | Auto | API version 9之前:窗口宽度>=520时,采用Split模式显示;窗口宽度<520时,采用Stack模式显示。API version 10及以上:窗口宽度>=600时,采用Split模式显示;窗口宽度<600时,采用Stack模式显示,600等于minNavBarWidth(240) + minContentWidth (360)。 |
折叠屏适配
折叠屏接口
| Name | Description | Type | Platform |
| ------------------- | ------------------------------------------------------------ | -------- | --------- |
| getFoldCreaseRegion | 获取可折叠设备屏幕的折痕区域。 | function | OpenHarmony |
| getFoldStatus | 获取当前可折叠设备的状态(例如:展开、半折叠或折叠)。 | function | OpenHarmony |
| isFoldable | 判断设备是否可折叠。如果为 true,设备是可折叠的;否则是不可折叠设备。 | function | OpenHarmony |
| addFoldListener | 监听折叠设备的折叠状态变化。 | function | OpenHarmony |
| removeFoldListener | 移除已添加的折叠状态变化监听。 | function | OpenHarmony |
FoldSplitContainer组件
| Name | Description | Type | Platform | | :--------------------- | :--------------------------------------------- | :--------------------------- | :-------- | | primary | 主要区域回调函数。 | function | OpenHarmony | | secondary | 次要区域回调函数。 | function | OpenHarmony | | extra | 扩展区域回调函数,不传入的情况,没有对应区域。 | function | OpenHarmony | | expandedLayoutOptions | 展开态布局信息。 | ExpandedRegionLayoutOptions | OpenHarmony | | hoverModeLayoutOptions | 悬停态布局信息。 | HoverModeRegionLayoutOptions | OpenHarmony | | foldedLayoutOptions | 折叠态布局信息。 | FoldedRegionLayoutOptions | OpenHarmony | | onHoverStatusChange | 折叠屏进入或退出悬停模式时触发的回调函数。 | onHoverStatusChangeHandler | OpenHarmony |
FoldStack组件
| Name | Description | Type | Platform | | :--------------------- | :--------------------------------------------- | :--------------------------- | :-------- | | upperItems | 主要区域回调函数。 | string[] | OpenHarmony | | enableAnimation | 动画是否开启。 | boolean | OpenHarmony | | alignContent | 布局形式。 | Alignment | OpenHarmony | | autoHalfFold | 自动旋转开关。 | boolean | OpenHarmony | | onFolderStateChange | 折叠屏状态变化触发的回调函数。 | (event: { foldStatus: FoldStatus }) => void | OpenHarmony | | onHoverStatusChange | 折叠屏进入或退出悬停模式时触发的回调函数。 | onHoverStatusChangeHandler | OpenHarmony |
ExpandedRegionLayoutOptions
| Name | Description | Type | Platform | | :------------------------- | :----------------------------------------------------------- | :------------------ | --------- | | isExtraRegionPerpendicular | 扩展区域是否从上到下贯穿整个组件,当且仅当extra有效时此字段才生效。默认值:true。 | boolean | OpenHarmony | | verticalSplitRatio | 主要区域与次要区域之间的高度比例。默认值:PresetSplitRatio.LAYOUT_1V1。 | number | OpenHarmony | | horizontalSplitRatio | 主要区域与扩展区域之间的宽度比例,当且仅当extra有效时此字段才生效。默认值:PresetSplitRatio.LAYOUT_3V2。 | number | OpenHarmony | | extraRegionPosition | 扩展区域的位置信息,当且仅当isExtraRegionPerpendicular = false有效时此字段才生效。默认值:ExtraRegionPosition.top。 | ExtraRegionPosition | OpenHarmony |
HoverModeRegionLayoutOptions
| Name | Description | Type | Platform | | :------------------- | :----------------------------------------------------------- | :------------------ | :-------- | | showExtraRegion | 可折叠屏幕在半折叠状态下是否显示扩展区域。默认值:false。 | boolean | OpenHarmony | | horizontalSplitRatio | 主要区域与扩展区域之间的宽度比例,当且仅当extra有效时此字段才生效。默认值:PresetSplitRatio.LAYOUT_3V2。 | number | OpenHarmony | | extraRegionPosition | 扩展区域的位置信息,当且仅当showExtraRegion时此字段才生效。默认值:ExtraRegionPosition.top。 | ExtraRegionPosition | OpenHarmony |
FoldedRegionLayoutOptions
| Name | Description | Type | Platform | | :----------------- | :----------------------------------------------------------- | :----- | :-------- | | verticalSplitRatio | 主要区域与次要区域之间的高度比例。默认值:PresetSplitRatio.LAYOUT_1V1。 | number | OpenHarmony |
onHoverStatusChangeHandler
| Name | Description | Type | Platform | | :------- | :----------------------------------------- | :-------------------------------- | :-------- | | callback | 折叠屏进入或退出悬停模式时触发的回调函数。 | (status: HoverModeStatus) => void | OpenHarmony |
HoverModeStatus
| Name | Description | Type | Platform | | :---------- | :---------------------- | :--------- | :-------- | | foldStatus | 设备的折叠状态。 | FoldStatus | OpenHarmony | | isHoverMode | app当前是否处于悬停态。 | boolean | OpenHarmony | | appRotation | AppRotation。 | AppRotation | OpenHarmony |
AppRotation
| Name | Description | Value | | :----- | :----------------------- | :---- | | ROTATION_0 | 应用方向为0度。 | 0 | | ROTATION_90 | 应用方向为90度。 | 1 | | ROTATION_180 | 应用方向为180度。 | 2 | | ROTATION_270 | 应用方向为270度。 | 3 |
ExtraRegionPosition
| Name | Description | Value | | :----- | :----------------------- | :---- | | top | 扩展区域在组件上半区域。 | 1 | | bottom | 扩展区域在组件下半区域。 | 2 |
PresetSplitRatio
| Name | Description | Value | | :--------- | :---------- | :---- | | LAYOUT_1V1 | 1:1比例。 | 1/1 | | LAYOUT_3V2 | 3:2比例。 | 3/2 | | LAYOUT_2V3 | 2:3比例。 | 2/3 |
约束与限制
本示例仅支持标准系统上运行,支持设备:华为手机。 DevEco Studio版本:DevEco Studio NEXT Developer Beta5及以上。 SDK版本:API13及以上。
