Flutter动画效果插件siri_wave的使用

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

Flutter动画效果插件siri_wave的使用

插件简介

siri_wave 是一个Flutter插件,它能够创建类似于Siri的波形动画。这个库受到了siriwave库的启发。

ci Package: siri_wave Publisher: halildurmus.dev Language: Dart Platform: Flutter License: BSD-3-Clause

你可以通过 在线演示 来查看实际效果。

iOS 7 Siri-style 波形 GIF

iOS 7 Siri-style waveform

iOS 9 Siri-style 波形 GIF

iOS 9 Siri-style waveform

使用方法

创建iOS 7 Siri风格的波形

要创建一个iOS 7 Siri风格的波形,可以使用 SiriWaveform.ios7() 构造函数:

import 'package:siri_wave/siri_wave.dart';

class MyWidget extends StatelessWidget {
  MyWidget({super.key});

  @override
  Widget build(BuildContext context) => SiriWaveform.ios7();
}

你可以通过传递 controller 和/或 options 来自定义波形:

class MyWidget extends StatelessWidget {
  MyWidget({super.key});

  final controller = IOS7SiriWaveformController(
    amplitude: 0.5,
    color: Colors.red,
    frequency: 4,
    speed: 0.15,
  );

  @override
  Widget build(BuildContext context) => SiriWaveform.ios7(
        controller: controller,
        options: const IOS7SiriWaveformOptions(height: 200, width: 400),
      );
}

你也可以在之后更改波形的属性:

controller.amplitude = 0.3;
controller.color = Colors.white;

创建iOS 9 Siri风格的波形

要创建一个iOS 9 Siri风格的波形,可以使用 SiriWaveform.ios9() 构造函数:

import 'package:siri_wave/siri_wave.dart';

class MyWidget extends StatelessWidget {
  MyWidget({super.key});

  @override
  Widget build(BuildContext context) => SiriWaveform.ios9();
}

同样地,你可以通过传递 controller 和/或 options 来自定义波形:

class MyWidget extends StatelessWidget {
  MyWidget({super.key});

  final controller = IOS9SiriWaveformController(
    amplitude: 0.5,
    color1: Colors.red,
    color2: Colors.green,
    color3: Colors.blue,
    speed: 0.15,
  );

  @override
  Widget build(BuildContext context) => SiriWaveform.ios9(
        controller: controller,
        options: const IOS9SiriWaveformOptions(height: 200, width: 400),
      );
}

完整示例

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

import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:siri_wave/siri_wave.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) => MaterialApp(
        debugShowCheckedModeBanner: false,
        home: const HomePage(),
        darkTheme: ThemeData(brightness: Brightness.dark),
        themeMode: ThemeMode.dark,
        title: 'siri_wave Demo',
      );
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  double amplitude = 1;
  Color color = Colors.white;
  Color color1 = const Color(0xFFAD394C);
  Color color2 = const Color(0xFF30DC9B);
  Color color3 = const Color(0xFF0F52A9);
  SiriWaveformController controller = IOS9SiriWaveformController();
  double frequency = 6;
  final selection = [false, true];
  bool showSupportBar = true;
  double speed = .2;

  SiriWaveformStyle get style =>
      selection[0] ? SiriWaveformStyle.ios_7 : SiriWaveformStyle.ios_9;

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: const Text('siri_wave Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Spacer(),
              CustomSlider(
                onChanged: (value) {
                  controller.amplitude = value;
                  setState(() => amplitude = value);
                },
                label: 'Amplitude',
                value: amplitude,
              ),
              CustomSlider(
                onChanged: (value) {
                  controller.speed = value;
                  setState(() => speed = value);
                },
                label: 'Speed',
                value: speed,
              ),
              if (style == SiriWaveformStyle.ios_9) ...[
                CustomSwitch(
                  onChanged: (value) {
                    setState(() => showSupportBar = value);
                  },
                  value: showSupportBar,
                ),
                Wrap(
                  alignment: WrapAlignment.center,
                  spacing: 10,
                  children: [
                    ColorPickerWidget(
                      title: 'Color 1',
                      onChanged: (value) {
                        setState(() => color1 = value);
                        (controller as IOS9SiriWaveformController).color1 =
                            value;
                      },
                      color: color1,
                    ),
                    ColorPickerWidget(
                      title: 'Color 2',
                      onChanged: (value) {
                        setState(() => color2 = value);
                        (controller as IOS9SiriWaveformController).color2 =
                            value;
                      },
                      color: color2,
                    ),
                    ColorPickerWidget(
                      title: 'Color 3',
                      onChanged: (value) {
                        setState(() => color3 = value);
                        (controller as IOS9SiriWaveformController).color3 =
                            value;
                      },
                      color: color3,
                    )
                  ],
                ),
              ] else ...[
                FrequencySlider(
                  onChanged: (value) {
                    (controller as IOS7SiriWaveformController).frequency =
                        value.round();
                    setState(() => frequency = value);
                  },
                  value: frequency,
                ),
                ColorPickerWidget(
                  onChanged: (value) {
                    setState(() => color = value);
                    (controller as IOS7SiriWaveformController).color = value;
                  },
                  color: color,
                ),
              ],
              WaveformStyleToggleButtons(
                onPressed: (index) {
                  if (selection[index]) return;
                  for (var i = 0; i < selection.length; i++) {
                    selection[i] = i == index;
                  }
                  controller = index == 0
                      ? IOS7SiriWaveformController()
                      : IOS9SiriWaveformController();
                  setState(() {});
                },
                selection: selection,
              ),
              const Spacer(),
              const CustomDivider(),
              SiriWaveformWidget(
                controller: controller,
                showSupportBar: showSupportBar,
                style: style,
              ),
              const CustomDivider(),
            ],
          ),
        ),
      );
}

// 自定义滑块组件
class CustomSlider extends StatelessWidget {
  const CustomSlider({
    required this.onChanged,
    required this.label,
    required this.value,
    super.key,
  });

  final ValueChanged<double> onChanged;
  final String label;
  final double value;

  @override
  Widget build(BuildContext context) => Column(
        children: [
          Text(label, style: Theme.of(context).textTheme.titleLarge),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 5),
            child: SizedBox(
              width: 360,
              child: Slider(
                value: value,
                onChanged: onChanged,
              ),
            ),
          ),
        ],
      );
}

// 自定义开关组件
class CustomSwitch extends StatelessWidget {
  const CustomSwitch({
    required this.onChanged,
    required this.value,
    super.key,
  });

  final ValueChanged<bool> onChanged;
  final bool value;

  @override
  Widget build(BuildContext context) => AnimatedSize(
        curve: Curves.fastOutSlowIn,
        duration: const Duration(milliseconds: 400),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Show support bar',
              style: Theme.of(context).textTheme.titleLarge,
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 5),
              child: Switch(
                value: value,
                onChanged: onChanged,
              ),
            ),
          ],
        ),
      );
}

// 频率滑块组件
class FrequencySlider extends StatelessWidget {
  const FrequencySlider({
    required this.onChanged,
    required this.value,
    super.key,
  });

  final ValueChanged<double> onChanged;
  final double value;

  @override
  Widget build(BuildContext context) => AnimatedSize(
        curve: Curves.fastOutSlowIn,
        duration: const Duration(milliseconds: 400),
        child: Column(
          children: [
            Text(
              'Frequency',
              style: Theme.of(context).textTheme.titleLarge,
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 5),
              child: SizedBox(
                width: 360,
                child: Slider(
                  value: value,
                  divisions: 40,
                  min: -20,
                  max: 20,
                  onChanged: onChanged,
                ),
              ),
            ),
          ],
        ),
      );
}

// 颜色选择器组件
class ColorPickerWidget extends StatelessWidget {
  const ColorPickerWidget({
    required this.onChanged,
    required this.color,
    this.title = 'Color',
    super.key,
  });

  final ValueChanged<Color> onChanged;
  final Color color;
  final String title;

  @override
  Widget build(BuildContext context) => AnimatedSize(
        curve: Curves.fastOutSlowIn,
        duration: const Duration(milliseconds: 400),
        child: Column(
          children: [
            Text(
              title,
              style: Theme.of(context).textTheme.titleLarge,
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 15),
              child: ElevatedButton(
                onPressed: () async {
                  await showDialog<void>(
                    context: context,
                    builder: (context) => AlertDialog(
                      titlePadding: EdgeInsets.zero,
                      contentPadding: EdgeInsets.zero,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(9),
                      ),
                      content: SingleChildScrollView(
                        child: ColorPicker(
                          pickerColor: color,
                          onColorChanged: onChanged,
                          pickerAreaHeightPercent: .7,
                          displayThumbColor: true,
                          paletteType: PaletteType.hsl,
                          pickerAreaBorderRadius: BorderRadius.circular(8),
                        ),
                      ),
                    ),
                  );
                },
                child: const Text('Change color'),
              ),
            ),
          ],
        ),
      );
}

// 波形样式切换按钮
class WaveformStyleToggleButtons extends StatelessWidget {
  const WaveformStyleToggleButtons({
    required this.onPressed,
    required this.selection,
    super.key,
  });

  final ValueChanged<int> onPressed;
  final List<bool> selection;

  @override
  Widget build(BuildContext context) => Column(
        children: [
          Text('Style', style: Theme.of(context).textTheme.titleLarge),
          const SizedBox(height: 15),
          ToggleButtons(
            onPressed: onPressed,
            borderColor: Theme.of(context).primaryColorLight,
            borderRadius: BorderRadius.circular(16),
            isSelected: selection,
            selectedBorderColor: Theme.of(context).colorScheme.primary,
            children: const [
              Padding(padding: EdgeInsets.all(16), child: Text('iOS 7')),
              Padding(padding: EdgeInsets.all(16), child: Text('iOS 9')),
            ],
          ),
        ],
      );
}

// 自定义分割线
class CustomDivider extends StatelessWidget {
  const CustomDivider({super.key});

  @override
  Widget build(BuildContext context) => SizedBox(
        width: 360,
        child: Divider(
          color: Theme.of(context).colorScheme.primary,
          thickness: 1,
        ),
      );
}

// 波形显示组件
class SiriWaveformWidget extends StatelessWidget {
  const SiriWaveformWidget({
    required this.controller,
    required this.style,
    this.showSupportBar = true,
    super.key,
  });

  final SiriWaveformController controller;
  final bool showSupportBar;
  final SiriWaveformStyle style;

  @override
  Widget build(BuildContext context) => style == SiriWaveformStyle.ios_7
      ? SiriWaveform.ios7(
          controller: controller as IOS7SiriWaveformController,
          options: const IOS7SiriWaveformOptions(
            height: 180,
            width: 360,
          ),
        )
      : SiriWaveform.ios9(
          controller: controller as IOS9SiriWaveformController,
          options: IOS9SiriWaveformOptions(
            height: 180,
            showSupportBar: showSupportBar,
            width: 360,
          ),
        );
}

API 文档

更多详细信息,请参阅 API文档

贡献

欢迎贡献代码、提交问题和功能请求。请参考 issue tracker 获取更多信息。


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

1 回复

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


当然,下面是一个关于如何在Flutter中使用siri_wave插件来实现Siri风格的波浪动画效果的代码案例。

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

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

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

接下来,你可以在你的Flutter应用中使用SiriWave组件来实现动画效果。以下是一个完整的示例代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Siri Wave Animation Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SiriWaveDemoPage(),
    );
  }
}

class SiriWaveDemoPage extends StatefulWidget {
  @override
  _SiriWaveDemoPageState createState() => _SiriWaveDemoPageState();
}

class _SiriWaveDemoPageState extends State<SiriWaveDemoPage> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Siri Wave Animation Demo'),
      ),
      body: Center(
        child: SiriWave(
          animation: _controller,
          color: Colors.blueAccent,
          height: 50.0,
          waveCount: 3,
          waveSpeed: 0.05,
          amplitude: 20.0,
          frequency: 0.05,
          backgroundColor: Colors.white,
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个SiriWaveDemoPage页面,并在其中使用SiriWave组件。SiriWave组件接受几个参数来配置波浪动画的效果:

  • animation: 一个AnimationController对象,用于控制动画的播放。
  • color: 波浪的颜色。
  • height: 波浪的高度。
  • waveCount: 波浪的数量。
  • waveSpeed: 波浪的移动速度。
  • amplitude: 波浪的振幅。
  • frequency: 波浪的频率。
  • backgroundColor: 背景颜色。

initState方法中,我们初始化了一个AnimationController,并将其duration设置为2秒,然后调用repeat(reverse: true)方法使其不断正向和反向播放。

最后,在dispose方法中,我们调用_controller.dispose()来释放资源。

这个示例展示了如何使用siri_wave插件来创建一个简单的Siri风格的波浪动画效果。你可以根据需要调整参数来实现不同的动画效果。

回到顶部