✨ 本文配套实战项目地址: https://openharmonycrossplatform.csdn.net/content

本文将带你深入探索 Flutter 的强大之处,通过完整的电商应用 UI 实例,掌握现代跨平台应用开发的核心技能

一、Flutter 简介与优势

1.1 什么是 Flutter?

Flutter 是 Google 推出的开源 UI 开发框架,使用 Dart 语言编写,可以快速在 iOS、Android、Web 和桌面平台上构建高质量的原生用户界面。

1.2 Flutter 的核心优势

  • 热重载:开发过程中实时查看更改效果

  • 高性能:直接编译为原生 ARM 代码

  • 丰富的组件库:提供 Material Design 和 Cupertino 风格的组件

  • 一次编写,多端运行:真正实现跨平台开发

二、环境搭建与项目创建

2.1 环境配置要求

bash

# 检查 Flutter 环境
flutter doctor

# 创建新项目
flutter create ecommerce_app

# 运行项目
cd ecommerce_app
flutter run

2.2 项目结构解析

text

lib/
├── main.dart          # 应用入口
├── models/           # 数据模型
├── pages/            # 页面组件
├── widgets/          # 自定义组件
├── services/         # 业务逻辑
└── utils/            # 工具类

三、电商应用 UI 实战开发

3.1 应用主页设计

下面是一个完整的电商主页实现:

dart

// 代码区域开始
import 'package:flutter/material.dart';
import 'package:iconsax/iconsax.dart';

void main() => runApp(const ECommerceApp());

class ECommerceApp extends StatelessWidget {
  const ECommerceApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter 电商',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.deepOrange,
        appBarTheme: const AppBarTheme(
          elevation: 0,
          backgroundColor: Colors.white,
          iconTheme: IconThemeData(color: Colors.black),
        ),
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _selectedIndex = 0;
  
  final List<Map<String, dynamic>> _products = [
    {
      'id': 1,
      'name': '无线蓝牙耳机',
      'price': 299.00,
      'image': '🎧',
      'category': '电子产品',
      'rating': 4.5,
      'isFavorite': true,
    },
    {
      'id': 2,
      'name': '运动智能手表',
      'price': 899.00,
      'image': '⌚',
      'category': '穿戴设备',
      'rating': 4.8,
      'isFavorite': false,
    },
    {
      'id': 3,
      'name': '便携充电宝',
      'price': 159.00,
      'image': '🔋',
      'category': '配件',
      'rating': 4.3,
      'isFavorite': true,
    },
    {
      'id': 4,
      'name': '机械键盘',
      'price': 499.00,
      'image': '⌨️',
      'category': '外设',
      'rating': 4.7,
      'isFavorite': false,
    },
  ];

  final List<Widget> _pages = [
    const HomeContent(),
    const SearchPage(),
    const CartPage(),
    const ProfilePage(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Flutter 电商',
          style: TextStyle(
            fontWeight: FontWeight.bold,
            color: Colors.black,
          ),
        ),
        actions: [
          IconButton(
            icon: const Icon(Iconsax.notification),
            onPressed: () {},
          ),
        ],
      ),
      body: _pages[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) {
          setState(() {
            _selectedIndex = index;
          });
        },
        type: BottomNavigationBarType.fixed,
        selectedItemColor: Colors.deepOrange,
        unselectedItemColor: Colors.grey,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Iconsax.home),
            label: '首页',
          ),
          BottomNavigationBarItem(
            icon: Icon(Iconsax.search_normal),
            label: '搜索',
          ),
          BottomNavigationBarItem(
            icon: Badge(
              label: Text('3'),
              child: Icon(Iconsax.shopping_cart),
            ),
            label: '购物车',
          ),
          BottomNavigationBarItem(
            icon: Icon(Iconsax.user),
            label: '我的',
          ),
        ],
      ),
    );
  }
}

class HomeContent extends StatelessWidget {
  const HomeContent({super.key});

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 搜索框
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            decoration: BoxDecoration(
              color: Colors.grey[100],
              borderRadius: BorderRadius.circular(25),
            ),
            child: const TextField(
              decoration: InputDecoration(
                border: InputBorder.none,
                hintText: '搜索商品...',
                icon: Icon(Iconsax.search_normal, color: Colors.grey),
              ),
            ),
          ),
          
          const SizedBox(height: 20),
          
          // 分类网格
          const Text(
            '商品分类',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 10),
          
          GridView.count(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            crossAxisCount: 4,
            childAspectRatio: 0.8,
            children: [
              _buildCategoryItem('📱', '手机'),
              _buildCategoryItem('💻', '电脑'),
              _buildCategoryItem('🎧', '耳机'),
              _buildCategoryItem('⌚', '手表'),
              _buildCategoryItem('🔋', '配件'),
              _buildCategoryItem('📷', '相机'),
              _buildCategoryItem('🎮', '游戏'),
              _buildCategoryItem('🏠', '家居'),
            ],
          ),
          
          const SizedBox(height: 20),
          
          // 商品列表
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                '热门商品',
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              ),
              TextButton(
                onPressed: () {},
                child: const Text('查看全部'),
              ),
            ],
          ),
          
          GridView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              crossAxisSpacing: 12,
              mainAxisSpacing: 12,
              childAspectRatio: 0.75,
            ),
            itemCount: 4,
            itemBuilder: (context, index) {
              return ProductCard(product: {
                'id': index + 1,
                'name': '商品 ${index + 1}',
                'price': (99.99 * (index + 1)).toStringAsFixed(2),
                'image': ['📱', '💻', '🎧', '⌚'][index],
                'rating': 4.0 + (index * 0.2),
              });
            },
          ),
        ],
      ),
    );
  }

  Widget _buildCategoryItem(String emoji, String label) {
    return Column(
      children: [
        CircleAvatar(
          backgroundColor: Colors.deepOrange.withOpacity(0.1),
          radius: 30,
          child: Text(emoji, style: const TextStyle(fontSize: 24)),
        ),
        const SizedBox(height: 8),
        Text(label, style: const TextStyle(fontSize: 12)),
      ],
    );
  }
}

class ProductCard extends StatelessWidget {
  final Map<String, dynamic> product;

  const ProductCard({super.key, required this.product});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.1),
            blurRadius: 10,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 商品图片
          Container(
            height: 120,
            decoration: BoxDecoration(
              color: Colors.grey[50],
              borderRadius: const BorderRadius.vertical(
                top: Radius.circular(12),
              ),
            ),
            child: Center(
              child: Text(
                product['image'],
                style: const TextStyle(fontSize: 48),
              ),
            ),
          ),
          
          Padding(
            padding: const EdgeInsets.all(12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // 商品名称
                Text(
                  product['name'],
                  style: const TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 14,
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
                
                const SizedBox(height: 4),
                
                // 价格
                Text(
                  '¥${product['price']}',
                  style: const TextStyle(
                    color: Colors.deepOrange,
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                
                const SizedBox(height: 8),
                
                // 评分和按钮
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    // 评分
                    Row(
                      children: [
                        const Icon(Icons.star, color: Colors.amber, size: 16),
                        const SizedBox(width: 4),
                        Text(
                          '${product['rating']}',
                          style: const TextStyle(fontSize: 12),
                        ),
                      ],
                    ),
                    
                    // 购物车按钮
                    Container(
                      width: 32,
                      height: 32,
                      decoration: BoxDecoration(
                        color: Colors.deepOrange,
                        borderRadius: BorderRadius.circular(8),
                      ),
                      child: const Icon(
                        Iconsax.shopping_cart,
                        color: Colors.white,
                        size: 16,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

// 其他页面占位
class SearchPage extends StatelessWidget {
  const SearchPage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('搜索页面'));
  }
}

class CartPage extends StatelessWidget {
  const CartPage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('购物车页面'));
  }
}

class ProfilePage extends StatelessWidget {
  const ProfilePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('个人中心'));
  }
}
// 代码区域结束

3.2 商品详情页实现

dart

// 代码区域开始
class ProductDetailPage extends StatelessWidget {
  final Map<String, dynamic> product;

  const ProductDetailPage({super.key, required this.product});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            expandedHeight: 300,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
              background: Container(
                color: Colors.grey[50],
                child: Center(
                  child: Text(
                    product['image'],
                    style: const TextStyle(fontSize: 100),
                  ),
                ),
              ),
            ),
          ),
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    product['name'],
                    style: const TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    '¥${product['price']}',
                    style: const TextStyle(
                      fontSize: 28,
                      color: Colors.deepOrange,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 16),
                  const Text(
                    '商品描述',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 8),
                  const Text(
                    '这是一款高品质的商品,采用先进技术制造,'
                    '具有卓越的性能和耐用性,为用户提供最佳的使用体验。',
                    style: TextStyle(color: Colors.grey, height: 1.5),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
      bottomNavigationBar: Container(
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.grey.withOpacity(0.1),
              blurRadius: 10,
              offset: const Offset(0, -2),
            ),
          ],
        ),
        child: Row(
          children: [
            // 收藏按钮
            Container(
              width: 50,
              height: 50,
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey[300]!),
                borderRadius: BorderRadius.circular(12),
              ),
              child: const Icon(Iconsax.heart, color: Colors.grey),
            ),
            const SizedBox(width: 12),
            // 加入购物车按钮
            Expanded(
              child: Container(
                height: 50,
                decoration: BoxDecoration(
                  color: Colors.orange.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(12),
                ),
                child: const Center(
                  child: Text(
                    '加入购物车',
                    style: TextStyle(
                      color: Colors.orange,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ),
            ),
            const SizedBox(width: 12),
            // 立即购买按钮
            Expanded(
              child: Container(
                height: 50,
                decoration: BoxDecoration(
                  color: Colors.deepOrange,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: const Center(
                  child: Text(
                    '立即购买',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
// 代码区域结束

四、Flutter 核心概念解析

4.1 Widget 树结构

dart

// Widget 是 Flutter 应用的基础构建块
Widget build(BuildContext context) {
  return Container(          // 容器 Widget
    color: Colors.white,
    child: Column(          // 列布局 Widget
      children: [
        Text('标题'),        // 文本 Widget
        Image.network(),    // 图片 Widget
        ElevatedButton(     // 按钮 Widget
          onPressed: () {}, // 点击事件
          child: Text('按钮'),
        ),
      ],
    ),
  );
}

4.2 State 状态管理

dart

// 有状态 Widget 示例
class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {  // 调用 setState 触发 UI 更新
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('计数: $_counter'),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('增加'),
        ),
      ],
    );
  }
}

五、性能优化技巧

5.1 使用 Const 构造函数

dart

// 优化前
Widget build(BuildContext context) {
  return Padding(
    padding: EdgeInsets.all(8.0),
    child: Text(
      '文本内容',
      style: TextStyle(fontSize: 14),
    ),
  );
}

// 优化后
Widget build(BuildContext context) {
  return const Padding(
    padding: EdgeInsets.all(8.0),
    child: Text(
      '文本内容',
      style: TextStyle(fontSize: 14),
    ),
  );
}

5.2 列表性能优化

dart

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
    );
  },
);

六、与物联网(IoT)开发结合

在我之前写的《Flutter物联网(IoT)开发实战指南》中提到,Flutter 可以很好地与 IoT 设备进行交互。以下是一个简单的 IoT 设备控制界面示例:

dart

// IoT 设备控制卡片
class IoTDeviceCard extends StatelessWidget {
  final String deviceName;
  final bool isOnline;
  final bool isActive;
  final VoidCallback onToggle;

  const IoTDeviceCard({
    super.key,
    required this.deviceName,
    required this.isOnline,
    required this.isActive,
    required this.onToggle,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        leading: Icon(
          isOnline ? Icons.wifi : Icons.wifi_off,
          color: isOnline ? Colors.green : Colors.grey,
        ),
        title: Text(deviceName),
        subtitle: Text(isOnline ? '在线' : '离线'),
        trailing: Switch(
          value: isActive,
          onChanged: isOnline ? (_) => onToggle() : null,
        ),
      ),
    );
  }
}

七、项目实战建议

7.1 项目结构规范

text

lib/
├── main.dart
├── app.dart
├── models/
│   ├── product.dart
│   └── user.dart
├── pages/
│   ├── home/
│   ├── product/
│   └── cart/
├── widgets/
│   ├── custom_app_bar.dart
│   └── product_card.dart
├── services/
│   ├── api_service.dart
│   └── auth_service.dart
└── utils/
    ├── constants.dart
    └── validators.dart

7.2 常用插件推荐

yaml

dependencies:
  flutter:
    sdk: flutter
  dio: ^5.0.0      # 网络请求
  provider: ^6.0.0 # 状态管理
  shared_preferences: ^2.0.0 # 本地存储
  url_launcher: ^6.0.0      # URL 跳转
  image_picker: ^0.8.0      # 图片选择
  fluttertoast: ^8.0.0      # Toast 提示

八、总结

Flutter 作为现代跨平台开发框架,具有以下优势:

  1. 开发效率高:热重载功能大大提升开发效率

  2. 性能优秀:接近原生应用的性能表现

  3. 生态丰富:拥有庞大的插件和社区支持

  4. 一致体验:在不同平台提供统一的用户体验

  5. 学习曲线平缓:Dart 语言简洁易懂

通过本文的电商应用实例,你可以看到 Flutter 如何快速构建美观、高性能的应用程序。无论是简单的 UI 界面还是复杂的业务逻辑,Flutter 都能提供强大的支持。

结合我之前介绍的 IoT 开发知识,你甚至可以用 Flutter 开发智能家居控制、工业监控等物联网应用,真正实现"一次编写,多端运行"的开发理想。

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐