在BottomSheet中实施过渡

时间:2019-04-30 22:19:25

标签: animation dart flutter bottom-sheet

我正在尝试实现以下设计,但是我似乎无法理解该做的事情:P

gif

我当时正在考虑使用通过BottomSheet函数显示的showModalBottomSheet,但是我不知道如何实现过渡(我会使用FadeTransition进行渐变效果,但对增高效果一无所知)

到目前为止,我得到了什么:

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

class Setup extends StatefulWidget {
  final Widget child;

  const Setup(this.child);

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

class MyCurve extends Curve {
  @override
  double transform(double t) => -pow(t, 2) + 1;
}

class _SetupState extends State<Setup> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> opacityAnimation;
  int i = 0;

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

    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500));
    opacityAnimation = CurvedAnimation(
        parent: Tween<double>(begin: 1, end: 0).animate(_controller),
        curve: Curves.easeInOutExpo);
  }

  @override
  Widget build(BuildContext context) {
    return BottomSheet(
      enableDrag: false,
      elevation: 16,
      backgroundColor: Colors.transparent,
      builder: (_) => Container(
            margin: EdgeInsets.all(8),
            decoration: BoxDecoration(borderRadius: BorderRadius.circular(16)),
            child: Material(
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(16)),
                child: FadeTransition(
                  opacity: opacityAnimation,
                  child: Padding(
                      padding: EdgeInsets.all(16),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          widget.child,
                          Container(
                            height: 10,
                          ),
                          RaisedButton(
                            child: Text("Next"),
                            onPressed: () {
                              _controller.forward().then((_) {
                                _controller.reverse();
                              });
                            },
                          )
                        ],
                      )),
                )),
          ),
      onClosing: () {},
    );
  }
}

如您所见,我只是使淡入淡出动画起作用,而没有完成任何布线或高度转换。

2 个答案:

答案 0 :(得分:1)

由于BottomNavigationSheet的高度基于其内容的高度,因此您可以轻松对其进行动画处理。

用于在BottomSheet内容器,并为其指定所需的高度。可以通过创建一个AnimationController来对高度本身进行动画处理,其Begin和End设置为您想要的高度值并设置状态。然后只需从不透明度动画开始动画。

containerHeight = CurvedAnimation(
    parent: Tween<double>(begin: 350, end: 200).animate(_controller)..addListener(() {setState(() {});});,
    curve: Curves.easeInOutExpo);

这应该可以完成工作。

答案 1 :(得分:0)

使用AnimatedContainerAnimateCrossFade可以使事情变得复杂的原因。

documentation

仅供参考

    class BS extends StatefulWidget {
      _BS createState() => _BS();
    }

    class _BS extends State<BS> {
      bool _showSecond = false;

      @override
      Widget build(BuildContext context) {
        return BottomSheet(
          onClosing: () {},
          builder: (BuildContext context) => AnimatedContainer(
            margin: EdgeInsets.all(20),
            decoration: BoxDecoration(
                color: Colors.white, borderRadius: BorderRadius.circular(30)),
            child: AnimatedCrossFade(
                firstChild: Container(
                  constraints: BoxConstraints.expand(
                      height: MediaQuery.of(context).size.height - 200),
//remove constraint and add your widget hierarchy as a child for first view
                  padding: EdgeInsets.all(20),
                  child: Align(
                    alignment: Alignment.bottomCenter,
                    child: RaisedButton(
                      onPressed: () => setState(() => _showSecond = true),
                      padding: EdgeInsets.all(15),
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10)),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Text("Suivant"),
                        ],
                      ),
                    ),
                  ),
                ),
                secondChild: Container(
                  constraints: BoxConstraints.expand(
                      height: MediaQuery.of(context).size.height / 3),
//remove constraint and add your widget hierarchy as a child for second view
                  padding: EdgeInsets.all(20),
                  child: Align(
                    alignment: Alignment.bottomCenter,
                    child: RaisedButton(
                      onPressed: () => setState(() => _showSecond = false),
                      color: Colors.green,
                      padding: EdgeInsets.all(15),
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10)),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Text("ok"),
                        ],
                      ),
                    ),
                  ),
                ),
                crossFadeState: _showSecond
                    ? CrossFadeState.showSecond
                    : CrossFadeState.showFirst,
                duration: Duration(milliseconds: 400)),
            duration: Duration(milliseconds: 400),
          ),
        );
      }
    }