'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 1:[1]

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),
      ),
    );
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tom O'Sullivan