После поворота виджета GestureDetector не работает в стеке
К виджету нельзя прикоснуться или изменить положение виджета на фиолетовой отметке, когда я изменяю поворот виджета. и будет успешно затронут, когда угол поворота вернется на 0 градусов или до изменения поворота.
работает нормально, когда не вращается
это мой код
import 'package:flutter/material.dart';
import 'dart:math' as math;
class View_Test_Design extends StatefulWidget {
@override
_View_Test_DesignState createState() => _View_Test_DesignState();
}
class _View_Test_DesignState extends State<View_Test_Design> {
double x = 100;
double y = 100;
double w = 200;
double h = 50;
double r=0; // Not Working fine when change to another number
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Rotate|Pos|Drag"),
),
body: Stack(
children: <Widget>[
Positioned(
left: x,
top: y,
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
x = x + details.delta.dx;
y = y + details.delta.dy;
});
},
child: Transform.rotate(
angle: math.pi * r / 180,
child:
Container(width: w, height: h, color: Colors.red))))
],
),
);
}
}
любое решение, почему это не работает?
3 ответа
Это связано с тем, что виджет Transform переводит виджет за пределы родительского виджета. Поэтому вам нужно увеличить родительский виджет.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Rotate|Pos|Drag"),
),
body: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
left: x,
top: y,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
x = x + details.delta.dx;
y = y + details.delta.dy;
});
},
child: Transform.rotate(
angle: math.pi * r / 180,
child:
Container(width: w, height: h, color: Colors.red))))
],
),
);
}
Ответ отсюда https://github.com/flutter/flutter/issues/27587
Используйте виджет DeferredPointer для обнаружения жестов за пределами родителя.
Была аналогичная проблема, это мое решение.
https://stackoverflow.com/a/74165192/12098106
import 'package:flutter/material.dart';
// -------------------------------------------------------------------
// THE ITEM TO BE DRAWN
// -------------------------------------------------------------------
class DrawContainer {
Color color;
Offset offset;
double width;
double height;
double scale;
double angle;
late double _baseScaleFactor;
late double _baseAngleFactor;
DrawContainer(this.color, this.offset, this.width, this.height, this.scale,
this.angle) {
onScaleStart();
}
onScaleStart() {
_baseScaleFactor = scale;
_baseAngleFactor = angle;
}
onScaleUpdate(double scaleNew) =>
scale = (_baseScaleFactor * scaleNew).clamp(0.5, 5);
onRotateUpdate(double angleNew) => angle = _baseAngleFactor + angleNew;
}
// -------------------------------------------------------------------
// APP
// -------------------------------------------------------------------
void main() {
runApp(const MaterialApp(home: GestureTest()));
}
class GestureTest extends StatefulWidget {
const GestureTest({Key? key}) : super(key: key);
@override
// ignore: library_private_types_in_public_api
_GestureTestState createState() => _GestureTestState();
}
// -------------------------------------------------------------------
// APP STATE
// -------------------------------------------------------------------
class _GestureTestState extends State<GestureTest> {
final List<DrawContainer> containers = [
DrawContainer(Colors.red, const Offset(50, 50), 100, 100, 1.0, 0.0),
DrawContainer(Colors.yellow, const Offset(100, 100), 200, 100, 1.0, 0.0),
DrawContainer(Colors.green, const Offset(150, 150), 50, 100, 1.0, 0.0),
];
void onGestureStart(DrawContainer e) => e.onScaleStart();
onGestureUpdate(DrawContainer e, ScaleUpdateDetails d) {
e.offset = e.offset + d.focalPointDelta;
if (d.rotation != 0.0) e.onRotateUpdate(d.rotation);
if (d.scale != 1.0) e.onScaleUpdate(d.scale);
setState(() {}); // redraw
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SizedBox(
height: double.infinity,
width: double.infinity,
child: Stack(
children: [
...containers.map((e) {
return GestureDetector(
onScaleStart: (details) {
// detect two fingers to reset internal factors
if (details.pointerCount == 2) {
onGestureStart(e);
}
},
onScaleUpdate: (details) => onGestureUpdate(e, details),
child: DrawWidget(e));
}).toList(),
],
),
),
));
}
}
// -------------------------------------------------------------------
// POSITION, ROTATE AND SCALE THE WIDGET
// -------------------------------------------------------------------
class DrawWidget extends StatelessWidget {
final DrawContainer e;
const DrawWidget(this.e, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
left: e.offset.dx,
top: e.offset.dy,
child: Transform.rotate(
angle: e.angle,
child: Transform.scale(
scale: e.scale,
child: Container(
height: e.width,
width: e.height,
color: e.color,
),
),
),
),
],
);
}
}