Widgets for creating Hero-like animations between two widgets within the same screen.

Overview

flutter_sidekick

Widgets for creating Hero-like animations between two widgets within the same screen.

Pub Donate

Logo

Overview

Features

  • Hero-like animations.
  • Allow you to specify a different animation for each Sidekick.
  • Widget to manage animations between children of two multi-child widgets.

Getting started

In the pubspec.yaml of your flutter project, add the following dependency: The latest version is Pub

dependencies:
  ...
  flutter_sidekick: ^latest_version

In your library add the following import:

import 'package:flutter_sidekick/flutter_sidekick.dart';

For help getting started with Flutter, view the online documentation.

Widgets

Sidekick

The Sidekick widget is heavily inspired by the Hero widget API. To link two sidekicks, the targetTag property of the one denoted as the source must be identical to the tag property of the other one, denoted the target. Then to animate sidekicks, you can use the SidekickController and one of the move function.

The animation below can be created with the following code:

Simple Overview

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

class SimpleExample extends StatefulWidget {
  @override
  _SimpleExampleState createState() => _SimpleExampleState();
}

class _SimpleExampleState extends State<SimpleExample>
    with TickerProviderStateMixin {
  SidekickController controller;

  @override
  void initState() {
    super.initState();
    controller =
        SidekickController(vsync: this, duration: Duration(seconds: 1));
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          top: 20.0,
          left: 20.0,
          width: 100.0,
          height: 100.0,
          child: GestureDetector(
            onTap: () => controller.moveToTarget(context),
            child: Sidekick(
              tag: 'source',
              targetTag: 'target',
              child: Container(
                color: Colors.blue,
              ),
            ),
          ),
        ),
        Positioned(
          bottom: 20.0,
          right: 20.0,
          width: 150.0,
          height: 100.0,
          child: GestureDetector(
            onTap: () => controller.moveToSource(context),
            child: Sidekick(
              tag: 'target',
              child: Container(
                color: Colors.blue,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

SidekickTeamBuilder

The SidekickTeamBuilder widget can be used to create complex layouts, where widgets from one container can be moved to another one, and you want the transition to be animated:

Wrap Overview

import 'package:example/widgets/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_sidekick/flutter_sidekick.dart';

class Item {
  Item({
    this.id,
  });
  final int id;
}

class WrapExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SidekickTeamBuilder<Item>(
      initialSourceList: List.generate(20, (i) => Item(id: i)),
      builder: (context, sourceBuilderDelegates, targetBuilderDelegates) {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              SizedBox(
                height: 120.0,
                child: Wrap(
                  children: sourceBuilderDelegates
                      .map((builderDelegate) => builderDelegate.build(
                            context,
                            WrapItem(builderDelegate.message, true),
                            animationBuilder: (animation) => CurvedAnimation(
                                  parent: animation,
                                  curve: Curves.ease,
                                ),
                          ))
                      .toList(),
                ),
              ),
              Expanded(
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    CircleButton(
                      text: '>',
                      onPressed: () => SidekickTeamBuilder.of<Item>(context)
                          .moveAll(SidekickFlightDirection.toTarget),
                    ),
                    SizedBox(width: 60.0, height: 60.0),
                    CircleButton(
                      text: '<',
                      onPressed: () => SidekickTeamBuilder.of<Item>(context)
                          .moveAll(SidekickFlightDirection.toSource),
                    ),
                  ],
                ),
              ),
              SizedBox(
                height: 250.0,
                child: Wrap(
                  children: targetBuilderDelegates
                      .map((builderDelegate) => builderDelegate.build(
                            context,
                            WrapItem(builderDelegate.message, false),
                            animationBuilder: (animation) => CurvedAnimation(
                                  parent: animation,
                                  curve: FlippedCurve(Curves.ease),
                                ),
                          ))
                      .toList(),
                ),
              )
            ],
          ),
        );
      },
    );
  }
}

class WrapItem extends StatelessWidget {
  const WrapItem(
    this.item,
    this.isSource,
  ) : size = isSource ? 40.0 : 50.0;
  final bool isSource;
  final double size;
  final Item item;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => SidekickTeamBuilder.of<Item>(context).move(item),
      child: Padding(
        padding: const EdgeInsets.all(2.0),
        child: Container(
          height: size - 4,
          width: size - 4,
          color: _getColor(item.id),
        ),
      ),
    );
  }

  Color _getColor(int index) {
    switch (index % 4) {
      case 0:
        return Colors.blue;
      case 1:
        return Colors.green;
      case 2:
        return Colors.yellow;
      case 3:
        return Colors.red;
    }
    return Colors.indigo;
  }
}

Changelog

Please see the Changelog page to know what's recently changed.

Contributions

Feel free to contribute to this project.

If you find a bug or want a feature, but don't know how to fix/implement it, please fill an issue.
If you fixed a bug or implemented a new feature, please send a pull request.

Comments
  • Question : How to show only source and then target

    Question : How to show only source and then target

    Hey,

    I would like to make a simple animation, showing at the beggining only the source, and at this end only the target (with SideKick widget)

    Could you give me some leads on this ? Do I have to play with the opacity, listening to the animation status ?

    Thanks !

    opened by g-balas 2
  • Change SourceList after initialization

    Change SourceList after initialization

    Thanks for your great plugin! 🎉 I am trying to build a select-widget with it, based on the SidekickTeamBuilder. The SidekickTeamBuilder is in its own builder of a Streambuilder (I am using the bloc model for datastreams), so I (thought I) can just easily filter my initialSourceList.

    But, even though my initialSourceList is setup correctly initially, when repainting the SidekickTeamBuilder with a new value for initialSourceList, it is never updated anymore when I rebuild/paint the widget.

    My question: How could I filter the available (sourceList) items, after it is painted on the screen already?

    opened by rogiervandenberg 2
  • Make source sidekick disappear at end

    Make source sidekick disappear at end

    I suspect because this code was borrowed from the Hero animation, currently the source and the target Sidekick appear after the animation completes. This is probably not what you want -- and it's not the behavior of the sidekick team -- normally you want it to seem like it has flown from one place to another.

    Making this one line change fixes that. :-)

    opened by efortuna 1
  • flutter_sidekick-0.1.3/lib/src/widgets/sidekick_team_builder.dart:75:17: Error: The method 'ancestorStateOfType' isn't defined for the class 'BuildContext'.

    flutter_sidekick-0.1.3/lib/src/widgets/sidekick_team_builder.dart:75:17: Error: The method 'ancestorStateOfType' isn't defined for the class 'BuildContext'.

    In flutter 2.x, I am seeing the following error message when attempting to use Sidekick:

    flutter_sidekick-0.1.3/lib/src/widgets/sidekick_team_builder.dart:75:17: Error: The method 'ancestorStateOfType' isn't defined for the class 'BuildContext'.

    Apparently context.ancestorStateOfType() and context.ancestorInheritedElementForWidgetOfExactType(type) are deprecated because they don't work correctly and have been removed for latest Flutter stable.

    opened by md84419 1
  • Support null safety

    Support null safety

    The library 'package:flutter_sidekick/flutter_sidekick.dart' is legacy, and should not be imported into a null safe library. Try migrating the imported library.

    Error: This project cannot run with sound null safety, because one or more project dependencies do not
    support null safety:
    
    -  package:flutter_sidekick
    
    dependencies:
      flutter_sidekick: ^0.1.3
    
    opened by md84419 0
  • Fix coordinate system for non-fullscreen overlays

    Fix coordinate system for non-fullscreen overlays

    When the overlay is not full screen, the animating widgets were not displayed in the correct position. This fix applies the same fixes that are present in the current Flutter's Hero implementation.

    opened by m4tbat 0
  • add param to keep showing from widget after flight

    add param to keep showing from widget after flight

    This PR adds a new param to use with the source "from" Sidekick widget to allow choosing to keep showing the original source widget.

    My thanks to @efortuna for submitting the bugfix that this PR essentially optionally disables as otherwise I would not have realised this functionality was possible with Sidekick.

    The reason I want to be able to do this is to use Sidekick to implement an animation which temporarily replaces the target widget, as shown in the video below.

    ps. My apologies for the laggyness at the end of the animation in the video, that just seems to be due to recording on the emulator, the actual animation is nice and smooth.

    sidekick-pr webm

    opened by maks-nuraphone 0
Releases(v0.1.2)
Owner
Romain Rastel
Flutter Developer
Romain Rastel
A flutter package which makes it easier to display the difference between two images.

?? Before After A flutter package which makes it easier to display the differences between two images.. The source code is 100% Dart, and everything r

Sahil Kumar 741 Dec 30, 2022
A Flutter ListView that implicitly animates between the changes of two lists with support to reorder its items.

Implicitly Animated Reorderable List A Flutter ListView that implicitly calculates the changes between two lists using the MyersDiff algorithm and ani

null 246 Feb 22, 2022
A Flutter ListView that implicitly animates between the changes of two lists with support to reorder its items.

Implicitly Animated Reorderable List A Flutter ListView that implicitly calculates the changes between two lists using the MyersDiff algorithm and ani

null 246 Feb 22, 2022
A set of transition patterns within the animations package using flutter.

Flutter Motion Transitions A fultter app to demonstrate Material motion system. Material Motion System The four main Material transition patterns are

Rafsan Ahmad 17 Oct 13, 2022
A Flutter package to custom splash screen like change logo icon, logo animation, and splash screen background color.

Custom Splash Screen A Flutter package to custom splash screen: change logo icon, logo animation, and splash screen background color. (Custom from ani

tranhuycong 78 Sep 6, 2022
Like Button is a flutter library that allows you to create a button with animation effects similar to Twitter's heart when you like something and animation effects to increase like count.

like_button Language: English | 中文简体 Like Button is a flutter library that allows you to create a button with animation effects similar to Twitter's h

FlutterCandies 357 Dec 27, 2022
Flutter package for creating awesome animations.

?? Simple Animations Simple Animations is a powerful package to create beautiful custom animations in no time. ?? fully tested ?? well documented ?? e

Felix Blaschke 879 Dec 31, 2022
A flutter package which display the library collapse according to the number of images associated with hero animation

?? Gallery Collapse A flutter package which display the library collapse accordi

null 6 Sep 12, 2022
A new Flutter dialog with a series of beautiful animations, slide fade rotate size scale rotate3D animations.

flutter_animated_dialog A new Flutter dialog with a series of beautiful animations, slide fade rotate size scale rotate3D animations. Dialog barrier i

null 20 Dec 3, 2022
A Flutter package that two widgets switch with clipper.

Flutter Switch Clipper A Flutter package that two widgets switch with clipper. 使用 使用FillClipper并自定义相关参数 View code SwitchCipper( initSelect: true,

FlutterCandies 23 Jan 3, 2023
Flutter widget that automatically resizes text to fit perfectly within its bounds.

ONLY FOR FLUTTER WEB Flutter widget that automatically resizes text to fit perfectly within its bounds. Show some ❤️ and star the repo to support the

Rebar Ahmad 4 Jan 6, 2022
A small library for creating snapping lists.

snaplist A small cozy library that allows you to make snappable list views. Issues and Pull Requests are really appreciated! Snaplist supports differe

David Leibovych 415 Dec 21, 2022
Orchestrate multiple animations with ease.

flutter_sequence_animation Features No need to use intervals and calculate percentages for your total animation time. Animate the same variable with m

Norbert Kozsir 381 Dec 27, 2022
🔔 A flutter package to create cool and beautiful text animations. [Flutter Favorite Package]

Animated Text Kit A flutter package which contains a collection of some cool and awesome text animations. Recommended package for text animations in C

Ayush Agarwal 1.4k Jan 6, 2023
Easily add staggered animations to your ListView, GridView, Column and Row children.

Flutter Staggered Animations Easily add staggered animations to your ListView, GridView, Column and Row children as shown in Material Design guideline

null 1.2k Jan 6, 2023
Fun canvas animations in Flutter based on time and math functions.

funvas Flutter package that allows creating canvas animations based on time and math (mostly trigonometric) functions. The name "funvas" is based on F

null 472 Jan 9, 2023
Organize your animations.

montage Organize your animations. Quickstart // 1. Define your animations const entrance = MontageAnimation( key: 'entrance', duration: Duration(s

Aloïs Deniel 14 Oct 19, 2022
A widget for stacking cards, which users can swipe horizontally and vertically with beautiful animations.

A widget for stacking cards, which users can swipe horizontally and vertically with beautiful animations.

HeavenOSK 97 Jan 6, 2023
A flutter package that adds support for vector data based animations.

animated_vector Description and inspiration A package that adds support for vector data based animations. The data format is heavily inspired from the

Potato Open Sauce Project 6 Apr 26, 2022