在 flutter 中制作可调整大小的下拉小部件

Making a resizable dropdown widget with touch in flutter

我想创建一个下拉菜单,如下图所示,通过触摸拖动打开,触摸外部关闭。

before dragging

after dragging

Scaffold(
  appBar: AppBar(
    automaticallyImplyLeading: false
  ),
  body: Stack(
    children: <Widget>[
      Container(
        height: 200,
        decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.vertical(bottom: Radius.circular(20))
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Align(
              alignment: Alignment.bottomCenter,
              child: Column(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.symmetric(horizontal: 40),
                    child: Divider(
                      color: Colors.blueGrey[500],
                      height: 10,
                      indent: 5,
                    ),
                  ),
                  Icon(FontAwesomeIcons.angleDoubleDown,size: 15,color: Colors.blueGrey[500],)
                ],
              ),
            )
          ],
        ),
      ),
      Center(child: Text('List View'),)
    ],
  )
)

我想改变高度,但遇到溢出错误! 制作此小部件的最佳方法是什么? 我可以在 AppBar 中执行此操作吗?

您可以通过某些方式做到这一点,但我马上想到的是在 Stack 顶部使用带有您自己的 CustomPainterCustomPaint 小部件,所以您实际上可以将其他小部件保留在滚动条下方。

我已尝试复制您在图片上显示的内容,但您可以根据自己的需要随意调整。

const kMinScrollBarHeight = 20.0;

class MyScreen extends StatefulWidget {
  _MyScreenState createState() => _MyScreenState();
}

class _MyScreenState extends State<MyScreen> {
  double _scrollBarOffset = 0.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color.fromRGBO(13, 23, 35, 1.0),
      appBar: AppBar(
        backgroundColor: const Color.fromRGBO(255, 72, 18, 1.0),
      ),
      body: Stack(children: <Widget>[
        GestureDetector(
          onVerticalDragUpdate: (tapDetails) => setState(() => _scrollBarOffset = tapDetails.globalPosition.dy),
          child: Stack(
            children: <Widget>[
              Center(
                child: Text(
                  'My screen widgets',
                  style: TextStyle(color: Colors.white),
                ),
              ),
              Stack(
                children: <Widget>[
                  Positioned(
                    bottom: MediaQuery.of(context).size.height -
                        max(_scrollBarOffset,
                            MediaQuery.of(context).padding.top + kToolbarHeight + kMinScrollBarHeight),
                    child: CustomPaint(
                      painter: MyDraggable(),
                      child: Container(
                        height: MediaQuery.of(context).size.height,
                        width: double.infinity,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            FlutterLogo(
                              size: 100.0,
                            ),
                            Text('Flutter is awesome'),
                          ],
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ]),
    );
  }
}

class MyDraggable extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()..color = Colors.white;
    final Radius cornerRadius = Radius.circular(20.0);
    final double lineMargin = 30.0;

    // Draw slider
    canvas.drawRRect(
        RRect.fromLTRBAndCorners(0.0, 0.0, size.width, size.height,
            bottomLeft: cornerRadius, bottomRight: cornerRadius),
        paint);
    paint.color = Colors.black.withAlpha(64);
    paint.strokeWidth = 1.5;

    // Draw triangle
    canvas.drawPoints(
        PointMode.polygon,
        [
          Offset((size.width / 2) - 5.0, size.height - 10.0),
          Offset((size.width / 2) + 5.0, size.height - 10.0),
          Offset((size.width / 2), size.height - 5.0),
          Offset((size.width / 2) - 5.0, size.height - 10.0),
        ],
        paint);

    // Draw line
    canvas.drawLine(Offset(lineMargin, size.height - kMinScrollBarHeight),
        Offset(size.width - lineMargin, size.height - kMinScrollBarHeight), paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}