将动画滑动到底部

时间:2018-11-13 10:21:39

标签: dart flutter

页面底部有一个圆点指示器。我需要在滑动到底部5秒钟后将其隐藏。当用户移至其他页面时,显示的点会滑到顶部,最后在5秒钟后再次隐藏。现在,圆点会在淡出5秒后隐藏起来,但我需要其他类型的动画。

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,
                        );
                      },
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

我认为position transition会对我有帮助,但是我不知道如何在不重写的情况下将其添加到代码中。有人可以帮助我吗?

更新

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,
                        );
                      },
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

现在我需要在用户触摸屏时调用 controller.reverse ...

1 个答案:

答案 0 :(得分:4)

要为指标创建滑动动画(如果我理解您的要求是对的),我只是建议使用SlideTransition小部件。将其集成到您现有的代码中不需要太多的工作。

以下代码显示了SlideTransition的最小示例。如果您想从一个屏幕导航到另一个屏幕期间继续显示它,则必须将其绘制在导航器的上方图层中。

如果您不喜欢使用Stack,则可以改用Overlay的抖动功能,如answer所述。通过在导航过渡期间显示期间显示动画,也可以解决这一难题。

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(),
              ),
            ),
          )
        ],
      ),
    );
  }
}