一、核心知识点:Steps 步骤条 完整核心用法

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

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

核心组件/API 作用说明 鸿蒙适配特性
View 核心步骤条容器组件,实现所有「步骤节点、连接线、步骤内容」,支持垂直/水平布局、间距控制 ✅ 鸿蒙端样式渲染无错位,宽高、圆角、背景色属性完美生效,无样式失效问题
useState / useRef / useEffect React 原生钩子,管理「当前步骤、步骤数据、动画状态」核心数据,控制步骤切换、动画启停 ✅ 响应式更新无延迟,状态切换流畅无卡顿,步骤切换无缝衔接
StyleSheet 原生样式管理,编写鸿蒙端最优的步骤条样式:节点圆圈、连接线、文字颜色、间距,无任何不兼容CSS属性 ✅ 贴合鸿蒙官方视觉设计规范,步骤颜色、圆角、间距均为真机实测最优值,无适配差异
TouchableOpacity 原生可点击按钮,实现「切换步骤、重置步骤」控制按钮,鸿蒙端点击反馈流畅 ✅ 无按压波纹失效、点击无响应等兼容问题,交互体验和鸿蒙原生一致
Text 展示步骤标题、描述文字,支持多行文本、不同颜色状态,鸿蒙端文字排版精准 ✅ 鸿蒙端文字排版精准,字号、颜色、行高适配无偏差
Animated / Easing RN原生动画核心API,实现步骤条灵魂的「节点缩放动画」,流畅无卡顿,无第三方动画库依赖 ✅ 鸿蒙端完美兼容,动画渲染流畅,无报错无闪退,是RN实现动画的标准方案
Dimensions RN原生屏幕尺寸API,动态获取屏幕宽高,实现步骤条的响应式布局,适配不同屏幕尺寸 ✅ 鸿蒙端完美兼容,屏幕尺寸获取准确,布局自适应无问题

二、实战核心代码讲解

在展示完整代码之前,我们先深入理解步骤条实现的核心逻辑,掌握这些核心代码后,你将能够轻松应对各种步骤条相关的开发需求。

1. 步骤状态管理 - 核心逻辑

步骤条的核心在于状态管理,我们需要判断每个步骤处于什么状态(待处理、进行中、已完成),并根据状态渲染不同的样式。

// 步骤状态类型
type StepStatus = 'pending' | 'process' | 'finish' | 'error';

// 当前步骤索引
const [currentStep, setCurrentStep] = useState<number>(0);

// 获取步骤状态:核心判断逻辑
const getStepStatus = (index: number): StepStatus => {
  if (index < currentStep) return 'finish'; // 已完成:索引小于当前步骤
  if (index === currentStep) return 'process'; // 进行中:索引等于当前步骤
  return 'pending'; // 待处理:索引大于当前步骤
};

核心要点:

  • 通过比较步骤索引和当前步骤索引,动态判断每个步骤的状态
  • index < currentStep:表示该步骤已经完成,显示绿色对勾
  • index === currentStep:表示该步骤正在进行,显示蓝色高亮
  • index > currentStep:表示该步骤还未开始,显示灰色

2. 步骤样式映射 - 视觉呈现

根据不同的步骤状态,返回对应的颜色、图标等样式,实现视觉上的差异化。

// 获取步骤状态对应的样式
const getStepStyle = (status: StepStatus) => {
  switch (status) {
    case 'finish':
      return {
        backgroundColor: '#4CAF50', // 绿色背景
        borderColor: '#4CAF50',
        textColor: '#4CAF50',
        icon: '✓', // 对勾图标
      };
    case 'process':
      return {
        backgroundColor: '#007DFF', // 蓝色背景
        borderColor: '#007DFF',
        textColor: '#007DFF',
        icon: '',
      };
    case 'error':
      return {
        backgroundColor: '#F44336', // 红色背景
        borderColor: '#F44336',
        textColor: '#F44336',
        icon: '!',
      };
    case 'pending':
    default:
      return {
        backgroundColor: '#E5E6EB', // 灰色背景
        borderColor: '#E5E6EB',
        textColor: '#999',
        icon: '',
      };
  }
};

核心要点:

  • 使用 switch 语句根据状态返回对应的样式对象
  • 每个状态都有独立的背景色、边框色、文字颜色和图标
  • 鸿蒙端完美支持这些颜色值,无适配问题

3. 步骤节点动画 - 交互体验

当前步骤节点需要有一个缩放动画,让用户清楚地知道当前处于哪个步骤。

const scaleAnim = useRef(new Animated.Value(status === 'process' ? 1.2 : 1)).current;

// 当前步骤的缩放动画
useEffect(() => {
  if (status === 'process') {
    Animated.spring(scaleAnim, {
      toValue: 1.2, // 放大到 1.2 倍
      friction: 7,  // 摩擦力:值越小,弹性越大
      tension: 40,  // 张力:值越小,动画越慢
      useNativeDriver: true, // 使用原生驱动,鸿蒙端完美支持
    }).start();
  } else {
    Animated.spring(scaleAnim, {
      toValue: 1, // 恢复到原始大小
      friction: 7,
      tension: 40,
      useNativeDriver: true,
    }).start();
  }
}, [status]); // 依赖 status 变化时触发动画

核心要点:

  • 使用 Animated.spring 实现弹性动画,比 Animated.timing 更自然
  • friction: 7tension: 40 是鸿蒙端实测最优的动画参数组合
  • useNativeDriver: true 确保动画在鸿蒙端流畅运行,无卡顿
  • 当步骤状态变化时,自动触发动画

4. 水平布局 - 连接线处理

水平布局的步骤条需要处理连接线的显示,连接线只在非最后一项显示。

// 水平布局的步骤节点
<View style={styles.horizontalStepNode}>
  {/* 节点圆圈 */}
  <Animated.View style={[styles.stepCircle, { ... }]}>
    {/* 节点内容 */}
  </Animated.View>

  {/* 连接线:非最后一项才显示 */}
  {!isLast && (
    <View
      style={[
        styles.horizontalConnector,
        {
          backgroundColor: status === 'finish' ? '#4CAF50' : '#E5E6EB',
        },
      ]}
    />
  )}
</View>

// 连接线样式
horizontalConnector: {
  flex: 1,       // 占据剩余空间
  height: 3,     // 连接线高度
  minWidth: 40,  // 最小宽度,确保连接线可见
  marginLeft: 10, // 与节点圆圈的间距
}

核心要点:

  • 使用 !isLast 判断,只在非最后一项显示连接线
  • flex: 1 让连接线自动填充剩余空间
  • minWidth: 40 防止连接线过窄,确保在鸿蒙端清晰可见
  • 连接线颜色根据步骤状态动态变化:已完成显示绿色,其他显示灰色

5. 垂直布局 - 连接线处理

垂直布局的连接线处理方式与水平布局类似,但方向不同。

// 垂直布局的步骤节点
<View style={styles.verticalStepNode}>
  {/* 节点圆圈 */}
  <Animated.View style={[styles.stepCircle, { ... }]}>
    {/* 节点内容 */}
  </Animated.View>

  {/* 连接线:非最后一项才显示 */}
  {!isLast && (
    <View
      style={[
        styles.verticalConnector,
        {
          backgroundColor: status === 'finish' ? '#4CAF50' : '#E5E6EB',
        },
      ]}
    />
  )}
</View>

// 垂直连接线样式
verticalConnector: {
  width: 3,       // 连接线宽度
  flex: 1,       // 占据剩余空间
  marginTop: 10, // 与节点圆圈的间距
}

核心要点:

  • 垂直连接线的宽度为 3,高度通过 flex: 1 自动填充
  • marginTop: 10 确保连接线与节点圆圈有合适的间距
  • 连接线颜色同样根据步骤状态动态变化

6. 步骤切换 - 用户交互

提供上一步、下一步、重置等操作,让用户可以控制步骤的切换。

// 下一步
const handleNext = () => {
  if (currentStep < steps.length - 1) {
    setCurrentStep(prev => prev + 1); // 步骤索引 +1
  }
};

// 上一步
const handlePrev = () => {
  if (currentStep > 0) {
    setCurrentStep(prev => prev - 1); // 步骤索引 -1
  }
};

// 重置步骤
const handleReset = () => {
  setCurrentStep(0); // 重置到第一步
};

核心要点:

  • 使用边界判断防止索引越界
  • 使用函数式更新 prev => prev + 1 确保状态更新正确
  • 鸿蒙端状态更新流畅,无延迟

通过以上核心代码的讲解,你应该已经掌握了步骤条实现的核心逻辑。接下来我们将展示完整的代码实现。

三、实战完整版:企业级通用 Steps 步骤条

import React, { useState, useEffect, useRef } from 'react';
import {
  View, Text, TouchableOpacity, StyleSheet, SafeAreaView,
  Animated, Dimensions, ScrollView, Platform
} from 'react-native';

// 步骤状态类型
type StepStatus = 'pending' | 'process' | 'finish' | 'error';

// 步骤数据结构
interface StepData {
  id: number;
  title: string;
  description?: string;
}

const StepsScreen = () => {
  const [currentStep, setCurrentStep] = useState<number>(0);
  const [direction, setDirection] = useState<'horizontal' | 'vertical'>('horizontal');

  // 步骤数据
  const steps: StepData[] = [
    {
      id: 1,
      title: '填写信息',
      description: '完善个人基本信息',
    },
    {
      id: 2,
      title: '上传资料',
      description: '上传相关证明文件',
    },
    {
      id: 3,
      title: '审核中',
      description: '等待系统审核',
    },
    {
      id: 4,
      title: '完成',
      description: '操作完成',
    },
  ];

  // 获取步骤状态
  const getStepStatus = (index: number): StepStatus => {
    if (index < currentStep) return 'finish';
    if (index === currentStep) return 'process';
    return 'pending';
  };

  // 获取步骤状态对应的样式
  const getStepStyle = (status: StepStatus) => {
    switch (status) {
      case 'finish':
        return {
          backgroundColor: '#4CAF50',
          borderColor: '#4CAF50',
          textColor: '#4CAF50',
          icon: '✓',
        };
      case 'process':
        return {
          backgroundColor: '#007DFF',
          borderColor: '#007DFF',
          textColor: '#007DFF',
          icon: '',
        };
      case 'error':
        return {
          backgroundColor: '#F44336',
          borderColor: '#F44336',
          textColor: '#F44336',
          icon: '!',
        };
      case 'pending':
      default:
        return {
          backgroundColor: '#E5E6EB',
          borderColor: '#E5E6EB',
          textColor: '#999',
          icon: '',
        };
    }
  };

  // 单个步骤节点组件(水平布局)
  const HorizontalStepItem: React.FC<{ step: StepData; index: number; isLast: boolean }> = ({
    step,
    index,
    isLast,
  }) => {
    const status = getStepStatus(index);
    const style = getStepStyle(status);
    const scaleAnim = useRef(new Animated.Value(status === 'process' ? 1.2 : 1)).current;

    // 当前步骤的缩放动画
    useEffect(() => {
      if (status === 'process') {
        Animated.spring(scaleAnim, {
          toValue: 1.2,
          friction: 7,
          tension: 40,
          useNativeDriver: true,
        }).start();
      } else {
        Animated.spring(scaleAnim, {
          toValue: 1,
          friction: 7,
          tension: 40,
          useNativeDriver: true,
        }).start();
      }
    }, [status]);

    return (
      <View style={styles.horizontalStepItem}>
        {/* 步骤节点 */}
        <View style={styles.horizontalStepNode}>
          {/* 节点圆圈 */}
          <Animated.View
            style={[
              styles.stepCircle,
              {
                backgroundColor: style.backgroundColor,
                borderColor: style.borderColor,
                transform: [{ scale: scaleAnim }],
              },
            ]}
          >
            {status === 'finish' ? (
              <Text style={styles.stepIcon}>{style.icon}</Text>
            ) : (
              <Text style={[styles.stepNumber, { color: status === 'pending' ? '#999' : '#fff' }]}>
                {index + 1}
              </Text>
            )}
          </Animated.View>

          {/* 连接线(非最后一项) */}
          {!isLast && (
            <View
              style={[
                styles.horizontalConnector,
                {
                  backgroundColor: status === 'finish' ? '#4CAF50' : '#E5E6EB',
                },
              ]}
            />
          )}
        </View>

        {/* 步骤文字 */}
        <View style={styles.horizontalStepText}>
          <Text style={[styles.stepTitle, { color: style.textColor }]}>{step.title}</Text>
          {step.description && (
            <Text style={styles.stepDescription}>{step.description}</Text>
          )}
        </View>
      </View>
    );
  };

  // 单个步骤节点组件(垂直布局)
  const VerticalStepItem: React.FC<{ step: StepData; index: number; isLast: boolean }> = ({
    step,
    index,
    isLast,
  }) => {
    const status = getStepStatus(index);
    const style = getStepStyle(status);
    const scaleAnim = useRef(new Animated.Value(status === 'process' ? 1.2 : 1)).current;

    // 当前步骤的缩放动画
    useEffect(() => {
      if (status === 'process') {
        Animated.spring(scaleAnim, {
          toValue: 1.2,
          friction: 7,
          tension: 40,
          useNativeDriver: true,
        }).start();
      } else {
        Animated.spring(scaleAnim, {
          toValue: 1,
          friction: 7,
          tension: 40,
          useNativeDriver: true,
        }).start();
      }
    }, [status]);

    return (
      <View style={styles.verticalStepItem}>
        <View style={styles.verticalStepContent}>
          {/* 步骤节点 */}
          <View style={styles.verticalStepNode}>
            {/* 节点圆圈 */}
            <Animated.View
              style={[
                styles.stepCircle,
                {
                  backgroundColor: style.backgroundColor,
                  borderColor: style.borderColor,
                  transform: [{ scale: scaleAnim }],
                },
              ]}
            >
              {status === 'finish' ? (
                <Text style={styles.stepIcon}>{style.icon}</Text>
              ) : (
                <Text style={[styles.stepNumber, { color: status === 'pending' ? '#999' : '#fff' }]}>
                  {index + 1}
                </Text>
              )}
            </Animated.View>

            {/* 连接线(非最后一项) */}
            {!isLast && (
              <View
                style={[
                  styles.verticalConnector,
                  {
                    backgroundColor: status === 'finish' ? '#4CAF50' : '#E5E6EB',
                  },
                ]}
              />
            )}
          </View>

          {/* 步骤文字 */}
          <View style={styles.verticalStepText}>
            <Text style={[styles.stepTitle, { color: style.textColor }]}>{step.title}</Text>
            {step.description && (
              <Text style={styles.stepDescription}>{step.description}</Text>
            )}
          </View>
        </View>
      </View>
    );
  };

  // 下一步
  const handleNext = () => {
    if (currentStep < steps.length - 1) {
      setCurrentStep(prev => prev + 1);
    }
  };

  // 上一步
  const handlePrev = () => {
    if (currentStep > 0) {
      setCurrentStep(prev => prev - 1);
    }
  };

  // 重置步骤
  const handleReset = () => {
    setCurrentStep(0);
  };

  // 切换布局方向
  const toggleDirection = () => {
    setDirection(prev => (prev === 'horizontal' ? 'vertical' : 'horizontal'));
  };

  return (
    <SafeAreaView style={styles.container}>
      <Text style={styles.title}>React Native for Harmony</Text>
      <Text style={styles.subtitle}>Steps 步骤条</Text>

      {/* 控制按钮组 */}
      <View style={styles.controlGroup}>
        <TouchableOpacity
          style={[styles.controlBtn, styles.primaryBtn]}
          onPress={toggleDirection}
        >
          <Text style={styles.controlBtnText}>
            {direction === 'horizontal' ? '切换垂直布局' : '切换水平布局'}
          </Text>
        </TouchableOpacity>
      </View>

      {/* 步骤条容器 */}
      <View style={styles.stepsContainer}>
        {direction === 'horizontal' ? (
          // 水平布局
          <ScrollView
            horizontal
            showsHorizontalScrollIndicator={false}
            contentContainerStyle={styles.horizontalStepsWrapper}
          >
            {steps.map((step, index) => (
              <HorizontalStepItem
                key={step.id}
                step={step}
                index={index}
                isLast={index === steps.length - 1}
              />
            ))}
          </ScrollView>
        ) : (
          // 垂直布局
          <ScrollView showsVerticalScrollIndicator={false}>
            <View style={styles.verticalStepsWrapper}>
              {steps.map((step, index) => (
                <VerticalStepItem
                  key={step.id}
                  step={step}
                  index={index}
                  isLast={index === steps.length - 1}
                />
              ))}
            </View>
          </ScrollView>
        )}
      </View>

      {/* 操作按钮组 */}
      <View style={styles.buttonGroup}>
        <TouchableOpacity
          style={[styles.button, styles.prevButton]}
          onPress={handlePrev}
          disabled={currentStep === 0}
        >
          <Text style={[styles.buttonText, currentStep === 0 && styles.disabledText]}>
            上一步
          </Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.resetButton]}
          onPress={handleReset}
        >
          <Text style={styles.buttonText}>重置</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.nextButton]}
          onPress={handleNext}
          disabled={currentStep === steps.length - 1}
        >
          <Text style={[styles.buttonText, currentStep === steps.length - 1 && styles.disabledText]}>
            下一步
          </Text>
        </TouchableOpacity>
      </View>

      {/* 当前步骤信息 */}
      <View style={styles.infoBox}>
        <Text style={styles.infoTitle}>当前步骤:</Text>
        <Text style={styles.infoText}>
          {steps[currentStep].title} - {steps[currentStep].description || '无描述'}
        </Text>
        <Text style={styles.infoText}>
          进度:{currentStep + 1} / {steps.length}
        </Text>
      </View>
    </SafeAreaView>
  );
};

const RNHarmonyStepsPerfectAdapt = () => {
  return <StepsScreen />;
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F2F3F5',
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: '700',
    color: '#1a1a1a',
    textAlign: 'center',
    marginTop: 20,
  },
  subtitle: {
    fontSize: 18,
    fontWeight: '500',
    color: '#666',
    textAlign: 'center',
    marginTop: 8,
    marginBottom: 20,
  },

  // ======== 控制按钮组 ========
  controlGroup: {
    marginBottom: 20,
  },
  controlBtn: {
    backgroundColor: '#007DFF',
    borderRadius: 12,
    height: 50,
    justifyContent: 'center',
    alignItems: 'center',
  },
  controlBtnText: {
    fontSize: 16,
    color: '#fff',
    fontWeight: '600',
  },

  // ======== 步骤条容器 ========
  stepsContainer: {
    backgroundColor: '#fff',
    borderRadius: 16,
    padding: 20,
    marginBottom: 20,
    minHeight: 200,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },

  // ======== 水平布局样式 ========
  horizontalStepsWrapper: {
    paddingHorizontal: 10,
  },
  horizontalStepItem: {
    alignItems: 'center',
    minWidth: 100,
  },
  horizontalStepNode: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 12,
  },
  stepCircle: {
    width: 36,
    height: 36,
    borderRadius: 18,
    borderWidth: 3,
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 2,
  },
  stepNumber: {
    fontSize: 16,
    fontWeight: '700',
  },
  stepIcon: {
    fontSize: 18,
    color: '#fff',
    fontWeight: '700',
  },
  horizontalConnector: {
    flex: 1,
    height: 3,
    minWidth: 40,
    marginLeft: 10,
  },
  horizontalStepText: {
    alignItems: 'center',
  },

  // ======== 垂直布局样式 ========
  verticalStepsWrapper: {
    paddingHorizontal: 10,
  },
  verticalStepItem: {
    marginBottom: 20,
  },
  verticalStepContent: {
    flexDirection: 'row',
    alignItems: 'flex-start',
  },
  verticalStepNode: {
    alignItems: 'center',
    marginRight: 16,
  },
  verticalConnector: {
    width: 3,
    flex: 1,
    marginTop: 10,
  },
  verticalStepText: {
    flex: 1,
    paddingTop: 6,
  },

  // ======== 步骤文字通用样式 ========
  stepTitle: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 4,
  },
  stepDescription: {
    fontSize: 14,
    color: '#666',
    lineHeight: 20,
  },

  // ======== 操作按钮组 ========
  buttonGroup: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    gap: 12,
    marginBottom: 20,
  },
  button: {
    flex: 1,
    height: 50,
    borderRadius: 12,
    justifyContent: 'center',
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  buttonText: {
    fontSize: 16,
    color: '#fff',
    fontWeight: '600',
  },
  prevButton: {
    backgroundColor: '#FF9800',
  },
  nextButton: {
    backgroundColor: '#4CAF50',
  },
  resetButton: {
    backgroundColor: '#607D8B',
  },
  disabledText: {
    color: '#999',
  },

  // ======== 说明框样式 ========
  infoBox: {
    backgroundColor: '#fff',
    borderRadius: 12,
    padding: 20,
    borderWidth: 1,
    borderColor: '#E5E6EB',
  },
  infoTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
    marginBottom: 12,
  },
  infoText: {
    fontSize: 14,
    color: '#666',
    lineHeight: 22,
    marginBottom: 6,
  },
});

export default RNHarmonyStepsPerfectAdapt;

在这里插入图片描述

三、OpenHarmony6.0 专属避坑指南

以下是鸿蒙 RN 开发中实现「Steps 步骤条」的所有真实高频踩坑点,按出现频率排序,问题现象贴合开发实际,解决方案均为「一行代码/简单配置」,所有方案均为鸿蒙端专属最优解,也是本次代码能做到零报错、完美适配的核心原因,零基础可直接套用,彻底规避所有步骤条相关的样式变形、动画失效、布局错位、卡顿、类型错误等问题,全部真机实测验证通过,无任何兼容问题:

问题现象 问题原因 鸿蒙端最优解决方案
步骤条的水平布局在鸿蒙端显示错位,步骤节点重叠 水平布局未使用ScrollView包裹,或未设置horizontal属性,导致步骤节点无法横向滚动 ✅ 使用ScrollView设置horizontal={true},并设置showsHorizontalScrollIndicator={false}隐藏滚动条,本次代码已完美实现
步骤条的连接线在鸿蒙端不显示或显示异常 连接线未设置flex: 1minWidth,导致连接线宽度为 0,无法显示 ✅ 给连接线设置flex: 1minWidth: 40,确保连接线有足够宽度,本次代码已完美处理
步骤节点的缩放动画在鸿蒙端报错:transform属性不支持 RN的transform必须配合useNativeDriver: true使用,否则动画无法生效 ✅ 开启原生驱动useNativeDriver: true,鸿蒙端完美支持scale动画,本次代码已完美实现
步骤条的文字颜色在鸿蒙端显示异常 文字颜色未根据步骤状态动态设置,导致已完成、进行中、待处理的文字颜色相同 ✅ 使用getStepStyle函数根据步骤状态动态设置文字颜色,本次代码已完美处理
步骤条的圆角在鸿蒙端显示异常 步骤节点的圆角未设置或设置不正确,导致圆角显示为直角 ✅ 给步骤节点设置borderRadius: 18(圆圈直径的一半),确保圆角为完美圆形,本次代码已完美处理
步骤条的间距在鸿蒙端失效 步骤节点之间的间距未设置或设置不正确,导致步骤节点紧贴在一起 ✅ 给步骤节点设置marginRightmarginBottom,确保步骤节点之间有合适的间距,本次代码已完美处理
步骤条的阴影在鸿蒙端不显示 iOS 使用shadow*属性,Android/鸿蒙使用elevation属性,两者不互通 ✅ 同时设置 iOS 阴影属性(shadowColorshadowOffsetshadowOpacityshadowRadius)和鸿蒙elevation属性,本次代码已完美兼容
步骤条的动画在鸿蒙端卡顿 动画时长过短或过长,或动画曲线不合适,导致动画不流畅 ✅ 使用Animated.spring实现弹性动画,设置合适的frictiontension参数,鸿蒙端动画渲染最流畅,本次代码已完美实现
步骤条的点击事件无响应 按钮的TouchableOpacity未设置disabled样式,导致禁用状态下点击反馈不明显 ✅ 给禁用的按钮设置disabled样式和文字颜色,本次代码已完美实现
步骤条的垂直布局在鸿蒙端显示错位 垂直布局的连接线未设置flex: 1marginTop,导致连接线位置不正确 ✅ 给垂直连接线设置flex: 1marginTop: 10,确保连接线正确显示在节点下方,本次代码已完美处理

四、扩展用法:步骤条高频进阶优化(纯原生 无依赖 鸿蒙适配)

基于本次的核心步骤条代码,结合RN的内置能力,可轻松实现鸿蒙端开发中所有高频的步骤条进阶需求,全部为纯原生API实现,无需引入任何第三方库,零基础只需在本次代码基础上做简单修改即可实现,实用性拉满,全部真机实测通过,无任何兼容问题,满足企业级高阶需求:

✔️ 扩展1:带错误状态的步骤条

适配「表单验证、审核失败」等场景,在步骤条中显示错误状态,只需修改getStepStatus函数,添加错误状态判断,无需改动核心逻辑,一行代码实现,鸿蒙端完美兼容:

// 添加错误步骤索引
const [errorStep, setErrorStep] = useState<number>(-1);

// 修改步骤状态获取函数
const getStepStatus = (index: number): StepStatus => {
  if (index === errorStep) return 'error';
  if (index < currentStep) return 'finish';
  if (index === currentStep) return 'process';
  return 'pending';
};

// 触发错误状态
setErrorStep(2); // 设置第 3 步为错误状态

✔️ 扩展2:自定义步骤图标

适配不同的业务场景,可通过修改步骤节点的渲染逻辑,自定义不同状态的图标,无需改动核心逻辑,一行代码实现,鸿蒙端完美兼容:

// 定义图标映射
const stepIcons = {
  1: '📝', // 填写信息
  2: '📤', // 上传资料
  3: '⏳', // 审核中
  4: '✅', // 完成
};

// 在步骤节点中使用自定义图标
<Animated.View style={[styles.stepCircle, { ... }]}>
  {status === 'finish' ? (
    <Text style={styles.stepIcon}>{stepIcons[step.id] || '✓'}</Text>
  ) : (
    <Text style={[styles.stepNumber, { color: status === 'pending' ? '#999' : '#fff' }]}>
      {stepIcons[step.id] || index + 1}
    </Text>
  )}
</Animated.View>

✔️ 扩展3:带进度条的步骤条

适配「需要显示具体进度」的场景,在步骤条中添加进度条,无需改动核心逻辑,一行代码实现,鸿蒙端完美兼容:

// 添加进度条组件
const StepProgressBar: React.FC<{ current: number; total: number }> = ({ current, total }) => {
  const progress = ((current + 1) / total) * 100;
  return (
    <View style={styles.progressBar}>
      <View style={[styles.progressFill, { width: `${progress}%` }]} />
      <Text style={styles.progressText}>{Math.round(progress)}%</Text>
    </View>
  );
};

// 添加进度条样式
progressBar: {
  height: 8,
  backgroundColor: '#E5E6EB',
  borderRadius: 4,
  marginBottom: 20,
  overflow: 'hidden',
  position: 'relative',
},
progressFill: {
  height: '100%',
  backgroundColor: '#007DFF',
  borderRadius: 4,
},
progressText: {
  position: 'absolute',
  right: 10,
  top: -20,
  fontSize: 12,
  color: '#666',
  fontWeight: '600',
}

✔️ 扩展4:可点击跳转的步骤条

适配「用户可以点击任意步骤跳转」的场景,给步骤节点添加点击事件,无需改动核心逻辑,一行代码实现,鸿蒙端完美兼容:

// 修改步骤节点组件,添加点击事件
const HorizontalStepItem: React.FC<{ step: StepData; index: number; isLast: boolean }> = ({
  step,
  index,
  isLast,
}) => {
  // ... 其他代码

  return (
    <TouchableOpacity
      style={styles.horizontalStepItem}
      onPress={() => setCurrentStep(index)}
      activeOpacity={0.7}
    >
      {/* ... 步骤节点内容 */}
    </TouchableOpacity>
  );
};

✔️ 扩展5:带动画过渡的步骤内容

适配「步骤切换时显示不同内容」的场景,在步骤切换时显示对应的步骤内容,无需改动核心逻辑,一行代码实现,鸿蒙端完美兼容:

// 添加步骤内容数据
const stepContents = [
  '请填写您的个人信息',
  '请上传您的身份证照片',
  '系统正在审核您的资料',
  '恭喜您,操作已完成',
];

// 在步骤条下方显示当前步骤内容
<View style={styles.stepContentBox}>
  <Animated.Text
    style={[
      styles.stepContentText,
      {
        opacity: fadeAnim,
        transform: [{ translateY: slideAnim }],
      },
    ]}
  >
    {stepContents[currentStep]}
  </Animated.Text>
</View>

// 添加步骤内容样式
stepContentBox: {
  backgroundColor: '#E3F2FD',
  borderRadius: 12,
  padding: 20,
  marginTop: 20,
  minHeight: 80,
  justifyContent: 'center',
  alignItems: 'center',
},
stepContentText: {
  fontSize: 16,
  color: '#007DFF',
  fontWeight: '600',
  textAlign: 'center',
}

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

Logo

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

更多推荐