Flutter Animations

Jun's Coding Journey·2023년 10월 1일
0

[Learn] Flutter

목록 보기
22/22

Implicit Animations


Overview

Implicit animations in Flutter are encapsulated within a particular set of widgets. They provide a smooth transition between different configurations of a widget over a specified duration, without the need for a detailed step-by-step description.

 

Animated Opacity

AnimatedOpacity is a widget that automatically transitions a child's opacity over a given duration whenever the given opacity changes. It's an implicit animation widget, which means you only specify the start and end states, and the widget takes care of the animation for you.

AnimatedOpacity(
  opacity: _isVisible ? 1.0 : 0.0,
  duration: Duration(seconds: 1),
  child: Text('Fade me in/out!'),
),

 

Animated Container

AnimatedContainer is a widget that gradually changes its values over a period of time. It's an implicit animation widget, which means that you only need to define its target state, and the framework automatically transitions from the current state to that target state over a specified duration.

AnimatedContainer(
  duration: Duration(seconds: 2),
  width: _isExpanded ? 200.0 : 100.0,
  height: _isExpanded ? 200.0 : 100.0,
  color: _isExpanded ? Colors.red : Colors.blue,
  child: Center(child: Text('Tap Me!')),
),

 

Tween Animation Builder

TweenAnimationBuilder is a widget in Flutter that simplifies the process of creating animations. It can produce the desired visual effect without requiring a StatefulWidget or manual control of an AnimationController.

TweenAnimationBuilder<double>(
  tween: Tween<double>(begin: 0, end: 1),
  duration: Duration(seconds: 2),
  curve: Curves.easeInOut,
  builder: (BuildContext context, double value, Widget? child) {
    return Opacity(
      opacity: value,
      child: Text('Hello World!'),
    );
  },
)

 

Explicit Animations


Overview

Explicit animations in Flutter are more verbose than implicit animations but offer more control and flexibility. They are suitable for scenarios where you need detailed control over the animation process or when creating intricate animation choreographies.

 

Animation Controller w/ Ticker

The AnimationController is a special type of animation that produces a linear sequence of values over a specified duration. It gives you control over the animation, letting you start, stop, reverse, and control other aspects of the animation.

The animation controller works with the SingleTickerProviderStateMixin to establish a Ticker, which is a mechanism to notify its listeners as the next frame is ready to be rendered. It's necessary for the AnimationController to advance its animation value by a tiny bit with each frame.

// animation controller
AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,  // This typically comes from the SingleTickerProviderStateMixin.
);
// single ticker provder state mixin
class _MyAnimatedWidgetState extends State<MyAnimatedWidget> with SingleTickerProviderStateMixin {
  AnimationController? _controller;

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

  // ... other code ...
}

 

Animated Builder

AnimatedBuilder is a widget that helps you create custom animations more efficiently by rebuilding only the widgets that need to be updated instead of rebuilding the entire widget tree.

When using animations in Flutter, it's common to rebuild a part of the widget tree when the animation changes. The AnimatedBuilder widget allows you to extract the animation logic and the widget tree that depends on the animation into a separate builder function. This way, only the subtree that needs updating is rebuilt, resulting in potentially better performance.

AnimationController controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this, // typically `this` refers to a `TickerProvider`, often a `State` object.
);

Animation<double> opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(controller);

AnimatedBuilder(
  animation: opacityAnimation,
  builder: (BuildContext context, Widget? child) {
    return Opacity(
      opacity: opacityAnimation.value,
      child: child,
    );
  },
  child: FlutterLogo(size: 100.0),
)

 

Tween

Tween is a way to define a range between a beginning and an ending value. Tween can interpolate smoothly between these values. When you're dealing with animations, you often want to transition between two values, and that's where Tween comes in.

AnimationController controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this, // `this` usually refers to a `TickerProvider`, typically a `State` object.
);

Animation<Color?> colorAnimation = ColorTween(
  begin: Colors.red,
  end: Colors.blue,
).animate(controller);

// Use `colorAnimation` in an `AnimatedBuilder` or an `AnimatedWidget` to update the UI.

 

Explicit Widgets

Just like implicit widgets, we also have explicit widgets which are tools we can use to display a type of animation using the animation controller.

Using explicit widgets, we can provide animation with position, rotatation, scale, size, slide, and so on.

A list of explicit widgets can be found here:
https://docs.flutter.dev/ui/widgets/animation

 

Curved Animation

Curved animation doesn't specifically refer to an animation that follows a visual curve on the screen. Instead, it pertains to how an animation progresses over time according to a defined curve, giving developers the capability to manipulate the speed and transition pattern of the animation.

For instance, rather than an animation linearly transitioning from one value to another, a curved animation allows you to make the transition start slow, become faster, and then slow down again, or any other pattern defined by the curve.

AnimationController controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,
);

// Apply curve to the animation.
Animation<double> curve = CurvedAnimation(
  parent: controller,
  curve: Curves.easeInOut, // Using predefined ease-in, ease-out curve
);

controller.forward(); // This starts the animation.

 

Value Notifier

ValueNotifier is a simple way to manage and respond to changes in a single value. It is a type of Listenable, which means you can listen to changes in its value.

Essentially, when you modify the value contained within a ValueNotifier, any listeners attached to that ValueNotifier are notified. This can be used to rebuild UI or trigger other side effects when the value changes.

ValueNotifier<int> counter = ValueNotifier<int>(0);

counter.addListener(() {
  // Do something when the value changes.
  print('Counter value: ${counter.value}');
});

counter.value = 5; // This will trigger the listener and print the new value.

ValueListenableBuilder<int>(
  valueListenable: counter,
  builder: (context, value, child) {
    return Text('Counter: $value');
  },
);

counter.dispose();

 

Animation Status

In Flutter, when dealing with animations, it's often useful to know the current state or "status" of an animation. The AnimationStatus is an enumeration that represents these possible states for animations.

AnimationController controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,
);

controller.addStatusListener((status) {
  if (status == AnimationStatus.completed) {
    // Do something when the animation completes
  } else if (status == AnimationStatus.dismissed) {
    // Do something when the animation is at the starting point
  } // ... Handle other statuses as needed
});

// Starting the animation
controller.forward();

 

Custom Painter


Overview

CustomPainter is a class that allows developers to draw custom designs, graphics, and visuals directly on the screen. It provides a canvas on which you can draw with a wide range of graphic primitives, from lines and shapes to paths and text.

When you want to create custom graphics or visuals in Flutter, you typically work with the CustomPaint widget, which takes a painter: a class that you've created which extends the CustomPainter abstract class.

class MyCustomPainter extends CustomPainter {
  
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 5.0
      ..style = PaintingStyle.fill;

    final Offset center = Offset(size.width / 2, size.height / 2);
    final double radius = size.width * 0.4;

    canvas.drawCircle(center, radius, paint);
  }

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}
CustomPaint(
  painter: MyCustomPainter(),
  child: ... , // You can have a child for this widget if needed.
)

 

drawArc

drawArc method is used to draw a segment of an ellipse (or a full ellipse/circle) on a Canvas. It's a method available to the Canvas object and is commonly used within the paint method of a CustomPainter.

void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
class MyArcPainter extends CustomPainter {
  
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill; // This will fill the arc with the color

    final Rect rect = Rect.fromCenter(
      center: Offset(size.width / 2, size.height / 2),
      width: size.width * 0.8,
      height: size.height * 0.5,
    );

    final double startAngle = -pi / 2; // top of the canvas
    final double sweepAngle = pi; // half circle

    canvas.drawArc(rect, startAngle, sweepAngle, true, paint); // this will draw a semi-circle (half pie slice)
  }

  
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

 


 

Interpolation


Interpolation in Flutter animation refers to the process of determining intermediate values between two endpoints, based on a factor that progresses over time. It's a fundamental concept in animations, as it allows smooth transitions between values over a specified duration.

AnimationController controller = AnimationController(
  duration: Duration(seconds: 1),
  vsync: this,
);

Animation<double> animation = Tween<double>(begin: 0.0, end: 1.0).animate(
  CurvedAnimation(parent: controller, curve: Curves.easeInOut),
);

controller.forward();  // This starts the animation.

 

Page View Builder


PageView is a scrollable widget that displays its children in a sequence, allowing users to swipe between them. It works in a way similar to view pagers or carousel sliders in other frameworks.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final PageController _controller = PageController(initialPage: 0);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("PageView Example"),
      ),
      body: PageView(
        controller: _controller,
        children: <Widget>[
          Center(child: Text("Page 1")),
          Center(child: Text("Page 2")),
          Center(child: Text("Page 3")),
        ],
      ),
    );
  }
}

 

Page Controller


PageController is primarily used with the PageView widget to display a scrollable list that works page by page. It allows you to programmatically set which page is visible, animate to a specific page, listen to changes in page visibility, and more.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  PageController _controller = PageController(
    initialPage: 0,
  );

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("PageView Example"),
      ),
      body: PageView(
        controller: _controller,
        children: <Widget>[
          Center(child: Text("Page 1")),
          Center(child: Text("Page 2")),
          Center(child: Text("Page 3")),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Animate to the second page
          _controller.animateToPage(
            1,
            duration: Duration(seconds: 1),
            curve: Curves.easeInOut,
          );
        },
        child: Icon(Icons.navigate_next),
      ),
    );
  }
}

 

Animated Switcher


AnimatedSwitcher widget allows you to smoothly transition between two or more widgets with an animation. Whenever a new child is provided to the AnimatedSwitcher, it cross-fades from the previous widget to the new one. This can be very useful when you want to change the content of a part of your app’s UI and want to introduce some smooth transition effects between the changes.

class MyAnimatedSwitcher extends StatefulWidget {
  
  _MyAnimatedSwitcherState createState() => _MyAnimatedSwitcherState();
}

class _MyAnimatedSwitcherState extends State<MyAnimatedSwitcher> {
  bool _showFirst = true;

  
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        AnimatedSwitcher(
          duration: Duration(seconds: 1),
          child: _showFirst
              ? Text(
                  'First Text',
                  key: ValueKey<int>(1), // Unique key is crucial!
                )
              : Text(
                  'Second Text',
                  key: ValueKey<int>(2), // Unique key is crucial!
                ),
        ),
        ElevatedButton(
          child: Text('Switch Text'),
          onPressed: () {
            setState(() {
              _showFirst = !_showFirst;
            });
          },
        ),
      ],
    );
  }
}

 

Page Route Builder


PageRouteBuilder is a utility class that helps you create custom route transitions for your app's pages/screens. It provides more flexibility than the standard page routes, like MaterialPageRoute or CupertinoPageRoute, by allowing you to define custom animations for the transition.

Using PageRouteBuilder, you can define both the page transition animation and the actual page widget to be displayed. The builder provides you with an animation object, a secondary animation object, and a context. These can be used to create a custom animation that plays when the route is pushed or popped.

Navigator.of(context).push(
  PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => MyNewScreen(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      const begin = Offset(1.0, 0.0);
      const end = Offset.zero;
      const curve = Curves.easeInOut;
      var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
      var offsetAnimation = animation.drive(tween);

      return SlideTransition(position: offsetAnimation, child: child);
    },
  ),
);

Marquee


Marquee is a Flutter widget that scrolls text infinitely. Provides many customizations including custom scroll directions, durations, curves as well as pauses after every round.

Marquee(
  text: 'Some sample text that takes some space.',
  style: TextStyle(fontWeight: FontWeight.bold),
  scrollAxis: Axis.horizontal,
  crossAxisAlignment: CrossAxisAlignment.start,
  blankSpace: 20.0,
  velocity: 100.0,
  pauseAfterRound: Duration(seconds: 1),
  startPadding: 10.0,
  accelerationDuration: Duration(seconds: 1),
  accelerationCurve: Curves.linear,
  decelerationDuration: Duration(milliseconds: 500),
  decelerationCurve: Curves.easeOut,
)

 

Lottie


Lottie is a popular open-source library that allows for the rendering of Adobe After Effects animations natively on mobile, web, and desktop applications. Lottie animations are exported as a JSON file using the Bodymovin plugin for After Effects.

In the context of Flutter, Lottie provides a way to use these animations in your Flutter apps without needing to recreate them manually using Flutter's own animation framework. This is particularly useful as it helps developers maintain a consistent look and feel across platforms and reduces the amount of manual animation work.

import 'package:lottie/lottie.dart';

// ...

Lottie.asset('assets/lottie_animation.json')

 

Interval


The Interval class is part of Flutter's animation library, which is used for creating animations. It represents a normalized interval between two points in time, where 0.0 represents the start of the interval, and 1.0 represents the end. You can think of it as specifying how far along an animation should be at a certain point in time.

The Interval class is commonly used in combination with other animation classes like Tween and CurvedAnimation to control the progress of an animation over time. For example, you can use it to specify that an animation should only happen between 20% and 80% of its duration.

import 'package:flutter/animation.dart';

// Define an interval for the animation to occur between 20% and 80% of its duration.
final Interval interval = Interval(0.2, 0.8);

// Create a Tween using the interval.
final Tween<double> tween = Tween<double>(
  begin: 0.0,
  end: 1.0,
).chain(CurveTween(curve: Curves.easeInOut)).chain(Interval(0.2, 0.8));

profile
Greatness From Small Beginnings

0개의 댓글