ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-shimmer-placeholder — 骨架屏组件

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
📌 开发环境声明:本文基于 React Native 0.72.90 版本进行开发适配


🚀 一、开篇引言

骨架屏(Skeleton Screen)是一种优秀的加载占位方案,在内容加载完成前显示灰色的占位区块,给用户一种内容即将呈现的预期,相比传统的加载转圈,骨架屏能提供更好的用户体验。react-native-shimmer-placeholder 是 React Native 社区中流行的骨架屏组件,支持闪烁动画效果,可以与渐变组件配合使用,实现更加精美的加载占位效果。本文将带你深入了解如何在 HarmonyOS 平台上集成和使用这个实用的 UI 组件。

1.1 你将学到什么?

  • ✅ ShimmerPlaceholder 的核心概念与工作原理
  • ✅ HarmonyOS 平台的完整集成流程
  • ✅ 基础骨架屏与闪烁效果
  • ✅ API 属性的深度解析
  • ✅ 实际应用场景的最佳实践

1.2 适用人群

  • 正在进行 React Native 鸿蒙化迁移的开发者
  • 需要优化加载体验的开发者
  • 对跨平台 UI 组件开发感兴趣的技术爱好者

1.3 为什么选择 ShimmerPlaceholder?

特点 说明
优雅加载 提供内容即将加载的视觉预期
闪烁动画 流畅的闪烁效果提升用户体验
跨平台一致 iOS、Android、HarmonyOS 表现一致
灵活配置 支持自定义样式、颜色、动画参数
渐变支持 可与 LinearGradient 配合使用

📦 二、库概览

2.1 基本信息

项目 内容
库名称 react-native-shimmer-placeholder
版本信息 2.0.9
官方仓库 https://github.com/tomzaku/react-native-shimmer-placeholder
开源协议 MIT

2.2 版本兼容性

三方库版本 支持RN版本
2.0.9 0.72 / 0.77

2.3 依赖说明

⚠️ 重要 :本库依赖 react-native-linear-gradient,需要先完成该库的配置。

可以先看这篇文章进行适配:https://blog.csdn.net/Easonmax/article/details/159132315

依赖库 版本 说明
react-native-linear-gradient 3.0.0-0.4.5 用于实现渐变闪烁效果

2.4 核心能力矩阵

能力项 描述 HarmonyOS 支持
骨架占位 ShimmerPlaceholder ✅ 完全支持
闪烁动画 shimmer 动画 ✅ 完全支持
渐变效果 LinearGradient ✅ 完全支持
可见状态切换 visible 属性 ✅ 完全支持
自定义样式 shimmerStyle ✅ 完全支持
动画控制 stopAutoRun ✅ 完全支持

2.5 技术架构图

平台层
动画层
React Native 应用层
ShimmerPlaceholder
createShimmerPlaceholder
LinearGradient 渐变
Animated API
闪烁动画
渐变移动
Android
iOS
HarmonyOS

2.6 典型应用场景

场景 描述 示例
列表加载 列表项占位 📋 新闻列表、商品列表
卡片加载 卡片内容占位 🃏 商品卡片、文章卡片
用户信息 头像和信息占位 👤 个人主页、评论列表
图片加载 图片占位 🖼️ 图片列表、相册

📖 三、安装与配置

3.1 安装依赖

首先确保已安装 react-native-linear-gradient,然后安装本库:

bash 复制代码
npm install react-native-shimmer-placeholder@2.0.9

或使用 yarn:

bash 复制代码
yarn add react-native-shimmer-placeholder@2.0.9

3.2 验证安装

安装完成后,检查 package.json 文件中是否包含以下依赖:

json 复制代码
{
  "dependencies": {
    "react-native-shimmer-placeholder": "2.0.9",
    "react-native-linear-gradient": "^3.0.0-0.4.5"
  }
}

3.3 基本导入

tsx 复制代码
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

📖 四、API 详解

4.1 createShimmerPlaceholder 函数

创建骨架屏组件的工厂函数,需要传入渐变组件。

签名:

typescript 复制代码
createShimmerPlaceholder(LinearGradient: ComponentType): ComponentType

用法:

tsx 复制代码
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

4.2 属性详解

visible - 可见状态

控制是否显示真实内容,false 时显示骨架屏。

类型: boolean

默认值: false

tsx 复制代码
const [visible, setVisible] = useState(false);

<ShimmerPlaceholder visible={visible}>
  <Text>真实内容</Text>
</ShimmerPlaceholder>
width - 宽度

骨架屏的宽度。

类型: number

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} />
height - 高度

骨架屏的高度。

类型: number

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} />
shimmerStyle - 闪烁样式

骨架屏的样式。

类型: ViewStyle

tsx 复制代码
<ShimmerPlaceholder
  width={100}
  height={100}
  shimmerStyle={{ borderRadius: 50 }}
/>
shimmerColors - 闪烁颜色

闪烁动画的颜色数组。

类型: string[]

默认值: ['#f0f0f0', '#e0e0e0', '#f0f0f0']

tsx 复制代码
<ShimmerPlaceholder
  width={200}
  height={20}
  shimmerColors={['#e0e0e0', '#c0c0c0', '#e0e0e0']}
/>
duration - 动画持续时间

闪烁动画的持续时间(毫秒)。

类型: number

默认值: 1000

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} duration={1500} />
shimmerWidthPercent - 闪烁宽度百分比

闪烁区域的宽度百分比。

类型: number

默认值: 1

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} shimmerWidthPercent={0.5} />
location - 闪烁位置

闪烁渐变的位置数组。

类型: number[]

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} location={[0.3, 0.5, 0.7]} />
isReversed - 反向动画

是否反向播放闪烁动画。

类型: boolean

默认值: false

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} isReversed={true} />
stopAutoRun - 停止自动运行

是否在挂载时停止闪烁动画。

类型: boolean

默认值: false

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} stopAutoRun={true} />
isInteraction - 交互句柄

是否在 InteractionManager 上创建交互句柄。

类型: boolean

默认值: false

tsx 复制代码
<ShimmerPlaceholder width={200} height={20} isInteraction={true} />
style - 容器样式

外层容器的样式。

类型: ViewStyle

tsx 复制代码
<ShimmerPlaceholder
  width={200}
  height={20}
  style={{ marginBottom: 10 }}
/>
contentStyle - 内容样式

可见时内容的样式。

类型: ViewStyle

tsx 复制代码
<ShimmerPlaceholder
  visible={true}
  contentStyle={{ backgroundColor: '#fff' }}
>
  <Text>内容</Text>
</ShimmerPlaceholder>

4.3 静态方法

getAnimated() - 获取动画对象

获取骨架屏的 Animated 对象,用于自定义动画控制。

返回值: Animated.Value

tsx 复制代码
const shimmerRef = useRef<any>(null);
const animatedValue = shimmerRef.current?.getAnimated();

💡 五、使用示例

5.1 基础骨架屏

最简单的使用方式,显示占位效果。

适用场景: 简单的加载占位。

tsx 复制代码
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

const BasicShimmer = () => {
  return (
    <View style={styles.container}>
      <ShimmerPlaceholder width={200} height={20} style={styles.item} />
      <ShimmerPlaceholder width={150} height={20} style={styles.item} />
      <ShimmerPlaceholder width={180} height={20} style={styles.item} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  item: {
    marginBottom: 15,
    borderRadius: 4,
  },
});

export default BasicShimmer;

代码解析:

  • createShimmerPlaceholder 创建组件
  • widthheight 设置占位尺寸
  • 自动显示闪烁动画

5.2 图片加载占位

图片加载完成前显示骨架屏。

适用场景: 图片列表、头像加载。

tsx 复制代码
import React, { useState, useRef } from 'react';
import { View, Image, StyleSheet } from 'react-native';
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

const ImageWithShimmer = () => {
  const [visible, setVisible] = useState(false);

  return (
    <View style={styles.container}>
      <ShimmerPlaceholder
        width={200}
        height={200}
        visible={visible}
        shimmerStyle={{ borderRadius: 12 }}
      >
        <Image
          source={{ uri: 'https://picsum.photos/200/200' }}
          style={styles.image}
          onLoadEnd={() => setVisible(true)}
        />
      </ShimmerPlaceholder>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5',
  },
  image: {
    width: 200,
    height: 200,
    borderRadius: 12,
  },
});

export default ImageWithShimmer;

代码解析:

  • visible={false} 显示骨架屏
  • onLoadEnd 图片加载完成后设置 visible={true}
  • shimmerStyle 设置骨架屏圆角

5.3 列表项骨架屏

模拟列表项的骨架屏效果。

适用场景: 列表加载占位。

tsx 复制代码
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, FlatList } from 'react-native';
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

const ListItemSkeleton = () => (
  <View style={styles.item}>
    <ShimmerPlaceholder
      width={60}
      height={60}
      shimmerStyle={{ borderRadius: 30 }}
    />
    <View style={styles.content}>
      <ShimmerPlaceholder width={150} height={16} style={styles.titleLine} />
      <ShimmerPlaceholder width={200} height={14} style={styles.descLine} />
      <ShimmerPlaceholder width={100} height={12} />
    </View>
  </View>
);

const ListItem = ({ item }: { item: any }) => (
  <View style={styles.item}>
    <View style={styles.avatar} />
    <View style={styles.content}>
      <Text style={styles.title}>{item.title}</Text>
      <Text style={styles.desc}>{item.desc}</Text>
      <Text style={styles.time}>{item.time}</Text>
    </View>
  </View>
);

const ListShimmer = () => {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    setTimeout(() => {
      setData([
        { id: 1, title: '标题一', desc: '描述内容描述内容', time: '2分钟前' },
        { id: 2, title: '标题二', desc: '描述内容描述内容', time: '5分钟前' },
        { id: 3, title: '标题三', desc: '描述内容描述内容', time: '10分钟前' },
      ]);
      setLoading(false);
    }, 2000);
  }, []);

  if (loading) {
    return (
      <View style={styles.container}>
        {[1, 2, 3].map((i) => (
          <ListItemSkeleton key={i} />
        ))}
      </View>
    );
  }

  return (
    <View style={styles.container}>
      {data.map((item: any) => (
        <ListItem key={item.id} item={item} />
      ))}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    padding: 16,
  },
  item: {
    flexDirection: 'row',
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0',
  },
  avatar: {
    width: 60,
    height: 60,
    borderRadius: 30,
    backgroundColor: '#007AFF',
  },
  content: {
    marginLeft: 12,
    flex: 1,
  },
  titleLine: {
    marginBottom: 8,
    borderRadius: 4,
  },
  descLine: {
    marginBottom: 6,
    borderRadius: 4,
  },
  title: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
  },
  desc: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  time: {
    fontSize: 12,
    color: '#999',
    marginTop: 4,
  },
});

export default ListShimmer;

代码解析:

  • 创建 ListItemSkeleton 组件模拟列表项结构
  • 加载完成后切换到真实列表
  • 使用 setTimeout 模拟网络请求

5.4 自定义颜色和动画

自定义骨架屏的颜色和动画参数。

适用场景: 深色主题、品牌色定制。

tsx 复制代码
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

const CustomShimmer = () => {
  return (
    <View style={styles.container}>
      <ShimmerPlaceholder
        width={200}
        height={20}
        shimmerColors={['#2a2a3e', '#3a3a5e', '#2a2a3e']}
        duration={800}
        shimmerWidthPercent={0.6}
        style={styles.item}
      />
      <ShimmerPlaceholder
        width={150}
        height={20}
        shimmerColors={['#2a2a3e', '#3a3a5e', '#2a2a3e']}
        duration={1200}
        isReversed
        style={styles.item}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#1a1a2e',
    justifyContent: 'center',
    alignItems: 'center',
  },
  item: {
    marginBottom: 15,
    borderRadius: 4,
  },
});

export default CustomShimmer;

代码解析:

  • shimmerColors 自定义闪烁颜色
  • duration 调整动画速度
  • isReversed 反向动画

❓ 八、常见问题

8.1 遗留问题

⚠️ 重要提示:当前版本在 HarmonyOS 平台上暂无已知遗留问题。


8.2 常见问题解答

Q1: 为什么闪烁效果不显示?

A: 确保已正确配置 react-native-linear-gradient 依赖。

Q2: 如何实现圆角骨架屏?

A: 使用 shimmerStyle={``{ borderRadius: 8 }} 设置圆角。

Q3: 如何停止闪烁动画?

A: 设置 stopAutoRun={true} 或调用 getAnimated() 手动控制。

Q4: 支持哪些渐变组件?

A: 支持 react-native-linear-gradientexpo-linear-gradient

8.3 最佳实践

  1. 结构匹配:骨架屏结构应与真实内容结构相似
  2. 动画速度duration 设置在 800-1500ms 效果较好
  3. 颜色搭配:骨架屏颜色应与应用主题协调
  4. 及时切换 :内容加载完成后立即切换 visible 状态

💻 九、完整示例代码

综合示例

本示例整合了前面所有章节的功能点,包括:基础骨架屏、图片加载占位、列表项骨架屏、自定义颜色动画、可见状态切换等。

ts 复制代码
import React, { useState, useEffect, useRef } from 'react';
import {
  View,
  Text,
  StyleSheet,
  SafeAreaView,
  ScrollView,
  TouchableOpacity,
  Image,
  FlatList,
  RefreshControl,
} from 'react-native';
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';

const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);

const BasicShimmerDemo = () => {
  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>5.1 基础骨架屏</Text>
      <View style={styles.basicContainer}>
        <ShimmerPlaceholder width={200} height={20} style={styles.shimmerItem} />
        <ShimmerPlaceholder width={150} height={20} style={styles.shimmerItem} />
        <ShimmerPlaceholder width={180} height={20} style={styles.shimmerItem} />
      </View>
    </View>
  );
};

const ImageShimmerDemo = () => {
  const [imageVisible, setImageVisible] = useState(false);

  useEffect(() => {
    const timer = setTimeout(() => setImageVisible(true), 2000);
    return () => clearTimeout(timer);
  }, []);

  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>5.2 图片加载占位</Text>
      <View style={styles.imageContainer}>
        <ShimmerPlaceholder
          width={200}
          height={200}
          visible={imageVisible}
          shimmerStyle={{ borderRadius: 12 }}
        >
          <Image
            source={{ uri: 'https://picsum.photos/200/200' }}
            style={styles.demoImage}
          />
        </ShimmerPlaceholder>
        <TouchableOpacity
          style={styles.reloadButton}
          onPress={() => setImageVisible(false)}
        >
          <Text style={styles.reloadText}>重新加载</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

const ListShimmerItem = () => (
  <View style={styles.listItem}>
    <ShimmerPlaceholder
      width={60}
      height={60}
      shimmerStyle={{ borderRadius: 30 }}
    />
    <View style={styles.listContent}>
      <ShimmerPlaceholder width={150} height={16} style={styles.shimmerLine} />
      <ShimmerPlaceholder width={200} height={14} style={styles.shimmerLine} />
      <ShimmerPlaceholder width={100} height={12} />
    </View>
  </View>
);

const ListShimmerDemo = ({ data, loading }: { data: any[]; loading: boolean }) => {
  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>5.3 列表项骨架屏</Text>
      {loading ? (
        <>
          <ListShimmerItem />
          <ListShimmerItem />
          <ListShimmerItem />
        </>
      ) : (
        data.map((item: any) => (
          <View key={item.id} style={styles.listItem}>
            <Image source={{ uri: item.avatar }} style={styles.avatar} />
            <View style={styles.listContent}>
              <Text style={styles.listTitle}>{item.name}</Text>
              <Text style={styles.listDesc}>{item.desc}</Text>
              <Text style={styles.listTime}>{item.time}</Text>
            </View>
          </View>
        ))
      )}
    </View>
  );
};

const CustomShimmerDemo = () => {
  const [stopAnimation, setStopAnimation] = useState(false);

  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>5.4 自定义颜色和动画</Text>
      <View style={styles.customContainer}>
        <ShimmerPlaceholder
          width={200}
          height={20}
          shimmerColors={['#2a2a3e', '#3a3a5e', '#2a2a3e']}
          duration={800}
          shimmerWidthPercent={0.6}
          stopAutoRun={stopAnimation}
          style={styles.shimmerItem}
        />
        <ShimmerPlaceholder
          width={150}
          height={20}
          shimmerColors={['#1a3a5e', '#2a4a6e', '#1a3a5e']}
          duration={1200}
          isReversed
          stopAutoRun={stopAnimation}
          style={styles.shimmerItem}
        />
        <View style={styles.controlRow}>
          <TouchableOpacity
            style={styles.controlButton}
            onPress={() => setStopAnimation(true)}
          >
            <Text style={styles.controlText}>停止动画</Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={styles.controlButton}
            onPress={() => setStopAnimation(false)}
          >
            <Text style={styles.controlText}>开始动画</Text>
          </TouchableOpacity>
        </View>
      </View>
    </View>
  );
};

const generateListData = () => [
  { id: 1, name: '用户昵称一', desc: '这是第一条评论内容', time: '2分钟前', avatar: 'https://picsum.photos/60/60?random=1' },
  { id: 2, name: '用户昵称二', desc: '这是第二条评论内容', time: '5分钟前', avatar: 'https://picsum.photos/60/60?random=2' },
  { id: 3, name: '用户昵称三', desc: '这是第三条评论内容', time: '10分钟前', avatar: 'https://picsum.photos/60/60?random=3' },
  { id: 4, name: '用户昵称四', desc: '这是第四条评论内容', time: '15分钟前', avatar: 'https://picsum.photos/60/60?random=4' },
  { id: 5, name: '用户昵称五', desc: '这是第五条评论内容', time: '20分钟前', avatar: 'https://picsum.photos/60/60?random=5' },
];

export default function App() {
  const [loading, setLoading] = useState(true);
  const [listData, setListData] = useState<any[]>([]);
  const [refreshing, setRefreshing] = useState(false);

  useEffect(() => {
    loadData();
  }, []);

  const loadData = () => {
    setLoading(true);
    setTimeout(() => {
      setListData(generateListData());
      setLoading(false);
    }, 2500);
  };

  const handleRefresh = () => {
    setRefreshing(true);
    setTimeout(() => {
      setListData(generateListData());
      setRefreshing(false);
    }, 2500);
  };

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView
        contentContainerStyle={styles.content}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={handleRefresh} />
        }
      >
        <Text style={styles.title}>骨架屏组件综合示例</Text>
        <Text style={styles.subtitle}>
          本示例展示 ShimmerPlaceholder 的所有核心功能
        </Text>

        <BasicShimmerDemo />
        <ImageShimmerDemo />
        <CustomShimmerDemo />
        
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>5.3 列表项骨架屏(可刷新)</Text>
          <ListShimmerDemo data={listData} loading={loading} />
          <TouchableOpacity style={styles.refreshButton} onPress={loadData}>
            <Text style={styles.refreshButtonText}>重新加载列表</Text>
          </TouchableOpacity>
        </View>

        <View style={styles.infoSection}>
          <Text style={styles.infoTitle}>功能说明</Text>
          <Text style={styles.infoText}>• 5.1 基础骨架屏:最基本的占位效果</Text>
          <Text style={styles.infoText}>• 5.2 图片加载:图片加载完成前显示占位</Text>
          <Text style={styles.infoText}>• 5.3 列表骨架:模拟列表项加载状态</Text>
          <Text style={styles.infoText}>• 5.4 自定义:自定义颜色、动画方向和速度</Text>
          <Text style={styles.infoText}>• 下拉刷新:支持 Pull-to-Refresh</Text>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  content: {
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
    textAlign: 'center',
  },
  subtitle: {
    fontSize: 14,
    color: '#666',
    textAlign: 'center',
    marginTop: 8,
    marginBottom: 24,
  },
  section: {
    backgroundColor: '#fff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
    marginBottom: 12,
  },
  basicContainer: {
    padding: 8,
  },
  shimmerItem: {
    marginBottom: 12,
    borderRadius: 4,
  },
  shimmerLine: {
    marginBottom: 8,
    borderRadius: 4,
  },
  imageContainer: {
    alignItems: 'center',
  },
  demoImage: {
    width: 200,
    height: 200,
    borderRadius: 12,
  },
  reloadButton: {
    marginTop: 12,
    paddingVertical: 8,
    paddingHorizontal: 16,
    backgroundColor: '#007AFF',
    borderRadius: 6,
  },
  reloadText: {
    color: '#fff',
    fontSize: 14,
  },
  customContainer: {
    padding: 8,
    backgroundColor: '#1a1a2e',
    borderRadius: 8,
  },
  controlRow: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginTop: 16,
  },
  controlButton: {
    paddingVertical: 8,
    paddingHorizontal: 16,
    backgroundColor: '#3a3a5e',
    borderRadius: 6,
  },
  controlText: {
    color: '#fff',
    fontSize: 14,
  },
  listItem: {
    flexDirection: 'row',
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0',
  },
  avatar: {
    width: 60,
    height: 60,
    borderRadius: 30,
  },
  listContent: {
    marginLeft: 12,
    flex: 1,
    justifyContent: 'center',
  },
  listTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
  },
  listDesc: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  listTime: {
    fontSize: 12,
    color: '#999',
    marginTop: 4,
  },
  refreshButton: {
    backgroundColor: '#007AFF',
    padding: 14,
    borderRadius: 8,
    alignItems: 'center',
    marginTop: 16,
  },
  refreshButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  infoSection: {
    backgroundColor: '#e8f4ff',
    borderRadius: 12,
    padding: 16,
    marginTop: 8,
  },
  infoTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#007AFF',
    marginBottom: 8,
  },
  infoText: {
    fontSize: 14,
    color: '#333',
    lineHeight: 22,
  },
});

🔗 十、相关资源

相关推荐
芙莉莲教你写代码2 小时前
Flutter 框架跨平台鸿蒙开发 - 单位换算大师应用
flutter·华为·harmonyos
不爱吃糖的程序媛3 小时前
Flutter应用运行到鸿蒙PC指南
flutter·华为·harmonyos
不爱吃糖的程序媛3 小时前
Flutter OH Engine 构建指导(macOS 版本)
flutter·华为·harmonyos
芙莉莲教你写代码3 小时前
Flutter 框架跨平台鸿蒙开发 - 历史知识问答应用
flutter·华为·harmonyos
代码飞天13 小时前
harmonyOS开发基础之标题栏(HdsNavigation)
华为·harmonyos
2501_9206276116 小时前
Flutter 框架跨平台鸿蒙开发 - 派对策划助手应用
flutter·华为·harmonyos
沙雕不是雕又菜又爱玩17 小时前
基于HarmonyOS的笔记管理应用
harmonyos
@不误正业17 小时前
AI Agent多轮对话管理:3大架构源码级实现与性能对比(附鸿蒙实战)
人工智能·架构·harmonyos
里欧跑得慢17 小时前
Flutter 组件 powersync_core 的适配 鸿蒙Harmony 实战 - 驾驭极致离线优先架构、实现鸿蒙端高性能 SQL 增量同步与数据安全治理方案
flutter·harmonyos·鸿蒙·openharmony·powersync_core