Flutter链式选择器插件linkage_picker的使用

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

Flutter链式选择器插件linkage_picker的使用

linkage_picker 是一个基于 CupertinoPicker 风格的链式选择器组件。它提供了 DatePicker 实现,并且你可以通过扩展 LinkagePickerWidget 来实现更复杂的场景。

DatePicker

DatePicker 是一个预设的链式选择器。

DatePicker(
  start: DateTime(2000, today.month, today.day),
  end: DateTime(2050, today.month, today.day),
  date: date,
)

你也可以将 DatePicker 以底部弹出框的形式展示:

DatePicker(
  ...
).showAsBottomSheet(context)

或者将其嵌入到其他组件中:

ValueListenableBuilder<bool>(
  valueListenable: showPicker,
  builder: (context, value, _) {
    return value
        ? Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              DatePicker(
                ...,
                onControllerCreated: (controller) {
                  this.controller = controller;
                },
              ),
              TextButton(
                onPressed: () {
                  showPicker.value = false;
                  final result = controller.result;
                  if (result != null) {
                    content.value = DateFormat('yyyy-MM-dd').format(result);
                  }
                },
                child: const Text('确认')),
            ],
          )
        : const SizedBox.shrink();
  })

CustomPicker

你可以通过扩展 LinkagePickerWidget 来创建自定义的链式选择器。

class CustomPicker extends LinkagePickerWidget<CustomData, String> {
  CustomPicker()
      : super(
          maxLevel: LinkagePickerLevel.second,
          dataBuilder: (level, parent) {
            return switch (level) {
              LinkagePickerLevel.first => LinkagePickerData<CustomData>[...],
              LinkagePickerLevel.second => LinkagePickerData<CustomData>[...],
              _ => throw UnimplementedError(),
            };
          },
          equalizer: (level, value1, value2) {
            return switch (level) {
              _ => (value1 as CustomData).equals(value2 as CustomData),
            };
          },
          resultConverter: (selection) {
            final getResultString(selection.first, selection.last);
          },
          conflictResolver: (level, previous, currents) {
            return switch (level) {
              LinkagePickerLevel.first => null,
              LinkagePickerLevel.second =>
                (previous as CustomData).copyWith(...),
              _ => throw UnimplementedError(),
            };
          },
          initialValue: <CustomData>[...],
          pickerStyle: LinkagePickerStyle(
            itemBuilder: (level, data, selected) {
              switch (level) {
                case LinkagePickerLevel.first:
                  return buildFirstPickerItem(data, selected);
                case LinkagePickerLevel.second:
                  return buildSecondPickerItem(data, selected);
                default:
                  throw UnimplementedError();
              }
            },
          ),
        );
}

LinkagePickerWidget<T,R>

  • <T>: 数据源值的类型
  • <R>: 结果的类型
  • maxLevel: 选择器的最大层级
  • dataBuilder: 返回当前层级及其父数据的数据源
  • equalizer: 告诉组件在当前层级两个值是否相等
  • resultConverter: 将结果转换为你想要的类型
  • conflictResolver: 将选择器选定的结果转换为导航结果
  • initialValue: 选择器的初始值
  • pickerStyle: 自定义选择器的样式
  • onControllerCreated: 控制器创建时的回调

LinkagePickerStyle

  • diameterRatio: 与 CupertinoPicker.diameterRatio 相同
  • itemExtent: 与 CupertinoPicker.itemExtent 相同
  • backgroundColor: 与 CupertinoPicker.backgroundColor 相同
  • offAxisFraction: 与 CupertinoPicker.offAxisFraction 相同
  • squeeze: 与 CupertinoPicker.squeeze 相同
  • useMagnifier: 与 CupertinoPicker.useMagnifier 相同
  • magnification: 与 CupertinoPicker.magnification 相同
  • selectionOverlay: 与 CupertinoPicker.selectionOverlay 相同
  • heightRatio: 选择器高度与项目高度的比例
  • itemBuilder: 自定义选择器项目的样式

完整示例代码

import 'package:example/picker_field/picker_field_custom_color_palette.dart';
import 'package:example/picker_field/picker_field_custom_time.dart';
import 'package:example/picker_field/picker_field_date_bottom_sheet.dart';
import 'package:example/picker_field/picker_field_date.dart';
import 'package:flutter/material.dart';

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Linkage Picker Example'),
      ),
      body: Container(
        padding: const EdgeInsets.symmetric(horizontal: 32),
        child: SingleChildScrollView(
          padding: const EdgeInsets.symmetric(vertical: 32),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              pickerExampleSegment(
                'DatePicker',
                const PickerFieldDate(),
              ),
              pickerExampleSegment(
                'DatePicker[BottomSheet]',
                PickerFieldDateBottomSheet(context),
              ),
              pickerExampleSegment(
                'CustomPicker[Time]',
                PickerFieldCustomTime(context),
              ),
              pickerExampleSegment(
                'CustomPicker[ColorPalette]',
                PickerFieldCustomColorPalette(context),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget pickerExampleSegment(String title, Widget child) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
        ),
        const SizedBox(height: 8),
        child,
        const SizedBox(height: 20),
      ],
    );
  }
}

更多关于Flutter链式选择器插件linkage_picker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter链式选择器插件linkage_picker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


linkage_picker 是一个用于 Flutter 的链式选择器插件,通常用于实现类似于省市区选择、日期选择等多级联动的选择器。它可以帮助用户通过多级联动的方式选择数据。

以下是如何在 Flutter 项目中使用 linkage_picker 插件的步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 linkage_picker 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  linkage_picker: ^1.0.0  # 请使用最新版本

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

2. 导入插件

在需要使用 linkage_picker 的 Dart 文件中导入插件:

import 'package:linkage_picker/linkage_picker.dart';

3. 使用 LinkagePicker

LinkagePicker 是一个可以自定义的多级联动选择器。你可以通过传递数据和配置来使用它。

示例:省市区选择器

假设你有一个包含省市区数据的数据源,你可以通过以下方式使用 LinkagePicker

class ProvinceCityAreaPicker extends StatefulWidget {
  @override
  _ProvinceCityAreaPickerState createState() => _ProvinceCityAreaPickerState();
}

class _ProvinceCityAreaPickerState extends State<ProvinceCityAreaPicker> {
  List<LinkageItem> _data = [];

  @override
  void initState() {
    super.initState();
    // 模拟省市区数据
    _data = [
      LinkageItem(name: '北京', children: [
        LinkageItem(name: '北京市', children: [
          LinkageItem(name: '东城区'),
          LinkageItem(name: '西城区'),
        ]),
      ]),
      LinkageItem(name: '上海', children: [
        LinkageItem(name: '上海市', children: [
          LinkageItem(name: '黄浦区'),
          LinkageItem(name: '徐汇区'),
        ]),
      ]),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('省市区选择器'),
      ),
      body: Center(
        child: LinkagePicker(
          data: _data,
          onChanged: (List<LinkageItem> selectedItems) {
            // 当用户选择时回调
            print('Selected: ${selectedItems.map((item) => item.name).toList()}');
          },
        ),
      ),
    );
  }
}

LinkageItem 结构

LinkageItemlinkage_picker 中用于表示每一级数据的类。它包含 namechildren 属性:

class LinkageItem {
  String name;
  List<LinkageItem> children;

  LinkageItem({required this.name, this.children = const []});
}

自定义样式

你可以通过 LinkagePickerstyle 参数来自定义选择器的样式:

LinkagePicker(
  data: _data,
  onChanged: (List<LinkageItem> selectedItems) {
    print('Selected: ${selectedItems.map((item) => item.name).toList()}');
  },
  style: LinkagePickerStyle(
    backgroundColor: Colors.white,
    itemTextStyle: TextStyle(color: Colors.black),
    selectedItemTextStyle: TextStyle(color: Colors.blue),
    dividerColor: Colors.grey,
  ),
);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!