Sliding animation to bottom in flutter
Asked Answered
A

1

28

I have a dot indicator in bottom of the page. I need to hide this after 5 seconds sliding to bottom. When user move to other page show dots sliding to top and finally after 5 seconds hide again. Now the dots hide after 5 seconds in fade out but i need other type of animation.

import 'package:flutter/material.dart';
import 'package:iGota/screens/partials/dots_indicator.dart';
import 'package:iGota/screens/posts_page.dart';
import 'package:iGota/screens/maps_page.dart';

class HomePage extends StatefulWidget {
  static String tag = 'home-page';

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

class _MyHomePageState extends State<HomePage> {
  final _controller = new PageController();
  static const _kDuration = const Duration(milliseconds: 300);
  static const _kCurve = Curves.ease;
  final _kArrowColor = Colors.black.withOpacity(0.8);
  bool _visible = true;

  void initState() {
    super.initState();
    Future.delayed(Duration(milliseconds: 5)).then((_) => _visible = !_visible);
  }

  @override
  Widget build(BuildContext context) {
    final List<Widget> _pages = <Widget>[
      new ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: new FlatButton(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              FlatButton(
                onPressed: () {
                  Navigator.pushNamed(context, PostsPage.tag);
                },
                child: Column(
                  children: <Widget>[
                    IconButton(
                      icon:
                          Icon(Icons.save_alt, color: Colors.white, size: 30.0),
                      onPressed: () {
                        Navigator.pushNamed(context, PostsPage.tag);
                      },
                    ),
                    Text(
                      "Contenedores",
                      style: TextStyle(color: Colors.white, fontSize: 20.0),
                    )
                  ],
                ),
              ),
            ],
          ),
          splashColor: Colors.white,
          color: Colors.blue[300],
          onPressed: () {
            Navigator.pushNamed(context, PostsPage.tag);
          },
        ),
      ),
      new ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: new FlatButton(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              FlatButton(
                onPressed: () {
                  Navigator.pushNamed(context, MapsPage.tag);
                },
                child: Column(
                  children: <Widget>[
                    IconButton(
                      icon: Icon(Icons.bubble_chart,
                          color: Colors.white, size: 30.0),
                      onPressed: () {
                        Navigator.pushNamed(context, MapsPage.tag);
                      },
                    ),
                    Text(
                      "Válvulas",
                      style: TextStyle(color: Colors.white, fontSize: 20.0),
                    )
                  ],
                ),
              ),
            ],
          ),
          splashColor: Colors.white,
          color: Colors.red[300],
          onPressed: () {
            Navigator.pushNamed(context, MapsPage.tag);
          },
        ),
      ),
    ];

    return new Scaffold(
      body: new IconTheme(
        data: new IconThemeData(color: _kArrowColor),
        child: new Stack(
          children: <Widget>[
            new PageView.builder(
              physics: new AlwaysScrollableScrollPhysics(),
              controller: _controller,
              itemCount: _pages.length,
              itemBuilder: (BuildContext context, int index) {
                this._visible=true;
                return _pages[index % _pages.length];
              },
            ),
            new Positioned(
              bottom: 0.0,
              left: 0.0,
              right: 0.0,
              child: AnimatedOpacity(
                opacity: _visible ? 1.0 : 0.0,
                duration: Duration(milliseconds: 3000),               
                child: new Container(       
                  color: Colors.grey[800].withOpacity(0.5),
                  padding: const EdgeInsets.all(20.0),
                  child: new Center(
                    child: new DotsIndicator(
                      controller: _controller,
                      itemCount: _pages.length,
                      onPageSelected: (int page) {
                        _controller.animateToPage(
                          page,
                          duration: _kDuration,
                          curve: _kCurve,
                        );
                      },
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

I think position transition would help me but i don't know exactly how can i add to my code without rewriting. So anybody can help me?

UPDATE

import 'package:flutter/material.dart';
import 'package:iGota/screens/partials/dots_indicator.dart';
import 'package:iGota/screens/posts_page.dart';
import 'package:iGota/screens/maps_page.dart';

class HomePage extends StatefulWidget {
  static String tag = 'home-page';

  @override
  HomePageState createState() => new HomePageState();
}

class HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  final _controller = new PageController();
  static const _kDuration = const Duration(milliseconds: 300);
  static const _kCurve = Curves.ease;
  final _kArrowColor = Colors.black.withOpacity(0.8);
  AnimationController controller;
  Animation<Offset> offset;

  @override
  void initState() {
    super.initState();

    controller =AnimationController(vsync: this, duration: Duration(seconds: 1));
    Future.delayed(Duration(seconds: 5)).then((_) => controller.forward());

    offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 1.0))
        .animate(controller);
  }

  @override
  Widget build(BuildContext context) {
    GestureDetector(onTap: () {
      setState(() {
        controller.reverse();
      });
    });
    final List<Widget> _pages = <Widget>[
      new ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: new FlatButton(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              FlatButton(
                onPressed: () {
                  Navigator.pushNamed(context, PostsPage.tag);
                },
                child: Column(
                  children: <Widget>[
                    IconButton(
                      icon:
                          Icon(Icons.save_alt, color: Colors.white, size: 30.0),
                      onPressed: () {
                        Navigator.pushNamed(context, PostsPage.tag);
                      },
                    ),
                    Text(
                      "Contenedores",
                      style: TextStyle(color: Colors.white, fontSize: 20.0),
                    )
                  ],
                ),
              ),
            ],
          ),
          splashColor: Colors.white,
          color: Colors.blue[300],
          onPressed: () {
            Navigator.pushNamed(context, PostsPage.tag);
          },
        ),
      ),
      new ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: new FlatButton(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              FlatButton(
                onPressed: () {
                  Navigator.pushNamed(context, MapsPage.tag);
                },
                child: Column(
                  children: <Widget>[
                    IconButton(
                      icon: Icon(Icons.bubble_chart,
                          color: Colors.white, size: 30.0),
                      onPressed: () {
                        Navigator.pushNamed(context, MapsPage.tag);
                      },
                    ),
                    Text(
                      "Válvulas",
                      style: TextStyle(color: Colors.white, fontSize: 20.0),
                    )
                  ],
                ),
              ),
            ],
          ),
          splashColor: Colors.white,
          color: Colors.red[300],
          onPressed: () {
            Navigator.pushNamed(context, MapsPage.tag);
          },
        ),
      ),
    ];

    return new Scaffold(
      body: new IconTheme(
        data: new IconThemeData(color: _kArrowColor),
        child: new Stack(
          children: <Widget>[
            new PageView.builder(
              physics: new AlwaysScrollableScrollPhysics(),
              controller: _controller,
              itemCount: _pages.length,
              itemBuilder: (BuildContext context, int index) {
                return _pages[index % _pages.length];
              },
            ),
            new Positioned(
              bottom: 0.0,
              left: 0.0,
              right: 0.0,
              child: SlideTransition(
                position: offset,
                child: new Container(
                  color: Colors.grey[800].withOpacity(0.5),
                  padding: const EdgeInsets.all(20.0),
                  child: new Center(
                    child: new DotsIndicator(
                      controller: _controller,
                      itemCount: _pages.length,
                      onPageSelected: (int page) {
                        _controller.animateToPage(
                          page,
                          duration: _kDuration,
                          curve: _kCurve,
                        );
                      },
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

Now i need to call controller.reverse when user touch screen...

Applaud answered 13/11, 2018 at 10:21 Comment(0)
S
53

To create a sliding animation for your indicator (if I've understood your requirement right), I would simply suggest using the SlideTransition widget. It should not require much work to integrate it in your existing code.

The code belows shows a minimal example of the SlideTransition. If you'd like to keep displaying it during the navigation from one screen to another, you'd have to draw it in a layer above your Navigator.

If you do not like to use a Stack, you can instead use the Overlay functionality of flutter, as given in this answer. This would also solve the struggle, with keeping the animation displayed during the navigation transition.

import 'package:flutter/material.dart';

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

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

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => HomeState();
}

class HomeState extends State<Home> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<Offset> offset;

  @override
  void initState() {
    super.initState();

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

    offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 1.0))
        .animate(controller);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          Center(
            child: RaisedButton(
              child: Text('Show / Hide'),
              onPressed: () {
                switch (controller.status) {
                  case AnimationStatus.completed:
                    controller.reverse();
                    break;
                  case AnimationStatus.dismissed:
                    controller.forward();
                    break;
                  default:
                }
              },
            ),
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: SlideTransition(
              position: offset,
              child: Padding(
                padding: EdgeInsets.all(50.0),
                child: CircularProgressIndicator(),
              ),
            ),
          )
        ],
      ),
    );
  }
}
Stanwin answered 13/11, 2018 at 17:54 Comment(4)
This is exactly what i want. But if i want to call controller.reverse(); on drag screen ¿How can i do this? I update my question.Applaud
@Niklas can i perform this animation on my list item. I want to slide my list item from right to left. I tried but didn't get exact thing. Can you help me?Expansionism
I am trying to do exactly this, but with a FloatingActionButton(or any button). But I and the button to be hidden from the start. How can you achieve this? I tried using Visibility but it didn't work as expected.Sammy
You can perform this animation on list item by using the scroll controller property of list widget. when the user reaches end of list call the animation.Pastille

© 2022 - 2024 — McMap. All rights reserved.