Implementing transitions in a BottomSheet

守給你的承諾、 提交于 2019-12-24 04:22:22

问题


I'm trying to implement the following design, but I can't seem to get my head around the way I should do it :P

I was thinking about using a BottomSheet displayed via the showModalBottomSheet function, but I can't figure out how to implement the transitions (I'd use a FadeTransition for the fade effect, no idea for the the height-changing effect though)

What I got so far :

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

As you can see, I just got the fade animation working, and got none of the routing or height transition done.


回答1:


Since the BottomNavigationSheet's height is based on the height of it's content, you could easily animate it.

Use to Container inside the BottomSheet an give it the height it needs. The height itself can be animated by creating an AnimationController with begin and end set to values you want the height be and set the state. Then just start the animation with the opacity-animation.

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

This should do the work.




回答2:


Why complicate things when you can achieve the same using AnimatedContainer and AnimateCrossFade.

Just for your information

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


来源:https://stackoverflow.com/questions/55929366/implementing-transitions-in-a-bottomsheet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!