Flutter 颤振-固定高度内的单视图

Flutter 颤振-固定高度内的单视图,flutter,height,fixed,singlechildscrollview,Flutter,Height,Fixed,Singlechildscrollview,我正在制作一个分割视图小部件,它可以通过拖动底部小部件来调整它们的比率。 问题是,我想在底部放置一些大的小部件,以便在扩展它时可以完全看到它,如果不扩展,只能看到部分 这是我的分割视图代码 class HorizontalSplitView extends StatefulWidget { final Widget top; final Widget bottom; final double ratio; const HorizontalSplitView( {Key

我正在制作一个分割视图小部件,它可以通过拖动底部小部件来调整它们的比率。 问题是,我想在底部放置一些大的小部件,以便在扩展它时可以完全看到它,如果不扩展,只能看到部分

这是我的分割视图代码

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,
              ),
            ),
          ],
        ),
      );
    });
  }
}
类HorizontalSplitView扩展StatefulWidget{
最终小部件顶部;
最终小部件底部;
最终倍率;
常量水平拆分视图(
{Key Key,@required this.top,@required this.bottom,this.ratio=0.2})
:super(key:key);
@凌驾
_HorizontalSplitViewState createState()=>\u HorizontalSplitViewState();
}
类_HorizontalSplitViewState扩展状态{
双u比;
双倍最大高度;
获取_height1=>_ratio*_maxHeight;
获取_高度2=>(1-_比率)*\u最大高度;
@凌驾
void initState(){
super.initState();
_ratio=widget.ratio;
}
@凌驾
小部件构建(构建上下文){
返回LayoutBuilder(生成器:(上下文,框约束){
_maxHeight=constraints.maxHeight;
返回大小框(
高度:constraints.maxHeight,
子:列(
crossAxisAlignment:crossAxisAlignment.stretch,
儿童:[
大小盒子(
高度:_高度1,
child:widget.top,
),
手势检测器(
行为:HitTestBehavior.transparent,
onPanUpdate:(DragUpdate详细信息){
设置状态(){
_比率+=details.delta.dy/_最大高度;
如果(_比率>0.85)
_比率=0.85;
否则,如果(_比率<0.0)_比率=0.0;
});
},
onPanEnd:(绘图详细信息){
设置状态(){
如果(_比率<0.5)
_比率=0.0;

否则如果(0.6你也可以这样做

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

你也可以这样做

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

如下图所示,通过改变布局来解决

@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,
                          ),
                        ],
                      ),
                    )),
              ),
            ),
          ),
        ]),
      );
    });
  }
@覆盖
小部件构建(构建上下文){
返回LayoutBuilder(生成器:(上下文,框约束){
_maxHeight=constraints.maxHeight;
返回脚手架(
//appBar:NavigationBar(appBarKey,searchFocus),
主体:堆栈(对齐方式:alignment.bottomCenter,子对象:[
填充物(
填充:常数边集全部(8.0),
子对象:对齐(
对齐:alignment.topCenter,
子:容器(
高度:(_maxHeight-_offset.dy-10.0)<(_maxHeight/2)
?_最大高度/2
:_maxHeight-_offset.dy-10.0,
装饰:盒子装饰(
颜色:颜色。橙色,
边框:边框。全部(颜色:颜色。黑色),
),
儿童:中心(
子项:文本('top'),
)),
),
),
手势检测器(
onPanUpdate:(详细信息){
_偏移量=偏移量(0,_offset.dy-details.delta.dy);
如果(_offset.dy<_minHeight){
_偏移=偏移(0,最小高度);
}否则如果(\u offset.dy>\u maxHeight){
_偏移量=偏移量(0,_最大高度);
}
setState((){});
},
onPanEnd:(绘图详细信息){
如果(_offset.dy<_minHeight){
_偏移=偏移(0,最小高度);

}否则,如果(_minHeight通过更改堆栈布局解决,如下所示

@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,
                          ),
                        ],
                      ),
                    )),
              ),
            ),
          ),
        ]),
      );
    });
  }
@覆盖
小部件构建(构建上下文){
返回LayoutBuilder(生成器:(上下文,框约束){
_maxHeight=constraints.maxHeight;
返回脚手架(
//appBar:NavigationBar(appBarKey,searchFocus),
主体:堆栈(对齐方式:alignment.bottomCenter,子对象:[
填充物(
填充:常数边集全部(8.0),
子对象:对齐(
对齐:alignment.topCenter,
子:容器(
高度:(_maxHeight-_offset.dy-10.0)<(_maxHeight/2)
?_最大高度/2
:_maxHeight-_offset.dy-10.0,
装饰:盒子装饰(
颜色:颜色。橙色,
边框:边框。全部(颜色:颜色。黑色),
),
儿童:中心(
子项:文本('top'),
)),
),
),
手势检测器(
onPanUpdate:(详细信息){
_偏移量=偏移量(0,_offset.dy-details.delta.dy);
如果(_offset.dy<_minHeight){
_偏移=偏移(0,最小高度);
}否则如果(\u offset.dy>\u maxHeight){
_偏移量=偏移量(0,_最大高度);
}
setState((){});
},
onPanEnd:(绘图详细信息){
如果(_offset.dy<_minHeight){
_偏移=偏移(0,最小高度);

}否则,如果(_minheights)这样,就不可能调整橙色和绿色小部件的大小。这样,就不可能调整橙色和绿色小部件的大小。