使用手势调整Flutter容器大小

fcg9iug3  于 2023-03-24  发布在  Flutter
关注(0)|答案(2)|浏览(155)

我想创建一个可调整大小的容器,可以由用户使用水平拖动调整大小。
这个Gif可以解释这个需求:

我尝试了GestureDetector.水平拖动,但结果是:

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,
              ),
            ),
          ],
        ),
      ),

我正在寻找一种方法来获得使用拖动一侧的大小变化,也应该减少或增加的宽度拖动方向的基础上,如果可能的话,整个容器可以移动以及。

iyr7buue

iyr7buue1#

您可以使用StackPositioned小部件来处理容器大小调整,并拖动整个容器(我正在使用transform)。

Run on 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,
                            ),
                          ),
                        ),
                      ],
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

您可以使用if条件进行 Package ,以避免超出屏幕。

fruv7luv

fruv7luv2#

这里是@Yeasin Sheikh的答案的更新版本,它解决了一些错误,避免了走出窗外和跨越自己。

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

  @override
  State<inputBox> createState() => _inputBoxState();
}

class _inputBoxState extends State<inputBox> {
  ///initial position or size of the bar
  double leftPos = 30;
  double rightPos = 30;
  double transformX = 0;
  double barHeight = 30;

  double _expandedWidth = 0.0; // keep track of the middle bar width

  @override
  Widget build(BuildContext context) {
    return Center(
      child: LayoutBuilder(
        builder: (context, constraints) => Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              transform: Matrix4.translationValues(0, 0, 0),
              height: barHeight,
              width: constraints.maxWidth,
              child: Stack(
                children: [
                  Positioned(
                    top: 0,
                    bottom: 0,
                    left: leftPos,
                    right: rightPos,
                    child: Row(
                      children: [
                        GestureDetector(
                          onTap: () {},
                          onHorizontalDragUpdate: (DragUpdateDetails details) {
                            final moveDelta = details.delta;

                            setState(() {
                              // Don't let the user pass outside the window or through the right dragbox
                              if (leftPos > 0 && _expandedWidth > 10) {
                                leftPos += moveDelta.dx;
                              } else if (leftPos < 0) {
                                // Do something when leftPos is less than zero
                                leftPos = 0.01;
                              } else if (_expandedWidth < 10) {
                                // Do something when _expandedWidth is less than
                                leftPos -= 20;
                              }
                            });
                          },
                          child: Container(
                            height: barHeight,
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.only(
                                  topRight: Radius.circular(0),
                                  bottomRight: Radius.circular(0),
                                  topLeft: Radius.circular(barHeight * 0.315),
                                  bottomLeft:
                                      Radius.circular(barHeight * 0.315)),
                              color: Color.fromARGB(255, 119, 176, 39),
                            ),
                            child: const Icon(
                              Icons.navigate_next_rounded,
                              color: Colors.black,
                            ),
                          ),
                        ),
                        Expanded(
                          child: LayoutBuilder(
                            builder: (BuildContext context,
                                BoxConstraints constraints) {
                              double containerWidth = constraints.maxWidth;
                              _expandedWidth =
                                  containerWidth; // store the current width in a state variable
                              return GestureDetector(
                                onTap: () {},
                                onHorizontalDragUpdate:
                                    (DragUpdateDetails details) {
                                  final moveDelta = details.delta;

                                  setState(() {
                                    if (leftPos > 0 && rightPos > 0) {
                                      leftPos += moveDelta.dx;
                                      rightPos -= moveDelta.dx;
                                    } else if (leftPos < 0) {
                                      // Do something when leftPos is less than zero
                                      leftPos +=
                                          moveDelta.dx + 10; // move back in
                                      rightPos -=
                                          moveDelta.dx + 10; // move back in
                                    } else if (rightPos < 0) {
                                      // Do something when rightPos is less than zero
                                      leftPos +=
                                          moveDelta.dx - 10; // move back in
                                      rightPos -=
                                          moveDelta.dx - 10; // move back in
                                    }
                                  });
                                },
                                child: Container(
                                  color: Color.fromARGB(255, 119, 176, 39),
                                  width: containerWidth,
                                ),
                              );
                            },
                          ),
                        ),
                        GestureDetector(
                            onTap: () {},
                            onHorizontalDragUpdate:
                                (DragUpdateDetails details) {
                              final moveDelta = details.delta;
                              setState(() {

                                // Don't let the user pass outside the window or through the left dragbox
                                if (rightPos > 0 && _expandedWidth > 10) {
                                  rightPos -= moveDelta.dx;
                                } else if (rightPos < 0) {
                                  // Do something when rightPos is less than zero
                                  rightPos = 0.01;
                                } else if (_expandedWidth < 10) {
                                  // Do something when _expandedWidth is less than
                                  rightPos -= 20;
                                }
                              });
                            },
                            child: Container(
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.only(
                                      topRight:
                                          Radius.circular(barHeight * 0.315),
                                      bottomRight:
                                          Radius.circular(barHeight * 0.315),
                                      topLeft: Radius.circular(0),
                                      bottomLeft: Radius.circular(0)),
                                  color: Color.fromARGB(255, 119, 176, 39),
                                ),
                                height: barHeight,
                                child: const Icon(
                                  Icons.navigate_before_rounded,
                                  color: Colors.black,
                                ))),
                      ],
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

相关问题