Flutter动画选择项插件animated_item_picker的使用

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

Flutter动画选择项插件animated_item_picker的使用

简介

animated_item_picker 是一个通用的选择项组件,封装了单选或多选逻辑。它适用于固定大小的项目列表,例如级别、星期几或性别选择器等。该插件支持点击时的透明度动画效果,可以增强用户体验。

预览

预览

使用方法

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 animated_item_picker 依赖:

dependencies:
  animated_item_picker: ^latest_version

2. 创建示例应用

以下是一个完整的示例代码,展示了如何使用 AnimatedItemPicker 组件来创建水平和垂直的选择器,并实现单选和多选功能。

import 'dart:math';
import 'package:animated_item_picker/animated_item_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Material(
        child: HomePage(),
        color: Colors.black,
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  static ColorTween _firstPickerColorTween1 = ColorTween(begin: Colors.white, end: Colors.redAccent);
  static ColorTween _firstPickerColorTween2 = ColorTween(begin: Colors.black, end: Colors.redAccent);

  static ColorTween _secondPickerColorTween1 = ColorTween(begin: Colors.black, end: Colors.yellow);
  static ColorTween _secondPickerColorTween2 = ColorTween(begin: Colors.white, end: Colors.yellow);

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Random _random = Random();
  int selectionIndex = 0;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      children: [
        // 水平单选选择器
        Container(
          padding: EdgeInsets.all(16),
          decoration: BoxDecoration(
            color: Colors.grey.shade800,
            borderRadius: BorderRadius.circular(8),
          ),
          child: AnimatedItemPicker(
            axis: Axis.horizontal, // 设置为水平方向
            multipleSelection: false, // 单选
            itemCount: Level.LIST.length, // 项目数量
            pressedOpacity: 0.85, // 点击时的透明度
            programmaticSelection: {Level.LIST.indexOf(Level.BEGINNER)}, // 初始选择项
            expandedItems: true, // 展开项目
            onItemPicked: (index, selected) {
              print("Level: ${Level.LIST[index]}, selected: $selected");
            },
            itemBuilder: (index, animValue) => GenderItemWidget(
              name: Level.LIST[index].toString(), // 项目名称
              borderColor: HomePage._firstPickerColorTween2.transform(animValue)!, // 边框颜色
              textColor: HomePage._firstPickerColorTween1.transform(animValue)!, // 文本颜色
            ),
          ),
        ),
        SizedBox(height: 20),
        // 垂直多选选择器
        Container(
          padding: EdgeInsets.all(16),
          decoration: BoxDecoration(
            color: Colors.grey.shade800,
            borderRadius: BorderRadius.circular(8),
          ),
          child: AnimatedItemPicker(
            axis: Axis.vertical, // 设置为垂直方向
            multipleSelection: true, // 多选
            itemCount: DayOfWeek.LIST.length, // 项目数量
            maxItemSelectionCount: 6, // 最大选择项数量
            expandedItems: true, // 展开项目
            programmaticSelection: Set.of(DayOfWeek.FOR_RANDOM[selectionIndex]), // 初始选择项
            onItemPicked: (index, selected) {
              print("Day: ${DayOfWeek.LIST[index]}, selected: $selected");
            },
            itemBuilder: (index, animValue) => DayItemWidget(
              name: DayOfWeek.LIST[index], // 项目名称
              textColor: HomePage._secondPickerColorTween2.transform(animValue)!, // 文本颜色
              backgroundColor: HomePage._secondPickerColorTween1.transform(animValue)!, // 背景颜色
            ),
          ),
        ),
        SizedBox(height: 20),
        // 切换选择项按钮
        CupertinoButton(
          child: Text('SWITCH DAYS PROGRAMMATICALLY'),
          onPressed: () {
            setState(() {
              selectionIndex = _random.nextInt(4); // 随机选择一个初始项
            });
          },
        ),
      ],
    );
  }
}

// 定义级别枚举
enum Level {
  BEGINNER,
  INTERMEDIATE,
  ADVANCED,
  EXPERT
}

extension LevelList on Level {
  static List<Level> LIST = [BEGINNER, INTERMEDIATE, ADVANCED, EXPERT];
}

// 定义星期几枚举
enum DayOfWeek {
  MONDAY,
  TUESDAY,
  WEDNESDAY,
  THURSDAY,
  FRIDAY,
  SATURDAY,
  SUNDAY
}

extension DayOfWeekList on DayOfWeek {
  static List<DayOfWeek> LIST = [
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
  ];

  static List<Set<int>> FOR_RANDOM = [
    {0, 1},
    {2, 3},
    {4, 5},
    {6}
  ];
}

// 自定义选择项小部件
class GenderItemWidget extends StatelessWidget {
  final String name;
  final Color borderColor;
  final Color textColor;

  GenderItemWidget({
    required this.name,
    required this.borderColor,
    required this.textColor,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: BoxDecoration(
        border: Border.all(color: borderColor, width: 2),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        name,
        style: TextStyle(color: textColor, fontSize: 16),
      ),
    );
  }
}

// 自定义选择项小部件
class DayItemWidget extends StatelessWidget {
  final String name;
  final Color textColor;
  final Color backgroundColor;

  DayItemWidget({
    required this.name,
    required this.textColor,
    required this.backgroundColor,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: BoxDecoration(
        color: backgroundColor,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        name,
        style: TextStyle(color: textColor, fontSize: 16),
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何使用 animated_item_picker 插件的示例代码。这个插件允许你在 Flutter 应用中实现带有动画效果的选项选择器。

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

dependencies:
  flutter:
    sdk: flutter
  animated_item_picker: ^最新版本号  # 替换为当前最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,是一个完整的示例代码,展示如何使用 animated_item_picker

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Item Picker Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Animated Item Picker Demo'),
        ),
        body: Center(
          child: MyAnimatedItemPicker(),
        ),
      ),
    );
  }
}

class MyAnimatedItemPicker extends StatefulWidget {
  @override
  _MyAnimatedItemPickerState createState() => _MyAnimatedItemPickerState();
}

class _MyAnimatedItemPickerState extends State<MyAnimatedItemPicker> {
  List<String> items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return AnimatedItemPicker(
      initialIndex: selectedIndex,
      itemCount: items.length,
      itemBuilder: (context, index) {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(
            items[index],
            style: TextStyle(fontSize: 24),
          ),
        );
      },
      onSelected: (index) {
        setState(() {
          selectedIndex = index;
        });
      },
      axis: Axis.vertical, // 或者 Axis.horizontal
      scrollPhysics: BouncingScrollPhysics(), // 可选,用于自定义滚动效果
      itemExtent: 60.0, // 每个项目的尺寸,仅在 axis 为 vertical 时有效
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.5),
            spreadRadius: 5,
            blurRadius: 7,
            offset: Offset(0, 3), // changes position of shadow
          ),
        ],
      ),
    );
  }
}

代码解释:

  1. 依赖导入:确保导入了 animated_item_picker 包。
  2. MyApp:主应用类,包含应用的主题和主页。
  3. MyAnimatedItemPicker:一个包含 AnimatedItemPicker 的自定义 Widget。
  4. _MyAnimatedItemPickerState
    • items:一个包含选项的列表。
    • selectedIndex:当前选中的选项索引。
    • AnimatedItemPicker
      • initialIndex:初始选中的索引。
      • itemCount:选项的总数。
      • itemBuilder:构建每个选项的 Widget。
      • onSelected:选中某个选项时的回调,更新 selectedIndex
      • axis:动画的方向,可以是 Axis.verticalAxis.horizontal
      • scrollPhysics:自定义滚动效果(可选)。
      • itemExtent:每个选项的尺寸(仅在垂直方向有效)。
      • decorationAnimatedItemPicker 的装饰,例如背景颜色、边框半径和阴影。

这段代码展示了如何使用 animated_item_picker 插件创建一个带有动画效果的选择器。你可以根据需要调整 itemBuilder 中的内容,以及其它参数,以满足你的应用需求。

回到顶部