基于HarmonyOS API 24 React Native跨平台鸿蒙开发实战系列:输入表单如何适配任何机型,总是占据页面下部分
本文是基于HarmonyOS API 24的进行的React Native跨平台技术实战项目
React Native 跨端鸿蒙开发,行业简称 RNOH(React Native OpenHarmony),是社区 + 华为共建的适配层方案:把 Meta 的 React Native 框架完整移植到鸿蒙(HarmonyOS NEXT / OpenHarmony),让一套 React/JS/TS 代码,同时运行在Android、iOS、鸿蒙手机 / 平板 / PC多端,属于原生级跨端方案,区别于 WebView 套壳网页方案。
简单一句话:前端工程师不用学 ArkTS,用熟悉的 React 语法写业务,底层自动映射成鸿蒙 ArkUI 原生控件,打包成鸿蒙标准 hap 应用上架应用市场。
它的核心定位可以概括为:不改变 React/TypeScript 前端研发习惯,复用现有 RN 业务代码资产,依托鸿蒙系统底层接口做一层高性能中间适配层,将 JSX 组件、JS 业务逻辑映射为鸿蒙原生 ArkUI 控件,最终构建可在手机、平板、车机、智慧屏、PC 等全鸿蒙设备运行、支持上架华为应用市场的原生级应用。和 UniApp、WebView 套壳等网页类跨端方案有本质区别,RNOH 不依赖浏览器内核渲染页面,所有 UI 渲染、手势交互、视图层级全部交给鸿蒙系统原生图形引擎处理,不存在网页性能瓶颈、样式兼容偏差等问题。
兼容完整 React 生态、Hooks、JSX、RN 标准组件,前端工程师无需学习 ArkTS、ArkUI 声明式语法,仅需少量平台兼容代码即可完成多端适配;底层打通鸿蒙 NAPI、ArkUI C 底层接口,兼顾代码复用性与鸿蒙原生能力调用,核心面向存量 RN App 快速新增鸿蒙渠道,是前端团队切入鸿蒙生态最低成本的技术路线。
这里的flex:1相当于flex: 1 1 0%,它是一个简写属性,表示项目(flex item)在弹性容器(flex container)中如何伸缩。它相当于flex: 1 1 0%,包含了三个子属性:
- flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
- flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
- flex-basis 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间,默认值为 auto ,即项目本身的大小。
二、flex:1
1. 语法定义
flex:1 是 flex-grow:1; flex-shrink:1; flex-basis:0% 的简写形式。
2. 核心行为
空间分配逻辑:
元素的初始尺寸由 flex-basis:0% 决定,即默认不占用任何空间。剩余空间会根据 flex-grow 的权重比例分配。例如,若两个元素均设置 flex:1,则平分剩余空间。收缩能力:
当容器空间不足时,元素会按 flex-shrink:1 的比例收缩,但最小尺寸被限制为 0%(可能导致内容截断)。
3. 典型场景
- 等分布局:多个子元素需均分容器宽度(如导航栏按钮)。
- 内容无关的弹性区域:元素尺寸完全由容器剩余空间决定,忽略内容本身大小(如侧边栏和主内容区)。
二、flex:auto
1. 语法定义
flex:auto 等价于 flex-grow:1; flex-shrink:1; flex-basis:auto。
2. 核心行为
- 空间分配逻辑:
元素的初始尺寸由 flex-basis:auto 决定(即元素本身内容或显式设置的宽度/高度)。剩余空间按 flex-grow 分配,但需叠加初始尺寸。例如,若元素 A 的 flex-basis 为 200px,元素 B 的 flex-basis 为 100px,剩余空间将按 200px:100px 的比例分配。
- 收缩能力:
元素可收缩至小于初始尺寸(但不会小于 min-content),适合动态适配内容。
3. 典型场景
- 内容优先的弹性布局:需根据内容动态调整(如卡片布局中部分卡片需固定宽度,另一部分自适应)。
- 混合尺寸分配:需兼顾内容尺寸和剩余空间分配(如表单输入框与按钮组合)。
flex:1的作用
使用flex:1的作用是让项目能够自动填充剩余空间,实现自适应布局。例如,我们有一个水平排列的三个项目,它们的内容长度不一样,我们想让它们平均占据一行的空间,就可以给它们都设置flex:1。
flex:1 是 CSS 弹性盒布局中的一个常用属性简写,用于让子元素自动填充容器的剩余空间。
核心含义
- flex:1 等同于 flex-grow:1、flex-shrink:1 和 flex-basis:0%
- flex-grow:1:当容器有剩余空间时,该项目会放大以填满空间
- flex-shrink:1:当空间不足时,该项目会按比例缩小
- flex-basis:0%`:在分配空间前,项目的基础尺寸为 0%
主要作用
- 自动分配空间:根据容器剩余空间自动调整项目大小
- 实现等高布局:即使内容不同,也能保证项目高度一致
- 响应式适配:轻松应对不同屏幕尺寸的布局需求
典型应用场景
.container{display:flex;}.sidebar{width:200px;/* 固定宽度 */}.main{flex:1;/* 自动填满剩余空间 */}## 与 flex:auto 的区别
- flex:1:空间不足时优先缩小自身尺寸
- flex:auto:空间不足时优先保持内容完整显示
安装DevEco Studio程序
选择目标安装目录:
设置环境变量,但是需要重启一下:
新建一个空白模板:
设置API为24的模板项目:
初始化项目,自动下载相关依赖:
防止无限撑大的技巧
当 flex:1 的子项内容过多时,可设置 max-height 和 overflow:auto 来显示滚动条,而不是无限扩展。
实用建议:在构建侧边栏+内容区布局时,给固定宽高的侧边栏后,直接为主内容区设置 flex:1,即可实现完美的自适应填充效果。
importReactfrom'react';import{View,Text,Dimensions,StyleSheet,Image,TextInput,AppRegistry}from'react-native';//获取屏幕的宽高constscreenWidth=Math.round(Dimensions.get('window').width);constscreenHight=Math.round(Dimensions.get('window').height);constAppStyles=StyleSheet.create({wrap:{width:'100%',height:screenHight,backgroundColor:'#85BDFF'},title:{width:'100%',height:72,fontFamily:'OPPOSans, OPPOSans',fontWeight:'normal',paddingTop:50,fontSize:36,color:'#304057',lineHeight:72,textAlign:'center',fontStyle:'normal'},banner:{paddingTop:50,paddingRight:32,paddingLeft:32,},bannerItem:{paddingTop:10,display:'flex',flexDirection:'row',alignItems:'center',justifyContent:'center',width:'50%',},loginBox:{width:'100%',paddingTop:29,paddingLeft:20,paddingRight:20,borderTopRightRadius:30,borderTopLeftRadius:30,backgroundColor:'#F2F8FF',flex:1}})functionApp(){return(<View style={AppStyles.wrap}><Text style={AppStyles.title}>鸿蒙ReactNative系统</Text><View style={AppStyles.banner}><View style={{display:'flex',flexDirection:'row',justifyContent:'space-between'}}><View style={AppStyles.bannerItem}><Image style={{width:27,height:27}}source={require('./images/checked.png')}></Image><Text style={{paddingLeft:4}}>实时业绩便捷查询</Text></View><View style={AppStyles.bannerItem}><Image style={{width:27,height:27}}source={require('./images/checked.png')}></Image><Text style={{paddingLeft:4}}>订单状态轻松把控</Text></View></View><View style={{display:'flex',flexDirection:'row',justifyContent:'space-between'}}><View style={AppStyles.bannerItem}><Image style={{width:27,height:27}}source={require('./images/checked.png')}></Image><Text style={{paddingLeft:4}}>宣传数据全程管理</Text></View><View style={AppStyles.bannerItem}><Image style={{width:27,height:27}}source={require('./images/checked.png')}></Image><Text style={{paddingLeft:4}}>海量素材一站转发</Text></View></View></View><Image style={{width:289,height:182,display:'flex',alignSelf:'center',margin:20}}source={require('./images/login-bg.png')}></Image><View style={AppStyles.loginBox}><TextInput style={{width:'100%',height:48,borderRadius:10,backgroundColor:'#FFFFFF',paddingLeft:16,paddingRight:16,fontSize:14,color:'#304057'}}placeholder="请输入手机号"></TextInput></View></View>);}exportdefaultApp;解决了问题:
在Web开发初期,开发者主要依赖float、position和inline-block实现页面布局,垂直居中难题:传统方案需通过margin: auto、transform或绝对定位配合top:50%等hack实现,代码冗余且维护性差。