Xiaocai found that when he failed to log in the Mi app market for a long time, there would be a sliding menu at the bottom of the half screen for users to download and promote. And in theFlutterThe half-screen bottom menu is not a simple oneBottomSheetCompleted, can passDraggableScrollableSheetAccording to the gesture operation, slide the fixed menu bar to complete; Simple dishes to learn;

DraggableScrollableSheet

Source code analysis

Const DraggableScrollableSheet({Key Key, this.initialChildSize = 0.5, // Initial ratio this.minChildSize = 0.25, MaxChildSize = 1.0, // maxChildSize this.expand = true, // Fill @required this.builder, }) @overridep Widget build(BuildContext context) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { _extent.availablePixels = widget.maxChildSize * constraints.biggest.height; final Widget sheet = FractionallySizedBox( heightFactor: _extent.currentExtent, child: widget.builder(context, _scrollController), alignment: Alignment.bottomCenter, ); return widget.expand ? SizedBox.expand(child: sheet) : sheet; }); }Copy the code

Simple analysis of the source code DraggableScrollableSheet as a StatefulWidget Widget, FractionallySizedBox based on the parent Widget, can set the width and height ratio of containers to build child content;

Case try

1. builder

The ScrollableWidgetBuilder constructor is a required field for displaying slidable child content in the DraggableScrollableSheet; The returned content must be a slidable ScrollableWidget, such as ListView/GridView/SingleChildScrollView.

_listWid(controller) => SingleChildScrollView( controller: controller, child: Column(children: [ Container( height: Color: color.blue. WithOpacity (0.8), borderRadius: Borderradio.all (radio.Circular (16.0))), Margin: EdgeInsets. Symmetric (vertical: 12.0)), Padding(Padding: EdgeInsets. Symmetric (Horizontal: 12.0), Child: GridView.builder(physics: ScrollPhysics(), Primary: false, shrinkWrap: true, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 5, mainAxisSpacing: 8.0, crossAxisSpacing: 12.0, childAspectRatio: 0.7), itemCount: 12, itemBuilder: (context, index) => GestureDetector( child: Column(children: <Widget>[ PhysicalModel( color: Colors.transparent, shape: BoxShape.circle, clipBehavior: Clip.antiAlias, child: Image.asset('images/icon_hzw01.jpg')), SizedBox(height: 4), Text (" one piece ")]), onTap: () {}))), ListView. Builder (physics: NeverScrollableScrollPhysics (), shrinkWrap: true, itemCount: 15, itemBuilder: (BuildContext context, index) => ListTile(title: Text('Current Item = ${(index + 1)}'))) ]));Copy the code

2. initialChildSize

InitialChildSize is used to display the ratio of the initial child Widgets to the parent Widget. At the same time, if the returned child Widget does not provide a ScrollController, the DraggableScrollableSheet will not slide with the gesture. InitialChildSize = minChildSize = maxChildSize;

_sheetWid02() => DraggableScrollableSheet(initialChildSize: 0.66, Builder: (BuildContext context, ScrollController scrollController) => Container( decoration: BoxDecoration( color: Color.grey.withopacity (0.4), borderRadius: borderRadius. Only (topLeft: Radius. Circular (16.0), topRight: The Radius. Circular (16.0))), the child: _listWid (null)));Copy the code

3. minChildSize & maxChildSize

MinChildSize and maxChildSize correspond to the maximum and minimum proportion of child Widgets to the whole, where initialChildSize should be between the two.

_sheetWid03() => DraggableScrollableSheet(initialChildSize: 0.6, minChildSize: 0.3, maxChildSize: 0.9, expand: true, builder: (BuildContext context, ScrollController scrollController) => Container( decoration: Border-radius: borderRadius. Only (topLeft: Radius. Circular (16.0), topRight: Radius. Circular (16.0)), Child: _listWid(scrollController)));Copy the code

4. expand

Expand is used to determine whether to fill the parent Widget. If the outer layer of DraggableScrollableSheet is fixed in height, it will not be affected. Expand is used to fill the parent Widget if the outer layer is not fixed in height. The source code for the construct is also populated by SizedBox. Expand for the parent Widget;

return widget.expand ? SizedBox.expand(child: sheet) : sheet;
Copy the code

A small extension

In the previous analysis of DraggableScrollableSheet, its source code used FractionallySizedBox scale container, a small dish to briefly understand, its source code is very simple, You can set the ratio of heightFactor and widthFactor to the parent Widget. You can set the alignment mode of the parent Widget by using the alignment.

SizedBox. Expand (Child: _sizedBox()) _sizedBox() => FractionallySizedBox(heightFactor: 0.5, widthFactor: Child: 0.5, alignment, alignment, center, the Container (color: Colors. DeepOrange. WithOpacity (0.4), the child: ListView.builder( itemCount: 15, itemBuilder: (BuildContext context, index) => ListTile(title: Text('Current Item = ${(index + 1)}')))));Copy the code


Example source code


Xiao CAI is not familiar with the gesture sliding process of DraggableScrollableSheet, and will further learn the gesture later. If there are mistakes, please give more guidance!

Source: Little Monk A Ce