51. React Native 鸿蒙跨平台开发:Flexbox 弹性布局代码指南

一、核心知识点:Flexbox 弹性布局完整核心用法

1. 用到的纯内置组件与 API

所有能力均为 RN 原生自带,全部从 react-native 核心包直接导入,无任何额外依赖、无任何第三方库,鸿蒙端无任何兼容问题,也是实现 Flexbox 弹性布局的全部核心能力,零基础易理解、易复用,无任何冗余,所有 Flexbox 弹性布局功能均基于以下组件/API 原生实现:

核心组件/API 作用说明 鸿蒙适配特性
View 核心容器组件,实现所有「弹性布局容器」,支持 flex、flexDirection、justifyContent、alignItems、alignSelf、flexWrap、flexGrow、flexShrink、flexBasis、gap 等所有 Flexbox 属性 ✅ 鸿蒙端 Flexbox 布局渲染无错位,所有属性完美生效
Text 文本组件,显示布局示例和说明 ✅ 鸿蒙端文本渲染正常,支持多行文本
StyleSheet 原生样式管理,编写鸿蒙端最优的 Flexbox 样式:弹性容器样式、对齐样式、间距样式,无任何不兼容CSS属性 ✅ 贴合鸿蒙官方视觉设计规范,颜色、圆角、间距均为真机实测最优值
SafeAreaView 安全区域容器,适配刘海屏等异形屏 ✅ 鸿蒙端安全区域适配正常
ScrollView 滚动容器,支持 flex 布局的滚动内容 ✅ 鸿蒙端滚动正常

二、深入理解 Flexbox 弹性布局

1. Flexbox 是什么?

Flexbox(Flexible Box)是一种一维布局模型,用于在容器中高效地分配空间和对齐子元素。React Native 实现了 Flexbox 布局系统的核心子集,与 Web 端的 Flexbox 非常相似,但有一些差异。

2. 为什么需要 Flexbox?

在移动应用开发中,我们需要一种灵活、高效的布局方式来适应不同屏幕尺寸和方向。Flexbox 提供了以下优势:

  1. 响应式布局:自动适应不同屏幕尺寸
  2. 灵活对齐:轻松实现水平和垂直对齐
  3. 空间分配:自动分配剩余空间
  4. 方向控制:支持横向和纵向布局
  5. 简化代码:减少嵌套层级,提高可读性

3. Flexbox 的核心概念

Flexbox 布局基于两个核心概念:

  • Flex 容器(Flex Container):设置了 display: flex 的父元素
  • Flex 子项(Flex Items):Flex 容器的直接子元素

4. Flexbox 的类型定义

// Flexbox 相关的样式属性类型
interface FlexStyle {
  flex?: number;
  flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
  justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
  alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
  alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
  flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse';
  flexGrow?: number;
  flexShrink?: number;
  flexBasis?: number | string;
  gap?: number | string;
  rowGap?: number | string;
  columnGap?: number | string;
}

三、Flexbox 容器属性详解

1. flexDirection - 主轴方向

控制 Flex 容器的主轴方向,决定子元素的排列方向。

// 横向排列(默认)
<View style={{ flexDirection: 'row' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 纵向排列
<View style={{ flexDirection: 'column' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 横向反向排列
<View style={{ flexDirection: 'row-reverse' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 纵向反向排列
<View style={{ flexDirection: 'column-reverse' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

取值说明

  • row:横向排列,从左到右(默认)
  • column:纵向排列,从上到下
  • row-reverse:横向反向排列,从右到左
  • column-reverse:纵向反向排列,从下到上

2. justifyContent - 主轴对齐

控制子元素在主轴上的对齐方式。

// 起始对齐(默认)
<View style={{ flexDirection: 'row', justifyContent: 'flex-start' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 结束对齐
<View style={{ flexDirection: 'row', justifyContent: 'flex-end' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 居中对齐
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 两端对齐
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 环绕对齐
<View style={{ flexDirection: 'row', justifyContent: 'space-around' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 均匀对齐
<View style={{ flexDirection: 'row', justifyContent: 'space-evenly' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

取值说明

  • flex-start:起始对齐(默认)
  • flex-end:结束对齐
  • center:居中对齐
  • space-between:两端对齐,子元素之间间距相等
  • space-around:环绕对齐,子元素两侧间距相等
  • space-evenly:均匀对齐,所有间距相等

3. alignItems - 交叉轴对齐

控制子元素在交叉轴上的对齐方式。

// 起始对齐(默认)
<View style={{ flexDirection: 'row', alignItems: 'flex-start' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={[styles.box, { height: 60 }]}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 结束对齐
<View style={{ flexDirection: 'row', alignItems: 'flex-end' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={[styles.box, { height: 60 }]}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 居中对齐
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={[styles.box, { height: 60 }]}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 拉伸对齐
<View style={{ flexDirection: 'row', alignItems: 'stretch' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={[styles.box, { height: 60 }]}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

取值说明

  • flex-start:起始对齐(默认)
  • flex-end:结束对齐
  • center:居中对齐
  • stretch:拉伸对齐,子元素拉伸填满交叉轴
  • baseline:基线对齐(文本基线)

4. flexWrap - 换行控制

控制子元素是否换行。

// 不换行(默认)
<View style={{ flexDirection: 'row', flexWrap: 'nowrap' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
  <View style={styles.box}><Text>4</Text></View>
  <View style={styles.box}><Text>5</Text></View>
</View>

// 换行
<View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
  <View style={styles.box}><Text>4</Text></View>
  <View style={styles.box}><Text>5</Text></View>
</View>

// 反向换行
<View style={{ flexDirection: 'row', flexWrap: 'wrap-reverse' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
  <View style={styles.box}><Text>4</Text></View>
  <View style={styles.box}><Text>5</Text></View>
</View>

取值说明

  • nowrap:不换行(默认)
  • wrap:换行
  • wrap-reverse:反向换行

5. gap - 间距控制

控制子元素之间的间距。

// 统一间距
<View style={{ flexDirection: 'row', gap: 10 }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
</View>

// 行间距和列间距
<View style={{ flexDirection: 'row', flexWrap: 'wrap', rowGap: 10, columnGap: 20 }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={styles.box}><Text>2</Text></View>
  <View style={styles.box}><Text>3</Text></View>
  <View style={styles.box}><Text>4</Text></View>
  <View style={styles.box}><Text>5</Text></View>
</View>

取值说明

  • gap:统一间距,同时设置行间距和列间距
  • rowGap:行间距
  • columnGap:列间距

四、Flexbox 子项属性详解

1. flex - 弹性比例

控制子元素的弹性比例,决定如何分配剩余空间。

// 等比例分配
<View style={{ flexDirection: 'row' }}>
  <View style={[styles.box, { flex: 1 }]}><Text>1</Text></View>
  <View style={[styles.box, { flex: 1 }]}><Text>2</Text></View>
  <View style={[styles.box, { flex: 1 }]}><Text>3</Text></View>
</View>

// 不同比例分配
<View style={{ flexDirection: 'row' }}>
  <View style={[styles.box, { flex: 1 }]}><Text>1</Text></View>
  <View style={[styles.box, { flex: 2 }]}><Text>2</Text></View>
  <View style={[styles.box, { flex: 1 }]}><Text>3</Text></View>
</View>

// 固定宽度 + 弹性
<View style={{ flexDirection: 'row' }}>
  <View style={[styles.box, { width: 60 }]}><Text>1</Text></View>
  <View style={[styles.box, { flex: 1 }]}><Text>2</Text></View>
  <View style={[styles.box, { width: 60 }]}><Text>3</Text></View>
</View>

取值说明

  • flex: 1:占据所有可用空间
  • flex: 2:占据两倍可用空间
  • flex: 0:不占据可用空间(固定大小)

2. alignSelf - 独立对齐

控制单个子元素的对齐方式,覆盖容器的 alignItems

<View style={{ flexDirection: 'row', alignItems: 'flex-start' }}>
  <View style={styles.box}><Text>1</Text></View>
  <View style={[styles.box, { alignSelf: 'center' }]}><Text>2</Text></View>
  <View style={[styles.box, { alignSelf: 'flex-end' }]}><Text>3</Text></View>
</View>

取值说明

  • auto:继承容器的 alignItems(默认)
  • flex-start:起始对齐
  • flex-end:结束对齐
  • center:居中对齐
  • stretch:拉伸对齐
  • baseline:基线对齐

3. flexGrow - 扩展比例

控制子元素的扩展比例。

<View style={{ flexDirection: 'row' }}>
  <View style={[styles.box, { flexGrow: 0 }]}><Text>1</Text></View>
  <View style={[styles.box, { flexGrow: 1 }]}><Text>2</Text></View>
  <View style={[styles.box, { flexGrow: 2 }]}><Text>3</Text></View>
</View>

取值说明

  • flexGrow: 0:不扩展(默认)
  • flexGrow: 1:扩展
  • flexGrow: 2:扩展两倍

五、实战完整版:企业级通用 Flexbox 弹性布局

import React, { useState } from 'react';
import {
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  SafeAreaView,
  ScrollView,
} from 'react-native';

// Flexbox 弹性布局演示
const FlexboxScreen = () => {
  const [alignItems, setAlignItems] = useState<'flex-start' | 'center' | 'flex-end' | 'stretch'>('flex-start');
  const [justifyContent, setJustifyContent] = useState<'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'>('flex-start');
  const [flexDirection, setFlexDirection] = useState<'row' | 'column'>('row');

  const alignItemsOptions = [
    { value: 'flex-start', label: 'flex-start', description: '起始对齐' },
    { value: 'center', label: 'center', description: '居中对齐' },
    { value: 'flex-end', label: 'flex-end', description: '结束对齐' },
    { value: 'stretch', label: 'stretch', description: '拉伸对齐' },
  ];

  const justifyContentOptions = [
    { value: 'flex-start', label: 'flex-start', description: '起始对齐' },
    { value: 'center', label: 'center', description: '居中对齐' },
    { value: 'flex-end', label: 'flex-end', description: '结束对齐' },
    { value: 'space-between', label: 'space-between', description: '两端对齐' },
    { value: 'space-around', label: 'space-around', description: '环绕对齐' },
    { value: 'space-evenly', label: 'space-evenly', description: '均匀对齐' },
  ];

  const flexDirectionOptions = [
    { value: 'row', label: 'row', description: '水平布局' },
    { value: 'column', label: 'column', description: '垂直布局' },
  ];

  return (
    <SafeAreaView style={styles.container}>
      {/* 标题区域 */}
      <View style={styles.header}>
        <Text style={styles.pageTitle}>React Native for Harmony</Text>
        <Text style={styles.subtitle}>Flexbox 弹性布局</Text>
      </View>

      {/* 内容区域 */}
      <ScrollView style={styles.content}>
        {/* flexDirection 选择 */}
        <View style={styles.card}>
          <View style={styles.cardHeader}>
            <Text style={styles.cardTitle}>flexDirection - 主轴方向</Text>
          </View>
          <View style={styles.cardBody}>
            <Text style={styles.currentValue}>当前: {flexDirection}</Text>
            <View style={styles.buttonRow}>
              {flexDirectionOptions.map((option) => (
                <TouchableOpacity
                  key={option.value}
                  style={[
                    styles.optionButton,
                    flexDirection === option.value && styles.optionButtonActive,
                  ]}
                  onPress={() => setFlexDirection(option.value as any)}
                >
                  <Text style={[
                    styles.optionButtonText,
                    flexDirection === option.value && styles.optionButtonTextActive,
                  ]}>
                    {option.label}
                  </Text>
                </TouchableOpacity>
              ))}
            </View>
          </View>
        </View>

        {/* justifyContent 选择 */}
        <View style={styles.card}>
          <View style={styles.cardHeader}>
            <Text style={styles.cardTitle}>justifyContent - 主轴对齐</Text>
          </View>
          <View style={styles.cardBody}>
            <Text style={styles.currentValue}>当前: {justifyContent}</Text>
            <View style={styles.buttonRow}>
              {justifyContentOptions.map((option) => (
                <TouchableOpacity
                  key={option.value}
                  style={[
                    styles.optionButton,
                    justifyContent === option.value && styles.optionButtonActive,
                  ]}
                  onPress={() => setJustifyContent(option.value as any)}
                >
                  <Text style={[
                    styles.optionButtonText,
                    justifyContent === option.value && styles.optionButtonTextActive,
                  ]}>
                    {option.label}
                  </Text>
                </TouchableOpacity>
              ))}
            </View>
          </View>
        </View>

        {/* alignItems 选择 */}
        <View style={styles.card}>
          <View style={styles.cardHeader}>
            <Text style={styles.cardTitle}>alignItems - 交叉轴对齐</Text>
          </View>
          <View style={styles.cardBody}>
            <Text style={styles.currentValue}>当前: {alignItems}</Text>
            <View style={styles.buttonRow}>
              {alignItemsOptions.map((option) => (
                <TouchableOpacity
                  key={option.value}
                  style={[
                    styles.optionButton,
                    alignItems === option.value && styles.optionButtonActive,
                  ]}
                  onPress={() => setAlignItems(option.value as any)}
                >
                  <Text style={[
                    styles.optionButtonText,
                    alignItems === option.value && styles.optionButtonTextActive,
                  ]}>
                    {option.label}
                  </Text>
                </TouchableOpacity>
              ))}
            </View>
          </View>
        </View>

        {/* 演示区域 */}
        <View style={styles.card}>
          <View style={styles.cardHeader}>
            <Text style={styles.cardTitle}>实时预览</Text>
          </View>
          <View style={styles.cardBody}>
            <View
              style={[
                styles.previewContainer,
                {
                  flexDirection,
                  justifyContent,
                  alignItems,
                },
              ]}
            >
              <View style={styles.previewItem}>
                <Text style={styles.previewText}>1</Text>
              </View>
              <View style={styles.previewItem}>
                <Text style={styles.previewText}>2</Text>
              </View>
              <View style={styles.previewItem}>
                <Text style={styles.previewText}>3</Text>
              </View>
            </View>
            <View style={styles.codePreview}>
              <Text style={styles.codeText}>
                flexDirection: "{flexDirection}"{'\n'}
                justifyContent: "{justifyContent}"{'\n'}
                alignItems: "{alignItems}"
              </Text>
            </View>
          </View>
        </View>

        {/* 说明区域 */}
        <View style={styles.infoCard}>
          <Text style={styles.infoTitle}>💡 属性说明</Text>
          <Text style={styles.infoText}>• flexDirection: 主轴方向(row: 水平, column: 垂直)</Text>
          <Text style={styles.infoText}>• justifyContent: 主轴对齐方式</Text>
          <Text style={styles.infoText}>• alignItems: 交叉轴对齐方式</Text>
          <Text style={styles.infoText}>• 点击按钮切换不同布局效果</Text>
          <Text style={styles.infoText}>• 鸿蒙端完美兼容,交互流畅</Text>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

const App = () => {
  return <FlexboxScreen />;
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5F7FA',
  },

  // ======== 标题区域 ========
  header: {
    padding: 20,
    backgroundColor: '#FFFFFF',
    borderBottomWidth: 1,
    borderBottomColor: '#EBEEF5',
  },
  pageTitle: {
    fontSize: 24,
    fontWeight: '700',
    color: '#303133',
    textAlign: 'center',
    marginBottom: 8,
  },
  subtitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#909399',
    textAlign: 'center',
  },

  // ======== 内容区域 ========
  content: {
    flex: 1,
    padding: 16,
  },

  // ======== 卡片样式 ========
  card: {
    backgroundColor: '#FFFFFF',
    borderRadius: 12,
    marginBottom: 16,
    shadowColor: '#000000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 8,
    elevation: 4,
  },
  cardHeader: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#EBEEF5',
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#303133',
  },
  cardBody: {
    padding: 16,
  },

  // ======== 当前值显示 ========
  currentValue: {
    fontSize: 14,
    color: '#606266',
    marginBottom: 12,
    textAlign: 'center',
  },

  // ======== 按钮行 ========
  buttonRow: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    marginBottom: 8,
  },

  // ======== 选项按钮 ========
  optionButton: {
    backgroundColor: '#F5F7FA',
    paddingHorizontal: 12,
    paddingVertical: 8,
    borderRadius: 6,
    marginRight: 8,
    marginBottom: 8,
    borderWidth: 1,
    borderColor: '#DCDFE6',
  },
  optionButtonActive: {
    backgroundColor: '#409EFF',
    borderColor: '#409EFF',
  },
  optionButtonText: {
    fontSize: 12,
    color: '#606266',
    fontWeight: '500',
  },
  optionButtonTextActive: {
    color: '#FFFFFF',
  },

  // ======== 预览容器 ========
  previewContainer: {
    backgroundColor: '#F5F7FA',
    borderRadius: 8,
    padding: 20,
    minHeight: 150,
    marginBottom: 16,
  },
  previewItem: {
    width: 60,
    height: 60,
    backgroundColor: '#409EFF',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
    margin: 8,
  },
  previewText: {
    fontSize: 24,
    fontWeight: '700',
    color: '#FFFFFF',
  },

  // ======== 代码预览 ========
  codePreview: {
    backgroundColor: '#2D2D2D',
    borderRadius: 8,
    padding: 12,
  },
  codeText: {
    fontSize: 12,
    color: '#00FF00',
    fontFamily: 'monospace',
  },

  // ======== 信息卡片 ========
  infoCard: {
    backgroundColor: '#FFFFFF',
    borderRadius: 12,
    padding: 16,
    margin: 16,
    marginTop: 0,
    shadowColor: '#000000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 8,
    elevation: 4,
  },
  infoTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#303133',
    marginBottom: 12,
  },
  infoText: {
    fontSize: 14,
    color: '#606266',
    lineHeight: 22,
    marginBottom: 6,
  },
});

export default App;

在这里插入图片描述

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐