如何创建从侧面打开的模态底片

abh*_*ham 3 flutter flutter-layout

我正在尝试克隆股票 android 计算器应用程序。我无法弄清楚如何实现在右侧打开的可拉式抽屉。

这是一个 gif,显示了我在说什么:https : //imgur.com/a/hnYLTyA

Mob*_*ina 5

  • 用于Stack将抽屉放在计算器屏幕的顶部。

  • 使用Positioned的抽屉,并设置其left根据,它的拉动量参数。

  • left最初将抽屉的参数设置到屏幕的末尾。

  • 拉动时使用GestureDetectoronPanUpdate更改位置。

  • 根据抽屉的位置改变抽屉图标。

  • 对于计算器屏幕上的昏暗效果,请使用ModalBarrier. 用一个Opacity小部件包裹它并opacity根据抽屉被拉出的数量设置它的参数。

  static double _offset = 30;
  double _drawerLeft = 400;
  IconData _drawerIcon = Icons.arrow_back_ios;
  bool _init = true;

  @override
  Widget build(BuildContext context) {
    if (_init) {
      _drawerLeft = MediaQuery.of(context).size.width - _offset;
      _init = false;
    }
    return Scaffold(
      body: Align(
        alignment: Alignment.bottomCenter,
        child: FractionallySizedBox(
          widthFactor: 1,
          heightFactor: 0.5,
          child: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              Positioned.fill(
                child: Container(
                  color: Colors.grey[200],
                  child: Center(
                      child: Text(
                    'text',
                    style: TextStyle(fontSize: 32),
                  )),
                ),
              ),
              Positioned.fill(
                right: 0,
                child: Opacity(
                  opacity: 1 -
                      _drawerLeft /
                          (MediaQuery.of(context).size.width - _offset),
                  child:
                      ModalBarrier(dismissible: false, color: Colors.black87),
                ),
              ),
              Positioned(
                width: MediaQuery.of(context).size.width * 3 / 4,
                top: 0,
                height: MediaQuery.of(context).size.height / 2,
                left: _drawerLeft,
                child: GestureDetector(
                    onPanUpdate: (details) {
                      _drawerLeft += details.delta.dx;
                      if (_drawerLeft <= MediaQuery.of(context).size.width / 4)
                        _drawerLeft = MediaQuery.of(context).size.width / 4;
                      if (_drawerLeft >=
                          MediaQuery.of(context).size.width - _offset)
                        _drawerLeft =
                            MediaQuery.of(context).size.width - _offset;
                      if (_drawerLeft <= MediaQuery.of(context).size.width / 3)
                        _drawerIcon = Icons.arrow_forward_ios;
                      if (_drawerLeft >=
                          MediaQuery.of(context).size.width - 2 * _offset)
                        _drawerIcon = Icons.arrow_back_ios;
                      setState(() {});
                    },
                    child: Container(
                      decoration: BoxDecoration(color: Colors.blue),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: <Widget>[
                          Padding(
                            padding: EdgeInsets.only(right: _offset),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: <Widget>[
                                Icon(
                                  _drawerIcon,
                                  color: Colors.white,
                                ),
                              ],
                            ),
                          ),
                          Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: <Widget>[
                              Text(
                                'text',
                                style: TextStyle(
                                    color: Colors.white, fontSize: 32),
                              )
                            ],
                          )
                        ],
                      ),
                    )),
              ),
            ],
          ),
        ),
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

结果:

资源