npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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多设备适配问题的三方库,专为不同设备类型(包括折叠屏、平板、手机等)提供了便捷的支持。该库包含的接口和开箱即用的组件,使开发者能够轻松应对各种设备的布局适配需求。

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

  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接口

安装与使用

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

npm

npm install @hadss/react_native_adaptive_layout

yarn

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"
  }
}

引入原生端代码

目前有两种方法:

  1. 通过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操作同步代码。

  1. 直接链接源码。

    如需使用直接链接源码,请参考直接链接源码说明

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 | 设置断点值的断点数列以及基于窗口或容器尺寸的相应参照。默认值:{ 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及以上。