npm package: @hadss/react_native_adaptive_layout
Description: RN framework-oriented multi-device layout scenario package
Latest version: 1.0.0-rc.2

# @hadss/react_native_adaptive_layout

## 介绍

这是一个旨在解决 React Native多设备适配问题的三方库，专为不同设备类型（包括折叠屏、平板、手机等）提供了便捷的支持。该库包含的接口和开箱即用的组件，使开发者能够轻松应对各种设备的布局适配需求。

目前该库提供的组件如下：

1. 断点相关组件：使用ArkUI断点能力开发的断点管理组件，能够让开发者直接使用ArkUI断点能力。
2. 折叠屏相关组件：基于ArkUI折叠屏相关接口开发的RN获取折叠屏信息的接口，包括折叠屏状态、是否是折叠屏、折叠屏避让区域信息及监听折叠屏变化等能力。
3. 自适应显隐容器：对标ArkUI的自适应显隐布局开发的容器，使开发者能够轻松的完成自适应显隐布局能力的开发。
4. 侧边栏组件：对标ArkUI的SideBarContainer组件开发的RN侧边栏组件，使开发者能够轻松的完成侧边栏相关布局能力的开发。
5. 自适应分栏组件：参考ArkUI的Navigation组件开发的RN分栏组件，使开发者能够轻松的完成分栏及路由跳转能力的开发。
6. 栅格组件：对标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接口
```


## 安装与使用

进入到工程目录并输入以下命令：

<!-- tabs:start -->

**npm**

```bash
npm install @hadss/react_native_adaptive_layout
```

**yarn**

```bash
yarn add @hadss/react_native_adaptive_layout
```

<!-- tabs:end -->

下面的代码展示了这个库的基本使用场景：

**横向断点&&FoldSplitContainer使用示例** 
```jsx
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使用示例**
```jsx
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使用示例**
```jsx
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;

```

**栅格使用示例**
```jsx
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;
```

**侧边栏使用示例**
```jsx
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使用示例**
```jsx
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;


```

**分栏使用示例**

```jsx
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](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-orientation.md)
> [@react-native-oh-tpl/react-native-reanimated](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-reanimated.md)


目前OpenHarmony暂不支持AutoLink，所以Link步骤需要手动配置。

首先需要使用DevEco Studio打开项目里的OpenHarmony工程，在工程根目录的`oh-package.json5`添加overrides字段：

```json
{
  ...
  "overrides": {
    "@rnoh/react-native-openharmony" : "./react_native_openharmony"
  }
}
```

### 引入原生端代码

目前有两种方法：

1. **通过har包引入（在IDE完善相关功能后该方法会被遗弃，目前首选此方法）。**

    >**说明：**
    >har包位于三方库安装路径的`harmony`文件夹下。

    a. 打开`entry/oh-package.json5`，添加以下依赖：

    ```json
    "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`，添加：

    ```diff
    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`，添加：

    ```diff
    #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`，添加：

    ```diff
      ...
    + import { LayoutModulePackage } from '@hadss/react_native_adaptive_layout/ts';
    
    export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
      return [
    +   new LayoutModulePackage(ctx),
      ];
    }
    ```

    e. 运行：

    点击右上角的`sync`按钮

    或者在终端执行：

    ```bash
    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操作同步代码。

2. **直接链接源码。**

    如需使用直接链接源码，请参考[直接链接源码说明](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/link-source-code.md)。

##  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      |

**约束：**

1. DisplayPriorityBox中子组件不支持position: 'absolute'布局。
2. DisplayPriorityBox容器仅在单行/列生效。
3. DisplayPriorityBox嵌套DisplayPriorityBox场景不适用。

### 栅格

**GridRow：栅格容器组件，仅可以和栅格子组件（GridCol）在栅格布局场景中使用，属性如下：**

| Name               | Description                                                  | Type                          | Platform |
| ------------------ | ------------------------------------------------------------ | ----------------------------- | -------- |
| columns            | 设置布局列数。默认值：12                                     | number \| GridRowColumnOption | All      |
| gutter             | 栅格布局间距。默认值：0                                      | Length  \| GutterOption       | All      |
| breakpoints        | 设置断点值的断点数列以及基于窗口或容器尺寸的相应参照。<br />默认值：{ 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   | 侧边栏嵌入到组件内，和内容区并列显示。<br/>组件尺寸小于minContentWidth + minSideBarWidth,并且未设置showSideBar时，侧边栏自动隐藏。<br/>未设置minSideBarWidth或者minContentWidth采用未设置接口的默认值进行计算。<br/>组件在自动隐藏后，如果通过点击控制按钮唤出侧边栏，则侧边栏悬浮在内容区上显示。<br/> |
| Overlay | 侧边栏浮在内容区上面。                                       |
| AUTO    | 组件尺寸大于等于minSideBarWidth+minContentWidth时，采用Embed模式显示。<br/>组件尺寸小于minSideBarWidth+minContentWidth时，采用Overlay模式显示。<br/>未设置minSideBarWidth或minContentWidth时，会使用未设置接口的默认值进行计算，若计算的值小于600，则使用600做为模式切换的断点值。<br/> |

**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                                               | 否       | 导航栏位置。<br/>默认值：NavBarPosition.Start。              |
| mode                   | NavigationMode                                               | 否       | 设置导航栏的显示模式，支持单栏（Stack）、分栏（Split）和自适应（Auto）。 |
| navBarWidthRange         | Length[]                                                       | 否       | 设置导航栏最小和最大宽度（双栏模式下生效）<br/>默认值：最小默认值 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显示为双栏;<br/>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及以上。