Flutter卡片设置界面插件card_settings_ui的使用

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

Flutter卡片设置界面插件 card_settings_ui 的使用

Overview

Demo

card_settings_ui 是一个基于 Card 的 Flutter 设置界面插件。它受到了 settings_ui 的启发,但作者不喜欢原生的 Android UI,并且原插件包含平台判断(不支持 OHOS),因此删除了这些平台判断并用 Card 包装了设置项。

Tip

这是一个纯 Dart 包,没有平台判断,因此支持所有平台,包括 OHOS。

Installing

  1. 在你的 pubspec.yaml 文件中添加依赖:

    dependencies:
      card_settings_ui: ^1.1.1
    
  2. 导入 card_settings_ui 包:

    import 'package:card_settings_ui/card_settings_ui.dart';
    

Basic Usage

使用方法与 settings_ui 类似。

Important

此包仅适用于 MaterialApp,旨在构建类似 CupertinoListSection 的设置界面。

SettingsList(
  sections: [
    SettingsSection(
      title: Text('Common'),
      tiles: <SettingsTile>[
        SettingsTile.navigation(
          leading: Icon(Icons.language),
          title: Text('Language'),
          value: Text('English'),
        ),
        SettingsTile.switchTile(
          onToggle: (value) {},
          initialValue: true,
          leading: Icon(Icons.format_paint),
          title: Text('Enable custom theme'),
        ),
      ],
    ),
  ],
),

Example Product

此包最初由 Predidit / Kazumi 使用,因此你可能会发现示例代码类似于 Predidit / Kazumi 中的代码。

示例代码

以下是一个完整的示例代码,展示了如何使用 card_settings_ui 插件创建一个设置页面:

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.blue, brightness: Brightness.light),
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.blue, brightness: Brightness.dark),
      ),
      debugShowCheckedModeBanner: false,
      home: const SettingsPage(),
    );
  }
}

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

  @override
  State<SettingsPage> createState() => _SettingsPageState();
}

class _SettingsPageState extends State<SettingsPage> {
  bool isEnabled = true;
  bool? selectAll = false;
  List<bool?> securityItem = [false, false, false];

  void updateSelectAll() {
    if (securityItem.every((item) => item == true)) {
      selectAll = true;
    } else if (securityItem.every((item) => item == false)) {
      selectAll = false;
    } else {
      selectAll = null;
    }
  }

  double size = 10.0;
  String density = densityList[0];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Settings'),
      ),
      body: Center(
        child: SizedBox(
          width: (MediaQuery.of(context).size.width > 800) ? 800 : null,
          child: SettingsList(
            sections: [
              SettingsSection(
                title: Text('Email density'),
                tiles: densityList
                    .map((e) => SettingsTile<String>.radioTile(
                          title: Text(e),
                          radioValue: e,
                          groupValue: density,
                          onChanged: (String? value) {
                            if (value != null) {
                              setState(() {
                                density = value;
                              });
                            }
                          },
                        ))
                    .toList(),
              ),
              SettingsSection(
                title: Text('Security'),
                tiles: <SettingsTile>[
                  SettingsTile.navigation(
                    onPressed: (_) => showToast(
                        context, 'Click checkbox in front to select all'),
                    leading: Checkbox(
                      value: selectAll,
                      onChanged: (_) {
                        if (selectAll == null || selectAll == true) {
                          selectAll = false;
                          securityItem.fillRange(0, securityItem.length, false);
                        } else {
                          selectAll = true;
                          securityItem.fillRange(0, securityItem.length, true);
                        }
                        setState(() {});
                      },
                      tristate: true,
                    ),
                    title: Text('Select all'),
                  ),
                ],
              ),
              SettingsSection(
                tiles: <SettingsTile>[
                  SettingsTile.checkboxTile(
                    onToggle: (value) {
                      securityItem[0] = value ?? !securityItem[0]!;
                      updateSelectAll();
                      setState(() {});
                    },
                    initialValue: securityItem[0],
                    leading: Icon(Icons.dialpad),
                    title: Text('PIN'),
                    description: Text('Allow user log in with PIN'),
                  ),
                  SettingsTile.checkboxTile(
                    onToggle: (value) {
                      securityItem[1] = value ?? !securityItem[1]!;
                      updateSelectAll();
                      setState(() {});
                    },
                    initialValue: securityItem[1],
                    leading: Icon(Icons.password_rounded),
                    title: Text('Password'),
                    description: Text('Allow user log in with password'),
                  ),
                  SettingsTile.checkboxTile(
                    onToggle: (value) {
                      securityItem[2] = value ?? !securityItem[2]!;
                      updateSelectAll();
                      setState(() {});
                    },
                    initialValue: securityItem[2],
                    leading: Icon(Icons.fingerprint),
                    title: Text('Fingerprint'),
                    description: Text('Allow user log in with fingerprint'),
                  ),
                ],
              ),
              SettingsSection(
                title: Text('Subtitle'),
                tiles: <SettingsTile>[
                  SettingsTile.switchTile(
                    onToggle: (value) {
                      isEnabled = value ?? !isEnabled;
                      setState(() {});
                    },
                    initialValue: isEnabled,
                    leading: Icon(Icons.subtitles),
                    title: Text('Enable subtitle'),
                  ),
                  SettingsTile.navigation(
                    onPressed: (_) => subtitleSizeDialog(context),
                    enabled: isEnabled,
                    leading: Icon(Icons.format_size),
                    title: Text('Subtitle size'),
                    value: Text('$size'),
                  ),
                ],
              ),
              SettingsSection(
                bottomInfo: Text('Upload settings to cloud'),
                tiles: <SettingsTile>[
                  SettingsTile(
                    onPressed: (_) => showToast(context, 'Upload successfully'),
                    title: Text('Upload'),
                    trailing: Icon(Icons.cloud_upload_rounded),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future subtitleSizeDialog(BuildContext context) {
    return showDialog(
      builder: (context) {
        return AlertDialog(
          title: const Text('Subtitle font size'),
          content: StatefulBuilder(builder: (BuildContext context, _) {
            return Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                for (final double i in subtitleSize) ...<Widget>[
                  if (i == size) ...<Widget>[
                    FilledButton(
                      onPressed: () async {
                        setState(() {
                          size = i;
                        });
                        Navigator.of(context).pop();
                      },
                      child: Text(i.toString()),
                    ),
                  ] else ...[
                    FilledButton.tonal(
                      onPressed: () async {
                        setState(() {
                          size = i;
                        });
                        Navigator.of(context).pop();
                      },
                      child: Text(i.toString()),
                    ),
                  ]
                ]
              ],
            );
          }),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: Text(
                'Cancel',
                style: TextStyle(color: Theme.of(context).colorScheme.outline),
              ),
            ),
          ],
        );
      },
      context: context,
    );
  }

  void showToast(BuildContext context, String message) {
    ScaffoldMessenger.of(context)
      ..removeCurrentSnackBar()
      ..showSnackBar(
        SnackBar(
          content: Text(message),
        ),
      );
  }
}

final List<double> subtitleSize = [
  10.0,
  11.0,
  12.0,
  13.0,
  14.0,
  15.0,
];

const List<String> densityList = [
  'Default',
  'Comfortable',
  'Compact',
];

以上代码展示了一个完整的设置页面,包括多个设置部分和不同的设置项类型,如单选按钮、复选框、开关和导航按钮。希望这对你有所帮助!


更多关于Flutter卡片设置界面插件card_settings_ui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter卡片设置界面插件card_settings_ui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用card_settings_ui插件来创建一个卡片设置界面的示例代码。card_settings_ui是一个强大的Flutter插件,用于创建美观和用户友好的设置卡片界面。

首先,确保你的Flutter项目中已经添加了card_settings_ui依赖。你可以在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  card_settings_ui: ^latest_version  # 请替换为最新的版本号

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

接下来是一个完整的示例代码,展示了如何使用card_settings_ui来创建一个简单的设置界面:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Card Settings UI Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SettingsScreen(),
    );
  }
}

class SettingsScreen extends StatefulWidget {
  @override
  _SettingsScreenState createState() => _SettingsScreenState();
}

class _SettingsScreenState extends State<SettingsScreen> {
  String _username = '';
  bool _notificationsEnabled = false;
  int _age = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Settings'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: CardSettingsForm(
          child: Column(
            children: <Widget>[
              CardSettingsText(
                label: 'Username',
                initialValue: _username,
                onChanged: (value) {
                  setState(() {
                    _username = value;
                  });
                },
              ),
              CardSettingsSwitch(
                label: 'Enable Notifications',
                initialValue: _notificationsEnabled,
                onChanged: (value) {
                  setState(() {
                    _notificationsEnabled = value;
                  });
                },
              ),
              CardSettingsNumberPicker(
                label: 'Age',
                initialValue: _age,
                min: 0,
                max: 100,
                onChanged: (value) {
                  setState(() {
                    _age = value;
                  });
                },
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 在这里处理提交逻辑,例如保存设置
          print('Username: $_username');
          print('Notifications Enabled: $_notificationsEnabled');
          print('Age: $_age');
        },
        tooltip: 'Submit',
        child: Icon(Icons.save),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的设置界面,包含以下元素:

  1. CardSettingsText:用于输入用户名。
  2. CardSettingsSwitch:用于启用或禁用通知。
  3. CardSettingsNumberPicker:用于选择年龄。

每个控件都有一个label属性来显示标签,一个initialValue属性来设置初始值,以及一个onChanged回调函数来处理用户输入的变化。

此外,我们在ScaffoldfloatingActionButton中添加了一个浮动操作按钮,用于处理提交逻辑(在这个示例中,仅仅是打印出设置的值)。

你可以根据需要添加更多的设置项,并自定义它们的外观和行为。card_settings_ui插件提供了丰富的控件和选项,可以帮助你快速构建出美观且功能强大的设置界面。

回到顶部