一尘不染

Flutter-通过滑动或按下floatActionButton来展开bottomNavigationBar

flutter

我有一个名为的主窗口小部件DashboardWidget。在里面,我有一个ScaffoldwithBottomNavigationBar和一个FloatingActionButton

现在,我想制作一个可通过以下方式从底部拖动的小部件:

  1. 用手指轻扫。
  2. 按下FloatingActionButton

换句话说,我想扩展BottomNavigationBar

如果我不清楚,这是一个设计概念。

问题是,我不确定从哪里开始实施。我已经考虑过删除BottomNavigationBar并创建一个可以扩展的自定义窗口小部件,但是我不确定是否也可以。


阅读 335

收藏
2020-08-13

共1个答案

一尘不染

输出:

在此处输入图片说明


我使用了另一种方法,并且没有使用AnimationControllerGlobalKey等等,逻辑代码非常短(_handleClick)。

我只使用了4个变量,简单而又简短!

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  static double _minHeight = 80, _maxHeight = 600;
  Offset _offset = Offset(0, _minHeight);
  bool _isOpen = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xFFF6F6F6),
      appBar: AppBar(backgroundColor: Color(0xFFF6F6F6), elevation: 0),
      body: Stack(
        alignment: Alignment.bottomCenter,
        children: <Widget>[
          Align(
            alignment: Alignment.topLeft,
            child: FlatButton(
              onPressed: _handleClick,
              splashColor: Colors.transparent,
              textColor: Colors.grey,
              child: Text(_isOpen ? "Back" : ""),
            ),
          ),
          Align(child: FlutterLogo(size: 300)),
          GestureDetector(
            onPanUpdate: (details) {
              _offset = Offset(0, _offset.dy - details.delta.dy);
              if (_offset.dy < _HomePageState._minHeight) {
                _offset = Offset(0, _HomePageState._minHeight);
                _isOpen = false;
              } else if (_offset.dy > _HomePageState._maxHeight) {
                _offset = Offset(0, _HomePageState._maxHeight);
                _isOpen = true;
              }
              setState(() {});
            },
            child: AnimatedContainer(
              duration: Duration.zero,
              curve: Curves.easeOut,
              height: _offset.dy,
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(30),
                    topRight: Radius.circular(30),
                  ),
                  boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.5), spreadRadius: 5, blurRadius: 10)]),
              child: Text("This is my Bottom sheet"),
            ),
          ),
          Positioned(
            bottom: 2 * _HomePageState._minHeight - _offset.dy - 28, // 56 is the height of FAB so we use here half of it.
            child: FloatingActionButton(
              child: Icon(_isOpen ? Icons.keyboard_arrow_down : Icons.add),
              onPressed: _handleClick,
            ),
          ),
        ],
      ),
    );
  }

  // first it opens the sheet and when called again it closes.
  void _handleClick() {
    _isOpen = !_isOpen;
    Timer.periodic(Duration(milliseconds: 5), (timer) {
      if (_isOpen) {
        double value = _offset.dy + 10; // we increment the height of the Container by 10 every 5ms 
        _offset = Offset(0, value);
        if (_offset.dy > _maxHeight) {
          _offset = Offset(0, _maxHeight); // makes sure it does't go above maxHeight
          timer.cancel();
        }
      } else {
        double value = _offset.dy - 10; // we decrement the height by 10 here
        _offset = Offset(0, value);
        if (_offset.dy < _minHeight) {
          _offset = Offset(0, _minHeight); // makes sure it doesn't go beyond minHeight
          timer.cancel();
        }
      }
      setState(() {});
    });
  }
}
2020-08-13