Flutter Container transform (animation package)

Viewed 6889

randomly when i seeing flutter packages and libraries, i found out animations package of flutter and into that i see, there is one of my very useful animation like with android Gmail application which that have search navigation animation. to understand what i mean you can see this link, number 4 animation

i looked at source folder of this package in repository on github, but i can't find sample implementation of this animation and i'm not sure that have sample code, is any body help me how can use Container transform to have that?

2 Answers

Animations package provides OpenContainer widget.

This widget has 2 builders: openBuilder closedBuilder.
ClosedBuilder returns the widget that user sees before open and after close widget, in flowing example it is SearchBar.
OpenBuilder returns the page showing after user opens the closed widget, in flowing example it is SearchPage.

open and close actions trigger by calling callback: openContainer, closeContainer.

enter image description here

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.blue,
        scaffoldBackgroundColor: Colors.white,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  String searchString;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(15.0),
          child: OpenContainer<String>(
            openBuilder: (_, closeContainer) => SearchPage(closeContainer),
            onClosed: (res) => setState(() {
              searchString = res;
            }),
            tappable: false,
            closedBuilder: (_, openContainer) => SearchBar(
              searchString: searchString,
              openContainer: openContainer,
            ),
          ),
        ),
      ),
    );
  }
}

class SearchBar extends StatelessWidget {
  const SearchBar(
      {Key key, @required this.searchString, @required this.openContainer})
      : super(key: key);

  final String searchString;
  final VoidCallback openContainer;
  @override
  Widget build(BuildContext context) {
    return Material(
      elevation: 3,
      borderRadius: BorderRadius.circular(5),
      child: InkWell(
        onTap: openContainer,
        child: Container(
          padding: EdgeInsets.all(10),
          color: Colors.white,
          child: Row(
            children: [
              Icon(Icons.search),
              SizedBox(width: 10),
              searchString != null
                  ? Expanded(child: Text(searchString))
                  : Spacer(),
              Icon(Icons.mic),
            ],
          ),
        ),
      ),
    );
  }
}

class SearchPage extends StatelessWidget {
  const SearchPage(
    this.onClose, {
    Key key,
  }) : super(key: key);

  final void Function({String returnValue}) onClose;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              padding: EdgeInsets.symmetric(horizontal: 10),
              decoration: BoxDecoration(
                boxShadow: [
                  BoxShadow(
                    offset: Offset(0, 2),
                    spreadRadius: 0,
                    blurRadius: 1,
                    color: Colors.black26,
                  )
                ],
                color: Colors.white,
              ),
              child: Row(
                children: [
                  IconButton(
                    icon: Icon(Icons.arrow_back),
                    onPressed: onClose,
                  ),
                  Spacer(),
                  Icon(Icons.mic),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  OutlineButton(
                    onPressed: () => onClose(returnValue: 'Flutter'),
                    child: Text('Search: "Flutter"'),
                  ),
                  OutlineButton(
                    onPressed: () => onClose(returnValue: 'Rabbit'),
                    child: Text('Search: "Rabbit"'),
                  ),
                  OutlineButton(
                    onPressed: () => onClose(returnValue: 'What is the Matrix'),
                    child: Text('Search: "What is the Matrix"'),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Correct me if I am wrong, but aren't these two the same animation?

#1gif of what OP is looking for #2gif of what is already present in the example lib

Gif #1 is what you said you are looking for. Gif #2 is what I got by following the example without making any meaningful changes: https://github.com/flutter/packages/tree/master/packages/animations/example/lib

Take a closer look at container_transition.dart, specifically what _ExampleCard returns. I won't be pasting any code here because: 1) In case the package changes I advise future readers to take a look at the official examples rather than blindly copy pasting from my answer which might become obsolete; 2) You didn't bother to post any yourself.

Related