Flutter-自定义表情雨下落动画

简介: Flutter-自定义表情雨下落动画
简述

今天给大家分享一个Flutter的表情雨的实现,具体的效果见下图,这个效果其实是工作中的一个小小的需求,这里面单独拿出来讲讲下这个效果的实现思路。


在以前特别是新手,遇到一些动画效果都是拿到需求后,在网络上去找寻类似的效果,然后修改修改就可以了,不知道你们是不是呢?其实从chatgpt出来以后,很多时候对于这种效果我们其实直接就可以问下gpt,gpt会给我们一些思路,只要我们表达的清晰,配合gpt我们会很快实现这个效果。

效果图

分析

我们如何去问gpt,才能让gpt给出我们想要的结果呢?当然在以前我们都是自己先了解这个效果属于什么效果,比如说 “跑马灯”、“画廊”等等,然后在网络搜索这个关键字查询。但是现在我们不是单纯的搜关键字了,而是用自己的语言把效果用话语表达出来,让gpt知道到底怎么写代码,总结来说你就是产品,gpt是开发人员,你要把产品需求告诉gpt去开发。

ChatGpt问答

用户问:请使用Flutter实现一个widget,这个widget支持设置宽高,其内容是由n个表情从上往下落下,这些表情下落的时机是间隔落下,下落过程中透明度在高度一半的时候透明度逐渐隐藏。

注意: 这里我使用的gpt是3.5版本。

gpt回答代码如下:

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';

class FallingEmojisWidget extends StatefulWidget {
 final double width;
 final double height;
 final List<String> emojis;
 final Duration interval;

 const FallingEmojisWidget({
   Key? key,
   required this.width,
   required this.height,
   required this.emojis,
   this.interval = const Duration(milliseconds: 500),
 }) : super(key: key);

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

class _FallingEmojisWidgetState extends State<FallingEmojisWidget>
   with TickerProviderStateMixin {
 late AnimationController _animationController;
 late Timer _timer;

 List<Widget> _emojiWidgets = [];

 @override
 void initState() {
   super.initState();
   _animationController = AnimationController(
     vsync: this,
     duration: Duration(milliseconds: 1000),
   );
   _timer = Timer.periodic(widget.interval, (_) => _addEmoji());
 }

 @override
 void dispose() {
   _animationController.dispose();
   _timer.cancel();
   super.dispose();
 }

 void _addEmoji() {
   setState(() {
     final emoji = widget.emojis[Random().nextInt(widget.emojis.length)];
     _emojiWidgets.add(_buildEmojiWidget(emoji));
   });
 }

 Widget _buildEmojiWidget(String emoji) {
   final initialOffset = Offset(
     Random().nextDouble() * widget.width,
     -50,
   );
   final targetOffset = Offset(
     initialOffset.dx,
     widget.height / 2,
   );

   final animation = Tween<Offset>(
     begin: initialOffset,
     end: targetOffset,
   ).animate(CurvedAnimation(
     parent: _animationController,
     curve: Curves.easeInOut,
   ));

   return AnimatedBuilder(
     animation: _animationController,
     builder: (context, child) {
       final opacity = _animationController.value < 0.5
           ? (_animationController.value * 2)
           : (1 - (_animationController.value - 0.5) * 2);

       return Positioned(
         left: animation.value.dx,
         top: animation.value.dy,
         child: Opacity(
           opacity: opacity,
           child: Text(
             emoji,
             style: TextStyle(fontSize: 24),
           ),
         ),
       );
     },
   );
 }

 @override
 Widget build(BuildContext context) {
   return Container(
     width: widget.width,
     height: widget.height,
     child: Stack(
       children: _emojiWidgets,
     ),
   );
 }
}`

gpt第一次回答你的代码其实已经告诉你实现思路了,比如上面的代码,通过gpt的回答我们知道可以使用Stack控件,然后在Stack中添加我们想要的数量的表情widget,然后通过AnimatedBuilder+Positioned实现表情下落的效果。是不是很6,从开始没有思路立马就知道如何实现了,你其实可以直接copy gpt的回答然后运行看看,在此基础上修改修改就ok了。下面是我修改后的完整代码。

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

/// 表情下落动画
class EmojiAnimWidget extends StatefulWidget {
  const EmojiAnimWidget(
      {Key? key,
      required this.width,
      required this.height,
      this.emojiNum = 6,
      this.duration = const Duration(seconds: 5)})
      : super(key: key);

  final double width;
  final double height;
  final int emojiNum;
  final Duration duration;

  @override
  State<EmojiAnimWidget> createState() => EmojiAnimWidgetState();
}

class EmojiAnimWidgetState extends State<EmojiAnimWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  List<Widget>? _emojis;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: widget.duration,
    );
  }

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

  /// 开始表情动画
  void startEmojiAnim(String emoji) {
    _emojis = List.generate(widget.emojiNum, (index) {
      var delay = Random().nextInt(150).toDouble() + 50;
      var fontSize = Random().nextInt(9).toDouble() + 18.0;
      var animation = Tween<double>(
        begin: 0.0,
        end: 1.0,
      ).animate(CurvedAnimation(
        parent: _animationController,
        curve: Interval(delay / 500, (delay + 300) / 500, curve: Curves.linear),
      ));
      return AnimatedBuilder(
        animation: _animationController,
        builder: (context, child) {
          var opacity = 1 - animation.value;
          return Positioned(
            left: (widget.width - 32) / widget.emojiNum * index,
            top: -delay + animation.value * (widget.height + delay),
            child: Opacity(
              opacity: (opacity > 0.5) ? 1 : opacity,
              child: Container(
                height: 50,
                color: Colors.transparent,
                alignment: Alignment.center,
                child: Text(
                  emoji,
                  style: TextStyle(fontSize: fontSize, height: 1.2),
                  textAlign: TextAlign.center,
                ),
              ),
            ),
          );
        },
      );
    });
    setState(() {
      _animationController.stop();
      _animationController.repeat();
      _animationController.forward();
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_emojis == null) return Container();
    return Container(
      alignment: Alignment.center,
      padding: const EdgeInsets.only(left: 16, right: 16),
      width: widget.width,
      height: widget.height,
      child: Stack(
        clipBehavior: Clip.none,
        children: _emojis!,
      ),
    );
  }
}
相关文章
|
1月前
|
开发工具 UED 容器
Flutter&鸿蒙next 实现长按录音按钮及动画特效
本文介绍了如何在 Flutter 中实现一个带有动画效果的长按录音按钮。通过使用 `GestureDetector` 监听长按手势,结合 `AnimatedContainer` 和 `AnimationController` 实现按钮的动画效果,以及 `flutter_sound` 插件完成录音功能。文章详细讲解了功能需求、实现思路和代码实现,帮助读者逐步掌握这一实用功能的开发方法。
122 5
|
1月前
|
UED 开发者 容器
Flutter&鸿蒙next 的 Sliver 实现自定义滚动效果
Flutter 提供了强大的滚动组件,如 ListView 和 GridView,但当需要更复杂的滚动效果时,Sliver 组件是一个强大的工具。本文介绍了如何使用 Sliver 实现自定义滚动效果,包括 SliverAppBar、SliverList 等常用组件的使用方法,以及通过 CustomScrollView 组合多个 Sliver 组件实现复杂布局的示例。通过具体代码示例,展示了如何实现带有可伸缩 AppBar 和可滚动列表的页面。
110 1
|
1月前
Flutter 自定义组件继承与调用的高级使用方式
本文深入探讨了 Flutter 中自定义组件的高级使用方式,包括创建基本自定义组件、继承现有组件、使用 Mixins 和组合模式等。通过这些方法,您可以构建灵活、可重用且易于维护的 UI 组件,从而提升开发效率和代码质量。
131 1
|
1月前
|
前端开发 开发者
深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画
本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。
80 1
|
1月前
|
Dart UED 开发者
Flutter&鸿蒙next中的按钮封装:自定义样式与交互
在Flutter应用开发中,按钮是用户界面的重要组成部分。Flutter提供了多种内置按钮组件,但有时这些样式无法满足特定设计需求。因此,封装一个自定义按钮组件变得尤为重要。自定义按钮组件可以确保应用中所有按钮的一致性、可维护性和可扩展性,同时提供更高的灵活性,支持自定义颜色、形状和点击事件。本文介绍了如何创建一个名为CustomButton的自定义按钮组件,并详细说明了其样式、形状、颜色和点击事件的处理方法。
86 1
|
1月前
|
Dart 搜索推荐 API
Flutter & 鸿蒙next版本:自定义对话框与表单验证的动态反馈与错误处理
在现代移动应用开发中,用户体验至关重要。本文探讨了如何在 Flutter 与鸿蒙操作系统(HarmonyOS)中创建自定义对话框,并结合表单验证实现动态反馈与错误处理,提升用户体验。通过自定义对话框和表单验证,开发者可以提供更加丰富和友好的交互体验,同时利用鸿蒙next版本拓展应用的受众范围。
84 1
|
2月前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
|
2月前
|
UED
flutter:动画&状态管理 (十三)
本文档介绍了Flutter中`animatedList`的使用方法和状态管理的示例。`animatedList`用于创建带有动画效果的列表,示例代码展示了如何添加、删除列表项,并执行相应的动画效果。状态管理部分通过一个简单的点击切换颜色的示例,演示了如何在Flutter中管理组件的状态。
|
3月前
|
前端开发 搜索推荐
Flutter中自定义气泡框效果的实现
Flutter中自定义气泡框效果的实现
114 3
|
4月前
|
前端开发
Flutter快速实现自定义折线图,支持数据改变过渡动画
Flutter快速实现自定义折线图,支持数据改变过渡动画
109 4
Flutter快速实现自定义折线图,支持数据改变过渡动画