我如何使用 Transform.transalte 确保我的容器不会超出我的屏幕范围

How can i make sure that my Container does not go outside my screen using Transform.transalte

我正在使用 Transform.translateContainer 制作动画,就像我的手指在屏幕上四处移动一样,我正在使用 Listener 小部件来增加我的 offset。但我注意到,如果我继续将我的 container 移到屏幕外,它也会一直穿过屏幕外。 我也把它包装成 safe area 但它也一直在边界外。

如何防止这种行为?

import 'package:flutter/material.dart';

class Test extends StatefulWidget {
  const Test({Key? key}) : super(key: key);
  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {

  late Offset offsetLocal=  const Offset(0,0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Listener(
          onPointerMove:(t){
            offsetLocal+=t.delta;
            setState(() {});
          },
          child: Center(
            child: Transform.translate(
                offset: offsetLocal,
                child: Container(
                  color: Colors.red,
                  width: 200,
                  height: 200,
                )
            ),
          ),
        ),

      ),
    );
  }
}

使用 Transform.translate 的更新位置将基于用户点击位置。

 ///Tap position needed to be centered
  updatePositionOnTransform(BoxConstraints constraints, PointerMoveEvent t) {
    debugPrint(t.position.toString());
   
    //* using single condition force to one dimension
    // if (t.position.dx < constraints.maxWidth - boxSize.width / 2 &&
    //     t.position.dx > boxSize.width / 2 &&
    //     t.localPosition.dy > boxSize.height / 2 &&
    //     t.localPosition.dy < constraints.maxHeight - boxSize.height / 2) {
    //   offsetLocal += t.delta;
    //   setState(() {});
    // }

    double dx = 0;
    double dy = 0;

    if (t.position.dx < constraints.maxWidth - boxSize.width / 2 &&
        t.position.dx > boxSize.width / 2) {
      dx = t.delta.dx;
    }
    if (t.localPosition.dy > boxSize.height / 2 &&
        t.localPosition.dy < constraints.maxHeight - boxSize.height / 2) {
      dy = t.delta.dy;
    }
    offsetLocal += Offset(dx, dy);
    setState(() {});
  }

使用 Stack 用户可以点击任何地方

 updatePosition(BoxConstraints constraints, offset) {
    double dx = offset.dx;
    double dy = offset.dy;

    //* -100 is coming from half container size
    if (dx < constraints.maxWidth - boxSize.width / 2 &&
        dx > boxSize.width / 2) {
      offsetLocal = Offset(dx - (boxSize.width / 2), offsetLocal.dy);
    }
    if (dy > boxSize.height / 2 &&
        dy < constraints.maxHeight - boxSize.height / 2) {
      offsetLocal = Offset(offsetLocal.dx, dy - (boxSize.height / 2));
    }

    setState(() {});
  }

你可以按照这个例子和select你喜欢的那个。

class _TestState extends State<Test> {
  late Offset offsetLocal = const Offset(0, 0);

  updatePosition(BoxConstraints constraints, offset) {
    double dx = offset.dx;
    double dy = offset.dy;

    //* -100 is coming from half container size
    if (dx < constraints.maxWidth - boxSize.width / 2 &&
        dx > boxSize.width / 2) {
      offsetLocal = Offset(dx - (boxSize.width / 2), offsetLocal.dy);
    }
    if (dy > boxSize.height / 2 &&
        dy < constraints.maxHeight - boxSize.height / 2) {
      offsetLocal = Offset(offsetLocal.dx, dy - (boxSize.height / 2));
    }

    setState(() {});
  }

  ///Tap position needed to be centered
  updatePositionOnTransform(BoxConstraints constraints, PointerMoveEvent t) {
    debugPrint(t.position.toString());
   
    //* using single condition force to one dimension
    // if (t.position.dx < constraints.maxWidth - boxSize.width / 2 &&
    //     t.position.dx > boxSize.width / 2 &&
    //     t.localPosition.dy > boxSize.height / 2 &&
    //     t.localPosition.dy < constraints.maxHeight - boxSize.height / 2) {
    //   offsetLocal += t.delta;
    //   setState(() {});
    // }

    double dx = 0;
    double dy = 0;

    if (t.position.dx < constraints.maxWidth - boxSize.width / 2 &&
        t.position.dx > boxSize.width / 2) {
      dx = t.delta.dx;
    }
    if (t.localPosition.dy > boxSize.height / 2 &&
        t.localPosition.dy < constraints.maxHeight - boxSize.height / 2) {
      dy = t.delta.dy;
    }
    offsetLocal += Offset(dx, dy);
    setState(() {});
  }

  final Size boxSize = const Size(200, 200);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(
        builder: (context, constraints) => SafeArea(
          // child: usingTransform(constraints),
          child: usingStack(constraints),
        ),
      ),
    );
  }

  Listener usingTransform(constraints) {
    return Listener(
      onPointerMove: (t) {
        updatePositionOnTransform(constraints, t);
      },
      child: Center(
        child: Transform.translate(
            offset: offsetLocal,
            child: Container(
              color: Colors.red,
              width: 200,
              height: 200,
            )),
      ),
    );
  }

  GestureDetector usingStack(BoxConstraints constraints) {
    return GestureDetector(
      onPanUpdate: (details) {
        updatePosition(constraints, details.localPosition);
      },
      child: Stack(
        children: [
          Positioned(
            // duration: const Duration(milliseconds: 100), //you can use `AnimatedPositioned`
            left: offsetLocal.dx,
            top: offsetLocal.dy,
            child: Container(
              color: Colors.red,
              width: boxSize.width,
              height: boxSize.height,
            ),
          ),
        ],
      ),
    );
  }
}