flutter_animate_plus 5.1.0 copy "flutter_animate_plus: ^5.1.0" to clipboard
flutter_animate_plus: ^5.1.0 copied to clipboard

A maintained fork of flutter_animate with beautiful animated effects and builders for Flutter.

example/lib/main.dart

import 'dart:ui';

import 'package:flutter/material.dart';

import 'about_page.dart';
import 'demo_playback.dart';
import 'examples/adapter_view.dart';
import 'examples/everything_view.dart';
import 'examples/info_view.dart';
import 'examples/playground_view.dart';
import 'examples/visual_view.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  try {
    final program = await FragmentProgram.fromAsset(
      'assets/shaders/shader.frag',
    );
    EverythingView.shader = program.fragmentShader();
  } catch (error, stack) {
    FlutterError.reportError(
      FlutterErrorDetails(exception: error, stack: stack),
    );
  }
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key, this.initialTab = 0});

  final int initialTab;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Animate Plus',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        brightness: Brightness.dark,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF80DDFF),
          brightness: Brightness.dark,
          surface: const Color(0xFF141A22),
        ),
        scaffoldBackgroundColor: const Color(0xFF10151C),
      ),
      home: FlutterAnimateExample(initialTab: initialTab),
    );
  }
}

class FlutterAnimateExample extends StatefulWidget {
  const FlutterAnimateExample({super.key, this.initialTab = 0})
    : assert(initialTab >= 0 && initialTab < 5);

  final int initialTab;

  static final List<TabInfo> tabs = [
    TabInfo(
      Icons.auto_awesome_outlined,
      (_) => const InfoView(),
      'Overview',
      'Compose expressive motion with a few lines of Dart.',
    ),
    TabInfo(
      Icons.palette_outlined,
      (_) => const VisualView(),
      'Visual',
      'Watch saturation, tint and blur work together.',
    ),
    TabInfo(
      Icons.tune,
      (_) => const AdapterView(),
      'Adapters',
      'Drive animation with a slider or scroll position.',
    ),
    TabInfo(
      Icons.grid_view_outlined,
      (_) => const EverythingView(),
      'Effects',
      'Explore individual effects and layered combinations.',
    ),
    TabInfo(
      Icons.science_outlined,
      (_) => const PlaygroundView(),
      'Playground',
      'A small starting point for your next animation.',
    ),
  ];

  @override
  State<FlutterAnimateExample> createState() => _FlutterAnimateExampleState();
}

class _FlutterAnimateExampleState extends State<FlutterAnimateExample> {
  late int _viewIndex = widget.initialTab;
  int _replay = 0;
  bool _playing = true;
  bool _allowMotion = false;

  void _select(int index) => setState(() {
    _viewIndex = index;
    _replay++;
  });

  @override
  Widget build(BuildContext context) {
    final tab = FlutterAnimateExample.tabs[_viewIndex];
    final reducedMotion = MediaQuery.disableAnimationsOf(context);
    final staticMode = reducedMotion && !_allowMotion;
    return LayoutBuilder(
      builder: (context, constraints) {
        final useRail =
            constraints.maxWidth >= 720 && constraints.maxHeight >= 500;
        final content = Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(24, 20, 12, 16),
              child: Row(
                children: [
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          tab.label,
                          style: Theme.of(context).textTheme.titleLarge,
                        ),
                        if (constraints.maxHeight >= 500 &&
                            MediaQuery.textScalerOf(context).scale(14) <
                                20) ...[
                          const SizedBox(height: 4),
                          Text(
                            tab.description,
                            style: const TextStyle(color: Color(0xFFAEBBCB)),
                          ),
                        ],
                      ],
                    ),
                  ),
                  if (!staticMode)
                    IconButton(
                      tooltip: _playing
                          ? 'Pause animation'
                          : 'Resume animation',
                      onPressed: () => setState(() => _playing = !_playing),
                      icon: Icon(_playing ? Icons.pause : Icons.play_arrow),
                    ),
                  IconButton(
                    tooltip: 'Replay animation',
                    onPressed: () {
                      if (staticMode) {
                        setState(() {
                          _allowMotion = true;
                          _playing = true;
                          _replay++;
                        });
                      } else {
                        setState(() {
                          _playing = true;
                          _replay++;
                        });
                      }
                    },
                    icon: const Icon(Icons.replay),
                  ),
                  IconButton(
                    tooltip: 'About Flutter Animate Plus',
                    onPressed: () => Navigator.of(context).push(
                      MaterialPageRoute<void>(
                        builder: (_) => const AboutPage(),
                      ),
                    ),
                    icon: const Icon(Icons.info_outline),
                  ),
                ],
              ),
            ),
            if (reducedMotion)
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: Wrap(
                  crossAxisAlignment: WrapCrossAlignment.center,
                  spacing: 8,
                  children: [
                    Text(
                      staticMode
                          ? 'Reduced motion · static previews'
                          : 'Motion enabled for this session',
                    ),
                    TextButton(
                      onPressed: () => setState(() {
                        _allowMotion = !_allowMotion;
                        _playing = _allowMotion;
                      }),
                      child: Text(
                        staticMode ? 'Enable demos' : 'Use static previews',
                      ),
                    ),
                  ],
                ),
              ),
            const Divider(height: 1),
            Expanded(
              child: KeyedSubtree(
                key: ValueKey('$_viewIndex:$_replay'),
                child: DemoPlayback(
                  playing: _playing,
                  staticMode: staticMode,
                  child: _viewIndex == 0
                      ? InfoView(onNavigate: _select)
                      : tab.builder(context),
                ),
              ),
            ),
          ],
        );
        return Scaffold(
          bottomNavigationBar: useRail
              ? null
              : NavigationBar(
                  selectedIndex: _viewIndex,
                  onDestinationSelected: _select,
                  labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
                  destinations: [
                    for (final item in FlutterAnimateExample.tabs)
                      NavigationDestination(
                        icon: Icon(item.icon),
                        label: item.label,
                      ),
                  ],
                ),
          body: SafeArea(
            bottom: useRail,
            child: DefaultTextStyle(
              style: const TextStyle(
                fontFamily: 'Roboto',
                color: Color(0xFFE6EDF5),
                fontSize: 14,
                height: 1.5,
              ),
              child: Row(
                children: [
                  if (useRail) ...[
                    NavigationRail(
                      selectedIndex: _viewIndex,
                      onDestinationSelected: _select,
                      labelType: NavigationRailLabelType.all,
                      leading: const Padding(
                        padding: EdgeInsets.symmetric(vertical: 20),
                        child: Icon(
                          Icons.animation,
                          color: Color(0xFF80DDFF),
                          size: 32,
                        ),
                      ),
                      destinations: [
                        for (final item in FlutterAnimateExample.tabs)
                          NavigationRailDestination(
                            icon: Icon(item.icon),
                            label: Text(item.label),
                          ),
                      ],
                    ),
                    const VerticalDivider(width: 1),
                  ],
                  Expanded(child: content),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}

class TabInfo {
  const TabInfo(this.icon, this.builder, this.label, this.description);
  final IconData icon;
  final WidgetBuilder builder;
  final String label;
  final String description;
}
2
likes
160
points
87
downloads

Documentation

API reference

Publisher

verified publisherhensell.dev

Weekly Downloads

A maintained fork of flutter_animate with beautiful animated effects and builders for Flutter.

Repository (GitHub)
View/report issues

Topics

#animation #ui #effects #widget

License

BSD-3-Clause (license)

Dependencies

flutter, flutter_shaders

More

Packages that depend on flutter_animate_plus