I am using Transform.translate
to animate a Container
as much as my finger move around on screen and I am using Listener widget to increase my offset
. but I noticed that if I keep move my container
outside the screen it also will keep go through outside the screen.
I also wrapped it into safe area
but it also keeps going outside the border.
How can I prevent this behavior?
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,
)
),
),
),
),
);
}
}
CodePudding user response:
The update position using Transform.translate
will be based on user tap location.
///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(() {});
}
using Stack user can tap anywhere
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(() {});
}
You can follow the example and select the one you prefer.
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,
),
),
],
),
);
}
}