flutter - 如何创建从侧面打开的模态底板

标签 flutter flutter-layout

我正在尝试克隆股票 android 计算器应用程序。我无法弄清楚如何实现在右侧打开的可拉式抽屉。
这是一个gif,显示了我在说什么:
https://imgur.com/a/hnYLTyA

最佳答案

  • 使用 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),
                                  )
                                ],
                              )
                            ],
                          ),
                        )),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    
    结果:
    res

    关于flutter - 如何创建从侧面打开的模态底板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63647747/

    相关文章:

    animation - 如何切换光斑动画?

    flutter - 如何预缓存 flutter 火光动画

    flutter - 我真的,甚至都不知道如何针对这个问题提出问题

    flutter - 使用 Flutter 嵌套和同步 ListView (类似调度程序)

    flutter - 使用 ConstrainedBox 和 Container 小部件为其子框提供约束有什么区别?

    flutter - 从init方法将上下文传递给Provider时,Flutter引发错误

    ios - 如何在 flutter 中的圆角容器上添加彩色底部边框?

    flutter - "' !_needsLayout ': is not true"在使用 BottomNavigationBar 切换屏幕时 Flutter 出错

    dart - 应用程序启动后如何启动一次登录和启动画面页面

    Flutter 使用拖动和按钮单击扩展 TextField