flutterdartanimationtext

Flutter Issue: Simultaneous Animation of Opacity and Font Size


In Flutter I am trying to animate Opacity and Font Size at the same time, but with different Curves. Unfortunately it cuts off the text at the top and bottom during the animation. It is maybe difficult to reproduce because it happens only on my physical device (Samsung S21) and not on the emulator. Also it doesn´t happen on all default font sizes, configured in the settings of the device. Does anyone know the cause or a possible fix?

See GIF for example below

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{

  late AnimationController _controller;
  late Animation<double> _fontSizeAnimation;
  late Animation<double> _opacityAnimation;
  late TextStyleTween _styleTween;
  late Tween<double> _opacityTween;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(duration: const Duration(seconds: 2), vsync: this);
    _fontSizeAnimation = CurvedAnimation(parent: _controller, curve: Curves.elasticOut);
    _opacityAnimation = CurvedAnimation(parent: _controller, curve: Curves.easeOutCirc)
      ..addListener(() {
        setState(() {

        });
      });
    _styleTween = TextStyleTween(
      begin: const TextStyle(fontSize: 0, color: Colors.black), end: const TextStyle(fontSize: 50, color: Colors.black),
    );
    _opacityTween = Tween<double>(begin: 0.0, end: 1.0);
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Opacity(
          opacity: _opacityTween.evaluate(_opacityAnimation),
          child: DefaultTextStyleTransition(
              style: _styleTween.animate(_fontSizeAnimation),
              child: const Text('2'),
          ),
        )
      ),
      floatingActionButton: FloatingActionButton(onPressed: () {
        _controller.forward(from: 0.0);
      },
      ),
    );
  }
}

I tried different approaches to animate, e.g. using AnimatedBuilder and also tried different Containers (Center, Container, SizedBox) to rule out any clipping issues.


Solution

  • You can use package: flutter_animate

    Note: It also supports AnimationController to handle animations based on actions.

    Text(
         "2",
         style: TextStyle(
         fontSize: 20,
         fontWeight: FontWeight.w500,
          ),
         ).animate().fade(duration: 100.ms).scale(delay: 100.ms)