Search code examples
flutterdartscrollgesture

Flutter DraggableScrollableSheet extent control


I am trying to implement a DraggableScrollableSheet that expands to maxChildSize when I perform a drag up action and collapses to minChildSize when I perform a drag down action. I would like to know how can I control the extent of the sheet.

DraggableScrollableSheet(
    initialChildSize: 0.75,
    minChildSize: 0.65,
    maxChildSize: 1.0,
    builder: (context, _scrollController) {
        return ListView(
            physics: ClampingScrollPhysics(),
            controller: _scrollController,
            children: [Widget A, Widget B, Widget C...],
        );
    },
)

I tried to wrap the sheet with a GestureDetector like this

GestureDetector(
    onVerticalDragEnd:(details) {print("drag ended");},
    child:DraggableScrollableSheet(
        initialChildSize: 0.75,
        minChildSize: 0.65,
        maxChildSize: 1.0,
        builder: (context, _scrollController) {
            return ListView(
                physics: ClampingScrollPhysics(),
                controller: _scrollController,
                children: [Widget A, Widget B, Widget C...],
            );
        },
    ),
)

But onVerticalDragEnd doesn't do anything, not even print out message.

I found a suggestion using DraggableScrollableActuator, it can do what I want with changing initialChildSize and calling DraggableScrollableActuator.reset(), but I cannot find any ways to make it animated or smoothly changing the sheet size.

Are there any ways to perform things like .animateTo() in DraggableScrollableSheet?


Solution

  • https://github.com/flutter/flutter/issues/102520

    Although the issue above does not directly ask your question above, I believe the answer provided by maheshmnj.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key}) : super(key: key);
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      final List<Color> colors = [
        Colors.green.shade400,
        Colors.green.shade900,
      ];
      late DraggableScrollableController _controller;
    
      @override
      void initState() {
        _controller = DraggableScrollableController();
        super.initState();
      }
    
      double initialSize = 1.0;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: DraggableScrollableSheet(
            controller: _controller,
            initialChildSize: initialSize,
            minChildSize: 0,
            maxChildSize: 1,
            builder: (context, controller) {
              return Container(
                color: Colors.blueGrey.shade100,
                child: ListView.builder(
                  controller: controller,
                  itemCount: 30,
                  itemBuilder: (context, index) {
                    return Container(
                      margin: const EdgeInsets.fromLTRB(20, 10, 20, 0),
                      height: 30,
                      color: colors[index % colors.length],
                      child: Center(child: Text('$index')),
                    );
                  },
                ),
              );
            },
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () async {
              await _controller.animateTo(
                _controller.size - 0.2,
                duration: Duration(milliseconds: 100),
                curve: Curves.linear,
              );
              setState(() {
                initialSize = _controller.size;
              });
            },
            child: const Icon(Icons.expand_more),
          ),
        );
      }
    }