17

I am using draggableScrollableSheet. I am giving these parameters

DraggableScrollableSheet(initialChildSize: 0.4,maxChildSize: 1,minChildSize: 0.4,builder: (BuildContext context, ScrollController scrollController) {
            return SingleChildScrollView(controller: scrollController,
              child: Theme(
                data: Theme.of(context).copyWith(canvasColor: Colors.transparent),
                child: Opacity(
                  opacity: 1,
                  child: IntrinsicHeight(
                      child: Column(mainAxisSize: MainAxisSize.min,
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: <Widget>[
                          SizedBox(height: 10,),
                          Container(
                            margin: EdgeInsets.only(right: 300),
                            decoration: BoxDecoration(
                              border: Border(
                                top: BorderSide(
                                    color: Colors.blue,
                                    width: 3,
                                    style: BorderStyle.solid),
                              ),
                            ),
                          ),
                          Card(
                            child: Row(
                              children: <Widget>[
                                Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Column(
                                    crossAxisAlignment:
                                    CrossAxisAlignment.start,
                                    children: <Widget>[
                                      Text(
                                        S
                                            .of(context)
                                            .we_have_found_you_a_driver,
                                        style: TextStyle(
                                            color: Colors.black,
                                            fontWeight: FontWeight.bold),
                                      ),
                                      SizedBox(
                                        height: 10,
                                      ),
                                      Text(S
                                          .of(context)
                                          .driver_is_heading_towards +
                                          ' ${widget.order.foodOrders.first.food.restaurant.name}')
                                    ],
                                  ),
                                ),
                              ],
                            ),
                            elevation: 5,
                          ),
                          SizedBox(height: 10,),
                          Card(
                            elevation: 5,
                            child: Row(
                                mainAxisAlignment: MainAxisAlignment.start,
                                children: <Widget>[
                                  CircleAvatar(
                                    radius: 50.0,
                                    backgroundColor: Colors.white,
                                    child:
                                    Image.asset(
                                        'assets/img/image_not_available.jpg'),
                                  ),
                                  Expanded(
                                    child: Column(mainAxisAlignment: MainAxisAlignment.start,
                                      children: <Widget>[
                                        Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
                                          children: <Widget>[
                                            Expanded(
                                              child: Text('Test',
                                                  textAlign: TextAlign.start,
                                                  style: new TextStyle(
                                                    color: Colors.black,
                                                    fontSize: 16.0,
                                                  )),
                                            ),
                                            Icon(Icons.star, color: Colors.yellow.shade700,)
                                          ],
                                        ),
                                        SizedBox(height: 30,),
                                        Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
                                          children: <Widget>[
                                            Expanded(
                                              child: Container(
                                                child: Text('Mobile number',
                                                    textAlign: TextAlign.start,
                                                    style: new TextStyle(
                                                      color: Colors.black,
                                                      fontSize: 16.0,
                                                    )),
                                              ),
                                            ),
                                            Icon(Icons.phone,),
                                            SizedBox(width: 10,),
                                            Icon(Icons.message),
                                          ],
                                        ),

                                      ],
                                    ),
                                  )
                                ]),
                          ),
                          SizedBox(height: 10,),
                          Card(
                            child: Align( alignment: Alignment(-1,1),
                              child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: <Widget>[
                                  Padding(
                                    padding: const EdgeInsets.all(8.0),
                                    child: Column(
                                      crossAxisAlignment:
                                      CrossAxisAlignment.start,
                                      children: <Widget>[
                                        Text(
                                          S
                                              .of(context)
                                              .you_ordered_from + ' ${widget.order.foodOrders.first.food.restaurant.name}',
                                          style: TextStyle(
                                            color: Colors.grey,
                                          ),
                                        ),
                                        SizedBox(
                                          height: 5,
                                        ),
                                        Column(children: List.generate(widget.order.foodOrders.length,(index) {
                                          return Text(
                                              '${widget.order.foodOrders[index].food.name}'
                                          );
                                        },),),
                                        Row(
                                          children: <Widget>[
                                            Column(crossAxisAlignment: CrossAxisAlignment.start,
                                              children: <Widget>[
                                                Text('See details', style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blue),),

                                              ],
                                            ),


                                          ],
                                        ),

                                      ],
                                    ),
                                  ),
                                  Padding(
                                    padding: const EdgeInsets.all(8.0),
                                    child: Column(
                                      children: <Widget>[
                                        SizedBox(height: 40,),
                                        Row(
                                          children: <Widget>[
                                            Icon(Icons.monetization_on),
                                            Text(widget.order.foodOrders
                                                .first.price
                                                .toString()),
                                          ],
                                        ),
                                      ],
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            elevation: 5,
                          ),
                        ],
                      ),
                  ),
                ),
              ),
            )

and I also used a single child scroll view and column so that I can show my cards in that column of draggableScrollableSheet. But I want draggableScrollableSheet to take height dynamically instead of defining size. Like now I want to show only 2 to 3 cards and that is taking full screen. But I want it to take the minimum height of the screen. How can we achieve this?

Hamed
  • 5,867
  • 4
  • 32
  • 56
Umair
  • 1,759
  • 6
  • 23
  • 44

3 Answers3

3

I was struggling with this for a while, and then discovered that the correct way to achieve this is to use ClampingScrollPhysics as the physics parameter of the scroll view.

https://api.flutter.dev/flutter/widgets/ClampingScrollPhysics-class.html

Jacobo Koenig
  • 11,728
  • 9
  • 40
  • 75
0

I'm a week into Flutter but I found a solution to this. It might be substandard so correct me if I'm wrong.

So what I've done is create a variable called bsRatio for the bottom sheet. This is will be the height of the child view/widget (or bottom sheet content) divide by the height of the parent/screen. This ratio should be set to the maxChildSize and probably even the initialChildSize of your DraggableScrollableSheet.

So in your parent widget or Widget State class add something like this.

class ParentWidget extends StatefulWidget {
  ParentWidget({Key? key}) : super(key: key);

  @override
  State<ParentWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
    
  var bsRatio = 0.4; // Set an initial ratio
    
  @override
  Widget build(BuildContext context) {
      // The line below is used to get status bar height. Might not be required if you are not using the SafeArea 
      final statusBarHeight = MediaQuery.of(context).viewPadding.top;
      // If you are not using SafeArea Widget you can skip subtracting status bar height from the Window height
      final windowHeight = MediaQuery.of(context).size.height - statusBarHeight;
      // This below is a callback function that will be passed to the child Widget of the DraggableScrollableSheet -> 
      childHeightSetter(childHeight) {
          // setState rebuilds the UI with the new `bsRatio` value
          setState(() {
              // The new bottom sheet max height ratio is the height of the Child View/Widget divide by the screen height
              bsRatio = childHeight / windowHeight;
          });
      }
      return Scaffold(
          backgroundColor: Colors.black12,
          body: SafeArea(
              child: Stack(
                  children: [
                      const SomeBackgroundView(),
                      DraggableScrollableSheet(
                          initialChildSize: bsRatio, // here you set the newly calculated ratio as the initial height of the Bottom Sheet
                          minChildSize: 0.2,
                          maxChildSize: bsRatio, // here you set the newly calculated ratio as the initial height of the Bottom Sheet
                          snap: true,
                          builder: (_, controller) {
                              return LayoutBuilder(builder: (_, box) {
                                  // Added a container here to add some curved borders and decent looking shadows via the decoration property
                                  return Container(
                                      child: SingleChildScrollView(
                                          controller: controller,
                                          // The child view/widget `MyBottomSheet` below is the actual bottom sheet view/widget
                                          child: MyBottomSheet(childHeightSetter: childHeightSetter),
                                      ),
                                      decoration: const BoxDecoration(
                                          boxShadow: [
                                              BoxShadow(
                                                  color: Colors.grey,
                                                  blurRadius: 5.0,
                                                  spreadRadius: 2.0
                                              )
                                          ],
                                          borderRadius: BorderRadius.all(Radius.circular(20.0))
                                      ),
                                  );
                              });
                          },
                      ),
                  ],
              ),
          ),
      );
  }
}

And this would be your child view/widget (also your BottomSheet view/widget)

class MyBottomSheet extends StatefulWidget {
  // This below is the local callback variable. The `?` is because it may not be set if not required
  final ValueSetter<double>? childHeightSetter;

  const MyBottomSheet({Key? key, this.childHeightSetter}) : super(key: key);

  @override
  _MyBottomSheetState createState() => _MyBottomSheetState();
}

class _LoginBottomSheetState extends State<LoginBottomSheet> {
  // bsKey is the key used to reference the Child widget we are trying to calculate the height of. Check the `Card` container below
  GlobalKey bsKey = GlobalKey();

  // this method will me used to get the height of the child content and passed to the callback function so it can be triggered and the ratio can be calculated and set in the parent widget
  _getSizes() {
    final RenderBox? renderBoxRed =
      bsKey.currentContext?.findRenderObject() as RenderBox?;
    final cardHeight = renderBoxRed?.size.height;
    if (cardHeight != null) 
      super.widget.childHeightSetter?.call(cardHeight);
  }

  // This is the function to be called after the Child has been drawn
  _afterLayout(_) {
    _getSizes();
  }

  @override
  void initState() {
    super.initState();
    // On initialising state pass the _afterLayout method as a callback to trigger after the child Widget is drawn
    WidgetsBinding.instance?.addPostFrameCallback(_afterLayout);
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      key: bsKey, // This is the key mentioned above used to calculate it's height
      color: Colors.white,
      shadowColor: Colors.black,
      elevation: 40.0,
      margin: EdgeInsets.zero,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0))),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          // Random children for bottom sheet content
          const SizedBox(height: 10.0),
          Center(
            child: Container(
              child: const SizedBox(width: 40.0, height: 5.0),
              decoration: BoxDecoration(
                color: Colors.grey[400],
                borderRadius: BorderRadius.circular(5.0)
              ),
            ),
          ),
          const SizedBox(height: 10.0),
          const AnotherBottomSheetContentView()
        ],
      ),
    );
  }
}
Devenom
  • 915
  • 1
  • 9
  • 20
-6

the initialChildSize is the height of your ScrollView before its actually scrolled, so that means you can actually decide what it would look like. here is an example![the draggable scrollsheet here has initialChildSize: 0.1,maxChildSize: 1,minChildSize: 0.1, ]1

and this is the sheet after full scroll, i have actually wrapped the sheet with container that have a fixed height

Pompidou
  • 577
  • 4
  • 18
  • How you had given height to draggablescrollablesheet. Like if in your case, if i add another textformfield then layout adjust itself in that dynamically or we have to set height statically? – Umair Feb 19 '20 at 12:02
  • im using SingleChildScrollView with Column , the column main axis size is set to minimun, that means your column size grows with respect to your children – Pompidou Feb 19 '20 at 12:08
  • I just reeditted my question. Now i also included code in my question. I had given minimum height to column too. Can you please see where i am doing wrong? – Umair Feb 19 '20 at 12:24
  • the child card column isn't set to minimum – Pompidou Feb 19 '20 at 12:31
  • yes, i check that. But did expanded widget also creating problem in above code? – Umair Feb 19 '20 at 12:34
  • I'm having the same problem, I need my sheet height to adjust to its children height, aka a way to get children height before it's rendered. – Victor Roberti Camolesi Nov 05 '20 at 18:11
  • 3
    poor answer. no example – pjdupreez Dec 04 '20 at 13:23