Flutter多表管理插件flutter_multi_table的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter多表管理插件 flutter_multi_table 的使用

介绍

flutter_multi_table 是一个用于创建动态、多列表格的 Flutter 插件,支持下拉选择、验证和只读单元格等功能。适用于交互式表格输入。

特性

  • ✨ 完全可定制的表格布局和样式
  • 📝 支持文本输入和下拉选择单元格
  • 🔒 可配置的只读单元格
  • ✅ 内置验证支持
  • 📱 响应式设计,支持横屏和竖屏模式
  • 🎨 自定义头部、单元格和错误消息的样式
  • 🔄 实时数据更新,支持 onChange 回调
  • 💾 通过专用控制器轻松管理数据

支持的平台

  • Flutter Android
  • Flutter iOS
  • Flutter Web
  • Flutter Desktop
  • Flutter macOS
  • Flutter Linux

安装

  1. pubspec.yaml 文件中添加依赖,并导入包:

    dependencies:
      flutter_multi_table: <latest-version>
    

    或者使用命令行:

    flutter pub add flutter_multi_table
    
  2. 运行 pub get

    flutter pub get
    
  3. 导入包:

    import 'package:flutter_multi_table/flutter_multi_table.dart';
    

基本用法

// 1. 定义表头
List headers = [
  'No',
  'Name',
  'Age',
  'City',
  'Status',
];

// 2. 创建初始数据
List<Map> initialData = [
  {
    'No': '1',
    'Name': 'John',
    'Age': '',
    'City': 'New York',
    'Status': 'Active',
  },
  {
    'No': '2',
    'Name': 'Alice',
    'Age': '',
    'City': 'London',
    'Status': 'Inactive',
  },
];

// 3. 初始化控制器
FlutterMultiTableController controller = FlutterMultiTableController(
  initialData: initialData,
  headers: headers,
);

// 4. 配置表格
FlutterMultiTableConfig config = FlutterMultiTableConfig(
  headers: headers,
  hint: '....',
);

// 5. 使用组件
FlutterMultiTable(
  controller: controller,
  config: config,
)

高级配置

表格配置

FlutterMultiTableConfig config = FlutterMultiTableConfig(
  headers: headers,
  hint: '....',

  // 定义哪些单元格是只读的
  isReadOnly: (row, column) {
    if (column == 0 || column == 1 || column == 3 || column == 4) {
      return true;
    }
    return false;
  },

  // 配置下拉选择单元格
  isDropdown: (row, column) {
    if (column == 2 && (row != 1 && row != 13)) {
      return true;
    }
    return false;
  },
  dropdownOptions: ['Jakarta', 'New York', 'London', 'Tokyo', 'Paris'],

  // 处理值变化
  onChanged: (row, column, value) {
    print('Cell ($row, $column) changed to: $value');
  },

  // 验证
  validator: (row, column, value) {
    if (column == 2 && value.isEmpty) {
      return 'Data wajib diisi';
    }
    return null;
  },

  // 下拉选择验证
  dropdownValidator: (row, column, value) {
    if (column == 2 && (value == null || value.isEmpty)) {
      return 'Data wajib diisi';
    }
    return null;
  },

  // 样式
  headerTextStyle: TextStyle(
    fontSize: 10,
    color: Colors.white,
    fontWeight: FontWeight.w700,
  ),
  errorTextStyle: TextStyle(fontSize: 8, color: Colors.red),
  cellTextStyle: TextStyle(
    fontSize: 6,
    fontWeight: FontWeight.w600,
  ),
  cellWidth: MediaQuery.of(context).size.width * 0.182,
  cellHeight: MediaQuery.of(context).size.height * 0.04,
  hintTextStyle: TextStyle(
    fontSize: 8,
    fontWeight: FontWeight.w400,
  ),
);

FlutterMultiTableController

主控制器类,用于管理表格数据和状态:

构造函数

FlutterMultiTableController({
  required List<Map> initialData,
  required List headers,
})

方法

  • updateCell(int row, int column, String value): 更新特定单元格的值
  • getCellValue(int row, int column): 获取特定单元格的值
  • setDropdownError(int row, int column, String? error): 设置下拉选择错误信息
  • getDropdownError(int row, int column): 获取下拉选择错误信息
  • dispose(): 清理资源

FlutterMultiTableConfig

配置类,用于自定义表格的外观和行为:

FlutterMultiTableConfig({
  required List headers,
  String hint = "",
  bool Function(int row, int column)? isReadOnly,
  bool Function(int row, int column)? isDropdown,
  List? dropdownOptions,
  void Function(int row, int column, String value)? onChanged,
  String? Function(int row, int column, String value)? validator,
  String? Function(int row, int column, String? value)? dropdownValidator,
  TextStyle? headerTextStyle,
  Color? headerBoxColor,
  TextStyle? cellTextStyle,
  TextStyle? hintTextStyle,
  TextStyle? errorTextStyle,
  TextInputType? textInputType,
  double? cellHeight,
  double? cellWidth,
})

完整示例

import 'package:flutter/material.dart';
import 'package:flutter_multi_table/flutter_multi_table.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Flutter Multi Table Example')),
        body: const SingleChildScrollView(child: MyHomePage()),
      ),
    );
  }
}

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

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  late FlutterMultiTableController _controllerCreate;
  late FlutterMultiTableController _controllerSaved;
  late FlutterMultiTableConfig _create;
  late FlutterMultiTableConfig _saved;
  List<Map<String, String>> savedData = [];

  List<String> headers = [
    'No',
    'Name',
    'Age',
    'City',
    'Status',
  ];

  @override
  void initState() {
    super.initState();
    List<Map<String, String>> initialData = [
      {
        'No': '1',
        'Name': 'John',
        'Age': '',
        'City': 'New York',
        'Status': 'Active',
      },
      {
        'No': '2',
        'Name': 'Alice',
        'Age': '',
        'City': 'London',
        'Status': 'Inactive',
      },
    ];

    _controllerCreate = FlutterMultiTableController(
      initialData: initialData,
      headers: headers,
    );

    _controllerSaved = FlutterMultiTableController(
      initialData: const [],
      headers: headers,
    );
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    _create = FlutterMultiTableConfig(
      headers: headers,
      hint: '....',
      validator: (row, column, value) {
        if (column == 2 && (value.isEmpty)) {
          return 'Data wajib diisi';
        }
        return null;
      },
      dropdownValidator: (row, column, value) {
        if (column == 2 && (value == null || value.isEmpty)) {
          return 'Data wajib diisi';
        }
        return null;
      },
      headerTextStyle: const TextStyle(
        fontSize: 10,
        color: Colors.white,
        fontWeight: FontWeight.w700,
      ),
      errorTextStyle: const TextStyle(fontSize: 8, color: Colors.red),
      cellTextStyle: const TextStyle(
        fontSize: 6,
        fontWeight: FontWeight.w600,
      ),
      cellWidth: MediaQuery.of(context).size.width * 0.182,
      cellHeight: MediaQuery.of(context).size.height * 0.04,
      hintTextStyle: const TextStyle(
        fontSize: 8,
        fontWeight: FontWeight.w400,
      ),
      isReadOnly: (row, column) {
        if (column == 0 || column == 1 || column == 3 || column == 4) {
          return true;
        }
        return false;
      },
      isDropdown: (row, column) {
        if (column == 2 && (row != 1 && row != 13)) {
          return true;
        }
        return false;
      },
      dropdownOptions: ['Jakarta', 'New York', 'London', 'Tokyo', 'Paris'],
      onChanged: (row, column, value) {
        debugPrint('Changed: Row $row, Column $column, Value: $value');
      },
    );

    // 配置保存的数据表(所有单元格只读)
    _saved = FlutterMultiTableConfig(
      headers: headers,
      headerTextStyle: const TextStyle(
        fontSize: 10,
        color: Colors.white,
        fontWeight: FontWeight.w700,
      ),
      cellTextStyle: const TextStyle(
        fontSize: 6,
        fontWeight: FontWeight.w600,
      ),
      cellWidth: MediaQuery.of(context).size.width * 0.182,
      cellHeight: MediaQuery.of(context).size.height * 0.04,
      isReadOnly: (row, column) => true, // 所有单元格只读
    );
  }

  void _saveData() {
    // 获取当前表格数据
    final currentData = _controllerCreate.tableData.map((row) {
      // 将 TextEditingController 值转换为字符串
      return row.map((key, value) {
        return MapEntry(key, value.text); // 提取文本值
      });
    }).toList();

    // 验证数据
    bool isValid = true;
    for (var row in currentData) {
      if (row['Age'] == null || row['Age']!.isEmpty) {
        isValid = false;
        break;
      }
    }

    if (!isValid) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Please fill all required fields'),
          backgroundColor: Colors.red,
        ),
      );
      return;
    }

    setState(() {
      savedData.addAll(currentData);
      // 更新保存数据表的控制器
      _controllerSaved = FlutterMultiTableController(
        initialData: savedData,
        headers: headers,
      );
    });

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('Data saved successfully'),
        backgroundColor: Colors.green,
      ),
    );
  }

  @override
  void dispose() {
    _controllerCreate.dispose();
    _controllerSaved.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text(
            'Input Data',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          const SizedBox(height: 10),
          FlutterMultiTable(
            controller: _controllerCreate,
            config: _create,
          ),
          const SizedBox(height: 20),
          Center(
            child: ElevatedButton(
              onPressed: _saveData,
              child: const Text('Submit'),
            ),
          ),
          if (savedData.isNotEmpty) ...[
            const SizedBox(height: 30),
            const Text(
              'Get Data',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 10),
            FlutterMultiTable(
              controller: _controllerSaved,
              config: _saved,
            ),
          ],
        ],
      ),
    );
  }
}

许可证

MIT

贡献

欢迎提交 Pull 请求。


更多关于Flutter多表管理插件flutter_multi_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter多表管理插件flutter_multi_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用flutter_multi_table插件来管理多个SQLite表的示例代码。这个插件允许你创建、读取、更新和删除(CRUD)SQLite数据库中的表。

首先,确保你已经在pubspec.yaml文件中添加了flutter_multi_table依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_multi_table: ^x.y.z  # 请替换为最新的版本号

然后,运行flutter pub get来安装依赖。

以下是一个完整的示例,展示了如何使用flutter_multi_table插件:

import 'package:flutter/material.dart';
import 'package:flutter_multi_table/flutter_multi_table.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Multi Table Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late FlutterMultiTableHelper _dbHelper;

  @override
  void initState() {
    super.initState();
    _dbHelper = FlutterMultiTableHelper();
    initDatabase();
  }

  Future<void> initDatabase() async {
    // 创建两个表
    await _dbHelper.createTable(
      tableName: 'users',
      columns: {
        'id': 'INTEGER PRIMARY KEY AUTOINCREMENT',
        'name': 'TEXT NOT NULL',
        'email': 'TEXT NOT NULL UNIQUE',
      },
    );

    await _dbHelper.createTable(
      tableName: 'products',
      columns: {
        'id': 'INTEGER PRIMARY KEY AUTOINCREMENT',
        'name': 'TEXT NOT NULL',
        'price': 'REAL NOT NULL',
      },
    );

    // 插入一些初始数据
    await _dbHelper.insert(
      tableName: 'users',
      values: {'name': 'Alice', 'email': 'alice@example.com'},
    );

    await _dbHelper.insert(
      tableName: 'products',
      values: {'name': 'Laptop', 'price': 999.99},
    );
  }

  Future<void> fetchData() async {
    // 从表中获取数据
    List<Map<String, dynamic>> users = await _dbHelper.getAllRows(tableName: 'users');
    List<Map<String, dynamic>> products = await _dbHelper.getAllRows(tableName: 'products');

    // 打印数据到控制台
    print('Users: $users');
    print('Products: $products');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Multi Table Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await fetchData();
            // 你可以在这里更新UI,例如使用setState来显示数据
          },
          child: Text('Fetch Data'),
        ),
      ),
    );
  }

  @override
  void dispose() {
    // 关闭数据库连接
    _dbHelper.close();
    super.dispose();
  }
}

在这个示例中,我们:

  1. 添加了flutter_multi_table依赖并安装了它。
  2. 创建了一个Flutter应用,并在MyHomePage中初始化了FlutterMultiTableHelper实例。
  3. 使用createTable方法创建了两个表:usersproducts
  4. 使用insert方法向这两个表中插入了初始数据。
  5. 提供了一个按钮,当点击时,会调用fetchData方法从两个表中获取所有数据并打印到控制台。

请注意,这个示例仅展示了如何在Flutter应用中使用flutter_multi_table插件进行基本的CRUD操作。你可能需要根据你的实际需求进一步扩展这个示例,例如更新UI以显示获取到的数据。

回到顶部