为啥容器在侧面同时从顶部和底部调整大小,以及同时向左和向右调整?

Posted

技术标签:

【中文标题】为啥容器在侧面同时从顶部和底部调整大小,以及同时向左和向右调整?【英文标题】:Why is the container resizing from the top and bottom at the side time, as well as left and right at the same time?为什么容器在侧面同时从顶部和底部调整大小,以及同时向左和向右调整? 【发布时间】:2021-11-27 04:56:59 【问题描述】:

我正在尝试构建一个可调整大小的容器,该容器可以容纳一个孩子,然后一次可以从任一侧调整大小。但是,从一侧拖动也会拖动另一侧。即在向右拖动时,左侧也被拖动。与顶部相同,顶部拖动底部,反之亦然。请帮忙。为不那么可读的代码道歉。

         
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 MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Material App Bar'),
        ),
        body: Center(
          child: ResizeableContainer(
            currentHeight: 200,
            currentWidth: 200,
            child: Container(
              color: Colors.yellow,
            ),
          ),
        ),
      ),
    );
  


enum ReferenceSide 
  top,
  bottom,
  left,
  right,


double referenceThickness = 4.0;

class ResizeableContainer extends StatefulWidget 
  ResizeableContainer(
    Key? key,
    required this.currentHeight,
    required this.currentWidth,
    required this.child,
  ) : super(key: key);
  double currentWidth;
  double currentHeight;
  Widget child;
  @override
  _ResizeableContainerState createState() => _ResizeableContainerState();


class _ResizeableContainerState extends State<ResizeableContainer> 
  @override
  Widget build(BuildContext context) 
    void onHorizontalDragLeft(DragUpdateDetails details) 
      setState(() 
        widget.currentWidth -= details.delta.dx;
      );
    

    void onHorizontalDragRight(DragUpdateDetails details) 
      setState(() 
        //widget.currentWidth += details.delta.dx;
        widget.currentWidth += details.delta.dx;
      );
    

    void onVerticalDragUp(DragUpdateDetails details) 
      setState(() 
        widget.currentHeight -= details.delta.dy;
        widget.currentHeight > 0 ? widget.currentHeight : 0;
      );
    

    void onVerticalDragDown(DragUpdateDetails details) 
      setState(() 
        widget.currentHeight += details.delta.dy;
        widget.currentHeight > 0 ? widget.currentHeight : 0;
      );
    

    return SizedBox(
      width: widget.currentWidth.clamp(4, 800),
      height: widget.currentHeight.clamp(4, 800),
      child: Stack(
        children: [
          widget.child,
          _DragReferences(
            length: widget.currentWidth,
            side: ReferenceSide.top,
            onDragCallBack: onVerticalDragUp,
          ),
          _DragReferences(
            length: widget.currentWidth,
            side: ReferenceSide.bottom,
            onDragCallBack: onVerticalDragDown,
          ),
          _DragReferences(
            length: widget.currentHeight,
            side: ReferenceSide.left,
            onDragCallBack: onHorizontalDragLeft,
          ),
          _DragReferences(
            length: widget.currentHeight,
            side: ReferenceSide.right,
            onDragCallBack: onHorizontalDragRight,
          )
        ],
      ),
    );
  



class _DragReferences extends StatefulWidget 
  _DragReferences(
      Key? key, required this.length, required this.side, this.onDragCallBack)
      : super(key: key);

  ReferenceSide side;
  double length;
  void Function(DragUpdateDetails)? onDragCallBack;

  @override
  _DragReferencesState createState() => _DragReferencesState();


class _DragReferencesState extends State<_DragReferences> 
  @override
  Widget build(BuildContext context) 
    bool isLeftSide = widget.side == ReferenceSide.left;
    bool isRightSide = widget.side == ReferenceSide.right;
    bool isTopSide = widget.side == ReferenceSide.top;
    bool isBottomSide = widget.side == ReferenceSide.bottom;

    return Positioned(
      left: isRightSide ? null : 0,
      right: isLeftSide ? null : 0,
      top: isBottomSide ? null : 0,
      bottom: isTopSide ? null : 0,
      child: GestureDetector(
        onVerticalDragUpdate:
            isTopSide || isBottomSide ? widget.onDragCallBack : null,
        onHorizontalDragUpdate:
            isLeftSide || isRightSide ? widget.onDragCallBack : null,
        child: _getMouseRegion(side: widget.side, length: widget.length),
      ),
    );
  



Widget _getMouseRegion(required ReferenceSide side, required double length) 
  bool isVertical = side == ReferenceSide.left || side == ReferenceSide.right;
  return

      
      MouseRegion(
    cursor: isVertical
        ? SystemMouseCursors.resizeLeftRight
        : SystemMouseCursors.resizeUpDown,
    opaque: true,
    child: Container(
      height: isVertical ? length : referenceThickness,
      width: isVertical ? referenceThickness : length,
      color: isVertical ? Colors.amber : Colors.red,
    ),
  );

        

【问题讨论】:

【参考方案1】:

这是因为您的 Container 位于 Center() 中。正因为如此,Box 与左侧和右侧的距离始终相同,并且当您缩小盒子时,它也会重新定位。如果您希望 Container 位于屏幕中间,您可以执行以下操作:

Center(
   child: SizedBox(
   height: 300, // Or whatever works for you
   width: 300,
   child: ResizeableContainer(
      currentHeight: 200,
      currentWidth: 200,
      child: Container(
         color: Colors.yellow,
      ),
   )
),

【讨论】:

以上是关于为啥容器在侧面同时从顶部和底部调整大小,以及同时向左和向右调整?的主要内容,如果未能解决你的问题,请参考以下文章

同时使用css显示图像裁剪图像的顶部和底部

使用窗口调整自定义视图的大小

如何强制 div 位于视口的顶部/底部,同时不将其从文档流中取出?

从底部调整大小时防止Windows窗体元素离开视图?

从 xib 文件加载的自动调整视图大小

如何在底部和所有侧面创建带有盒子阴影的容器