You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

初学者求教:Flutter是否有类似Bootstrap的开源预构建组件库?

类似Bootstrap的Flutter开源UI组件库

当然有不少对标Bootstrap的预构建Widget库,能帮你快速搭建UI,不用从零开发:

  • Flutter Bootstrap:完全遵循Bootstrap设计规范,提供栅格系统、按钮、表单、卡片等常用组件,用法和Web端Bootstrap高度相似,适合有Web开发经验的开发者快速上手。
  • Material Design Components (MDC) for Flutter:官方维护的Material风格组件库,虽然不是Bootstrap样式,但提供了大量开箱即用的组件(比如输入框、按钮、对话框),稳定性和兼容性拉满,是Flutter开发的标配。
  • Cupertino Widgets:官方的iOS风格组件库,如果你需要开发iOS原生风格的APP,这个库的所有组件都是预构建好的,直接调用即可。
  • FlutterFlow UI Kit:包含大量现成的UI组件,覆盖从基础元素到复杂布局的场景,适合快速搭建原型或直接用于生产项目。
表单、表格场景的预构建代码示例

基础表单示例

下面是一个包含输入验证、单选框、复选框的完整表单,基于Material组件实现:

import 'package:flutter/material.dart';

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

  @override
  State<UserForm> createState() => _UserFormState();
}

class _UserFormState extends State<UserForm> {
  final _formKey = GlobalKey<FormState>();
  String? _username;
  String? _email;
  bool _agreeTerms = false;
  String? _gender;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('用户注册')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TextFormField(
                decoration: const InputDecoration(labelText: '用户名'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '请输入用户名';
                  }
                  return null;
                },
                onSaved: (value) => _username = value,
              ),
              TextFormField(
                decoration: const InputDecoration(labelText: '邮箱'),
                keyboardType: TextInputType.emailAddress,
                validator: (value) {
                  if (value == null || !RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
                    return '请输入有效的邮箱地址';
                  }
                  return null;
                },
                onSaved: (value) => _email = value,
              ),
              const SizedBox(height: 16),
              const Text('性别'),
              Row(
                children: [
                  Radio(
                    value: 'male',
                    groupValue: _gender,
                    onChanged: (value) => setState(() => _gender = value),
                  ),
                  const Text('男'),
                  Radio(
                    value: 'female',
                    groupValue: _gender,
                    onChanged: (value) => setState(() => _gender = value),
                  ),
                  const Text('女'),
                ],
              ),
              CheckboxListTile(
                title: const Text('同意服务条款与隐私政策'),
                value: _agreeTerms,
                onChanged: (value) => setState(() => _agreeTerms = value!),
                validator: (value) {
                  if (value == false) {
                    return '必须同意条款才能继续';
                  }
                  return null;
                },
              ),
              const SizedBox(height: 24),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    _formKey.currentState!.save();
                    // 处理表单提交逻辑,比如发送到服务器
                    print('用户名: $_username, 邮箱: $_email, 性别: $_gender');
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(content: Text('注册成功!')),
                    );
                  }
                },
                child: const Text('注册'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

基础表格示例

下面是支持排序功能的DataTable实现,适合展示结构化数据:

import 'package:flutter/material.dart';

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

  @override
  State<EmployeeTable> createState() => _EmployeeTableState();
}

class _EmployeeTableState extends State<EmployeeTable> {
  final List<Map<String, dynamic>> _employees = [
    {'id': 1, 'name': '张三', 'age': 25, 'department': '前端开发'},
    {'id': 2, 'name': '李四', 'age': 30, 'department': '后端开发'},
    {'id': 3, 'name': '王五', 'age': 28, 'department': 'UI设计'},
    {'id': 4, 'name': '赵六', 'age': 32, 'department': '产品经理'},
  ];
  int _sortColumnIndex = 0;
  bool _sortAscending = true;

  void _sort<T>(Comparable<T> Function(Map<String, dynamic> emp) getField, int columnIndex) {
    if (_sortColumnIndex == columnIndex) {
      setState(() => _sortAscending = !_sortAscending);
    } else {
      setState(() {
        _sortColumnIndex = columnIndex;
        _sortAscending = true;
      });
    }
    _employees.sort((a, b) {
      final aValue = getField(a);
      final bValue = getField(b);
      return _sortAscending ? aValue.compareTo(bValue) : bValue.compareTo(aValue);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('员工信息表')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: DataTable(
            sortColumnIndex: _sortColumnIndex,
            sortAscending: _sortAscending,
            columns: [
              DataColumn(
                label: const Text('ID'),
                onSort: (columnIndex, ascending) => _sort((emp) => emp['id'] as int, columnIndex),
              ),
              DataColumn(
                label: const Text('姓名'),
                onSort: (columnIndex, ascending) => _sort((emp) => emp['name'] as String, columnIndex),
              ),
              DataColumn(
                label: const Text('年龄'),
                onSort: (columnIndex, ascending) => _sort((emp) => emp['age'] as int, columnIndex),
              ),
              DataColumn(
                label: const Text('部门'),
                onSort: (columnIndex, ascending) => _sort((emp) => emp['department'] as String, columnIndex),
              ),
            ],
            rows: _employees.map((emp) {
              return DataRow(
                cells: [
                  DataCell(Text(emp['id'].toString())),
                  DataCell(Text(emp['name'])),
                  DataCell(Text(emp['age'].toString())),
                  DataCell(Text(emp['department'])),
                ],
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者ABHISHEK REDDY GOTHAM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:25:25