Flutter - SingleChildScrollView within fixed height

812 Views Asked by At

I am making a split-view widget that can adjust their ratio by dragging bottom widget. The thing is that I want to put some big widget on the bottom so that it can be seen fully when I extend it, only partially if not.

Split-view design here

And here's my code for split view.

class HorizontalSplitView extends StatefulWidget {
  final Widget top;
  final Widget bottom;
  final double ratio;

const HorizontalSplitView(
      {Key key, @required this.top, @required this.bottom, this.ratio = 0.2})
      : super(key: key);

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

class _HorizontalSplitViewState extends State<HorizontalSplitView> {
  double _ratio;
  double _maxHeight;

  get _height1 => _ratio * _maxHeight;

  get _height2 => (1 - _ratio) * _maxHeight;


@override
void initState() {
  super.initState();
   _ratio = widget.ratio;
 }

@override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, BoxConstraints constraints) {
      _maxHeight = constraints.maxHeight;
      return SizedBox(
        height: constraints.maxHeight,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            SizedBox(
              height: _height1,
              child: widget.top,
            ),
            GestureDetector(
              behavior: HitTestBehavior.translucent,
              onPanUpdate: (DragUpdateDetails details) {
                setState(() {
                  _ratio += details.delta.dy / _maxHeight;
                  if (_ratio > 0.85)
                    _ratio = 0.85;
                  else if (_ratio < 0.0) _ratio = 0.0;
                });
              },
              onPanEnd: (DragEndDetails details) {
                setState(() {
                  if (_ratio < 0.5)
                    _ratio = 0.0;
                  else if (0.6 <= _ratio && _ratio < 0.8)
                    _ratio = 0.6;
                  else if (0.8 < _ratio) _ratio = 0.85;
                });
              },
              child: SizedBox(
                height: _height2,
                child: widget.bottom,
              ),
            ),
          ],
        ),
      );
    });
  }
}

The thing is if I put scrollchildview with boxconstraint height instead of sized box widget It throws overflow error. Is there any way to put scrollview or any other widget that can be located in determined height sizedBox widget? Thanks in advance.

2

There are 2 best solutions below

0
On

Solved by changing layout as Stack like below

@override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, BoxConstraints constraints) {
      _maxHeight = constraints.maxHeight;
      return Scaffold(
        //appBar: NavigationBar(appBarKey, searchFocus),
        body: Stack(alignment: Alignment.bottomCenter, children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Align(
              alignment: Alignment.topCenter,
              child: Container(
                  height: (_maxHeight - _offset.dy - 10.0) < (_maxHeight / 2)
                      ? _maxHeight / 2
                      : _maxHeight - _offset.dy - 10.0,
                  decoration: BoxDecoration(
                    color: Colors.orange,
                    border: Border.all(color: Colors.black),
                  ),
                  child: Center(
                    child: Text('top'),
                  )),
            ),
          ),
          GestureDetector(
            onPanUpdate: (details) {
              _offset = Offset(0, _offset.dy - details.delta.dy);
              if (_offset.dy < _minHeight) {
                _offset = Offset(0, _minHeight);
              } else if (_offset.dy > _maxHeight) {
                _offset = Offset(0, _maxHeight);
              }
              setState(() {});
            },
            onPanEnd: (DragEndDetails details) {
              if (_offset.dy < _minHeight) {
                _offset = Offset(0, _minHeight);
              } else if (_minHeight<_offset.dy && _offset.dy<_maxHeight/2){
                _offset = Offset(0, _maxHeight/2);
              } else if (_offset.dy > _maxHeight/2) {
                _offset = Offset(0, _maxHeight);
              }
              setState(() {});
            },
            child: AnimatedContainer(
              duration: Duration.zero,
              curve: Curves.easeOut,
              height: _offset.dy,
              alignment: Alignment.center,
              child: SingleChildScrollView(
                physics: NeverScrollableScrollPhysics(),
                child: ConstrainedBox(
                    constraints: BoxConstraints(
                      minHeight: _offset.dy,
                    ),
                    child: IntrinsicHeight(
                      child: Column(
                        children: [
                          Container(
                            // A fixed-height child.
                            color: Colors.black,
                            height: 120.0,
                          ),
                          Expanded(
                            child: Container(
                              color: Colors.blue,
                              height: 300.0,
                            ),
                          ),
                          Container(
                            // A fixed-height child.
                            color: Colors.yellow,
                            height: 120.0,
                          ),
                        ],
                      ),
                    )),
              ),
            ),
          ),
        ]),
      );
    });
  }
1
On

you can do this way also,

Column(
          children: [
            Container(
              height: 200,
              color: Colors.orange,
            ),
            Expanded(
              child: SingleChildScrollView(
                scrollDirection: Axis.vertical,
                child: Container(
                  color: Colors.green,
                ),
              ),
            )
          ],
        )