使用手势颤动可调整大小的容器

Raj*_*kad 5 dart flutter flutter-layout flutter-animation

我想创建一个可调整大小的容器,用户可以使用水平拖动来调整其大小。

这个 Gif 可以解释这个要求:

在此输入图像描述

我尝试了 GestureDetector.horizo​​ntal 拖动,但结果相差甚远:

Container(
        color: primary,
        width: size.width,
        height: 40,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            GestureDetector(
              onHorizontalDragUpdate: (details) {
                final double newWidth;
                if (details.delta.dx > 0) {
                  // movement in positive direction
                  final newWidth = size.width + 1;

                  print(newWidth);
                  final updatedSize = Size(newWidth, size.height);

                  setState(() {
                    size = updatedSize;
                  });
                } else {
                  // movement in negative direction
                  final newWidth = math.max(size.width - 1, 5).toDouble();
                  print(newWidth);
                  final updatedSize = Size(newWidth, size.height);

                  setState(() {
                    size = updatedSize;
                  });
                }
              },
              child: const Icon(
                Icons.navigate_before_rounded,
                color: Colors.white,
              ),
            ),
            GestureDetector(
              onHorizontalDragUpdate: (det) {
                if (det.delta.dx > 1) {
                  var newWidth = size.width + 1;

                  final updatedSize = Size(newWidth, size.height);

                  setState(() {
                    size = updatedSize;
                  });
                } else {
                  var newWidth = size.width - 1;
                  newWidth = math.max(newWidth, 10);
                  final updatedSize = Size(newWidth, size.height);

                  setState(() {
                    size = updatedSize;
                  });
                }

                
              },
              child: const Icon(
                Icons.navigate_next_rounded,
                color: Colors.white,
              ),
            ),
          ],
        ),
      ),
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我正在寻找一种使用拖动来改变一侧尺寸的方法,宽度也应该根据拖动方向减小或增加,如果可能的话,整个容器也可以移动。

Md.*_*ikh 7

您可以StackPositioned小部件一起使用来处理容器大小调整并拖动我正在使用的完整容器transform

在此输入图像描述

在 dartPad 上运行

您可以使用这个小部件。

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

  @override
  State<FContainer> createState() => _FContainerState();
}

class _FContainerState extends State<FContainer> {

  ///initial position
  double leftPos = 33;
  double rightPos = 33;
  double transformX = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: LayoutBuilder(
        builder: (context, constraints) => Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              transform: Matrix4.translationValues(transformX, 0, 0),
              height: 60,
              width: constraints.maxWidth,
              child: Stack(
                children: [
                  Positioned(
                    top: 0,
                    bottom: 0,
                    left: leftPos,
                    right: rightPos,
                    child: Row(
                      children: [
                        GestureDetector(
                          onTap: () {},
                          onHorizontalDragUpdate: (details) {
                            leftPos = details.globalPosition.dx;
                            setState(() {});
                            debugPrint(leftPos.toString());
                          },
                          child: Container(
                            height: 60,
                            color: Colors.purple,
                            child: const Icon(
                              Icons.navigate_next_rounded,
                              color: Colors.black,
                            ),
                          ),
                        ),
                        Expanded(
                          child: GestureDetector(
                            onTap: () {},
                            onHorizontalDragUpdate: (details) {
                              final midPos = details.delta;
                              transformX += midPos.dx;
                              setState(() {});
                              debugPrint(midPos.toString());
                            },
                            child: Container(
                              color: Colors.purple,
                            ),
                          ),
                        ),
                        GestureDetector(
                          onTap: () {},
                          onHorizontalDragUpdate: (details) {
                            rightPos = constraints.maxWidth -
                                details.globalPosition.dx;
                            setState(() {});
                            debugPrint(rightPos.toString());
                          },
                          child: Container(
                            height: 60,
                            color: Colors.purple,
                            child: const Icon(
                              Icons.navigate_before_rounded,
                              color: Colors.black,
                            ),
                          ),
                        ),
                      ],
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以使用 if 条件换行以避免离开屏幕。


小智 1

这是 @Yeasin Sheikh\xc2\xb4s 答案的更新版本,它解决了一些错误并避免了超出窗口和跨越自身。

\n
class inputBox extends StatefulWidget {\n  inputBox({Key? key}) : super(key: key);\n\n  @override\n  State<inputBox> createState() => _inputBoxState();\n}\n\nclass _inputBoxState extends State<inputBox> {\n  ///initial position or size of the bar\n  double leftPos = 30;\n  double rightPos = 30;\n  double transformX = 0;\n  double barHeight = 30;\n\n  double _expandedWidth = 0.0; // keep track of the middle bar width\n\n  @override\n  Widget build(BuildContext context) {\n    return Center(\n      child: LayoutBuilder(\n        builder: (context, constraints) => Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: [\n            Container(\n              transform: Matrix4.translationValues(0, 0, 0),\n              height: barHeight,\n              width: constraints.maxWidth,\n              child: Stack(\n                children: [\n                  Positioned(\n                    top: 0,\n                    bottom: 0,\n                    left: leftPos,\n                    right: rightPos,\n                    child: Row(\n                      children: [\n                        GestureDetector(\n                          onTap: () {},\n                          onHorizontalDragUpdate: (DragUpdateDetails details) {\n                            final moveDelta = details.delta;\n\n                            setState(() {\n                              // Don't let the user pass outside the window or through the right dragbox\n                              if (leftPos > 0 && _expandedWidth > 10) {\n                                leftPos += moveDelta.dx;\n                              } else if (leftPos < 0) {\n                                // Do something when leftPos is less than zero\n                                leftPos = 0.01;\n                              } else if (_expandedWidth < 10) {\n                                // Do something when _expandedWidth is less than\n                                leftPos -= 20;\n                              }\n                            });\n                          },\n                          child: Container(\n                            height: barHeight,\n                            decoration: BoxDecoration(\n                              borderRadius: BorderRadius.only(\n                                  topRight: Radius.circular(0),\n                                  bottomRight: Radius.circular(0),\n                                  topLeft: Radius.circular(barHeight * 0.315),\n                                  bottomLeft:\n                                      Radius.circular(barHeight * 0.315)),\n                              color: Color.fromARGB(255, 119, 176, 39),\n                            ),\n                            child: const Icon(\n                              Icons.navigate_next_rounded,\n                              color: Colors.black,\n                            ),\n                          ),\n                        ),\n                        Expanded(\n                          child: LayoutBuilder(\n                            builder: (BuildContext context,\n                                BoxConstraints constraints) {\n                              double containerWidth = constraints.maxWidth;\n                              _expandedWidth =\n                                  containerWidth; // store the current width in a state variable\n                              return GestureDetector(\n                                onTap: () {},\n                                onHorizontalDragUpdate:\n                                    (DragUpdateDetails details) {\n                                  final moveDelta = details.delta;\n\n                                  setState(() {\n                                    if (leftPos > 0 && rightPos > 0) {\n                                      leftPos += moveDelta.dx;\n                                      rightPos -= moveDelta.dx;\n                                    } else if (leftPos < 0) {\n                                      // Do something when leftPos is less than zero\n                                      leftPos +=\n                                          moveDelta.dx + 10; // move back in\n                                      rightPos -=\n                                          moveDelta.dx + 10; // move back in\n                                    } else if (rightPos < 0) {\n                                      // Do something when rightPos is less than zero\n                                      leftPos +=\n                                          moveDelta.dx - 10; // move back in\n                                      rightPos -=\n                                          moveDelta.dx - 10; // move back in\n                                    }\n                                  });\n                                },\n                                child: Container(\n                                  color: Color.fromARGB(255, 119, 176, 39),\n                                  width: containerWidth,\n                                ),\n                              );\n                            },\n                          ),\n                        ),\n                        GestureDetector(\n                            onTap: () {},\n                            onHorizontalDragUpdate:\n                                (DragUpdateDetails details) {\n                              final moveDelta = details.delta;\n                              setState(() {\n\n                                // Don't let the user pass outside the window or through the left dragbox\n                                if (rightPos > 0 && _expandedWidth > 10) {\n                                  rightPos -= moveDelta.dx;\n                                } else if (rightPos < 0) {\n                                  // Do something when rightPos is less than zero\n                                  rightPos = 0.01;\n                                } else if (_expandedWidth < 10) {\n                                  // Do something when _expandedWidth is less than\n                                  rightPos -= 20;\n                                }\n                              });\n                            },\n                            child: Container(\n                                decoration: BoxDecoration(\n                                  borderRadius: BorderRadius.only(\n                                      topRight:\n                                          Radius.circular(barHeight * 0.315),\n                                      bottomRight:\n                                          Radius.circular(barHeight * 0.315),\n                                      topLeft: Radius.circular(0),\n                                      bottomLeft: Radius.circular(0)),\n                                  color: Color.fromARGB(255, 119, 176, 39),\n                                ),\n                                height: barHeight,\n                                child: const Icon(\n                                  Icons.navigate_before_rounded,\n                                  color: Colors.black,\n                                ))),\n                      ],\n                    ),\n                  )\n                ],\n              ),\n            )\n          ],\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n