Flutter - 在使用 Transform.rotate 旋转容器后,它的子手势检测器 ontap 方法不起作用
Flutter - after rotate container with Transform.rotate, it's child gesturedetector ontap method not working
当我将容器旋转45度或其他弧度时,删除按钮、展开按钮没有执行'onTap'、'onPanUpdate'手势。我发现用 'RotatedBox' 旋转容器很好,但是它的参数 'quarterTurns' 只支持 int 类型值。我知道 'Transform.rotate' 和 'RotatedBox' 之间的区别。 'Transform.rotate' 仅刷新 UI,'Rotatedbox' 影响其子布局。我不知道怎么办。
请帮助我,谢谢。
这是我的示例代码:
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: stickersViewNotifier,
child: Consumer<KSStickersViewNotifier>(
builder: (context, notifier, child) {
return Positioned(
left: stickersViewNotifier._left,
top: stickersViewNotifier._top,
child: GestureDetector(
onTap: () {
stickersViewNotifier.updateShouldShowControl(!stickersViewNotifier.shouldShowControl);
},
onPanDown: (DragDownDetails e) {
print("${e.globalPosition}");
},
onPanUpdate: (DragUpdateDetails e) {
stickersViewNotifier.panContainer(e.delta.dx, e.delta.dy);
},
onPanEnd: (DragEndDetails e) {
//打印滑动结束时在x、y轴上的速度
print(e.velocity);
},
child: Transform.rotate(
angle: 45 / 180 * math.pi,
child: Container(
width: stickersViewNotifier._width,
height: stickersViewNotifier._height,
child: Stack(
children: [
Padding(
padding: EdgeInsets.all(controlButtonWidth * 0.33),
child: DottedBorder(
color: stickersViewNotifier.shouldShowControl ? Colors.black : Colors.transparent,
strokeWidth: 1,
dashPattern: [5, 5, 5, 5],
child: Container(
width: double.infinity,
height: double.infinity,
child: Padding(
padding: EdgeInsets.all(controlButtonWidth * 0.67),
child: Center(
child: containerWidget,
),
),
),
),
),
Offstage(
offstage: !stickersViewNotifier.shouldShowControl,
child: GestureDetector(
onTap: () {
onDelete(notifier.tag);
},
child: Container(
width: controlButtonWidth,
height: controlButtonWidth,
decoration: BoxDecoration(color: Colors.redAccent, borderRadius: BorderRadius.circular(controlButtonWidth / 2)),
child: Center(
child: Icon(
Icons.close_rounded,
color: Colors.white,
size: controlButtonWidth - 5,
),
),
),
),
),
Positioned(
right: 0,
child: Offstage(
offstage: !stickersViewNotifier.shouldShowControl,
child: GestureDetector(
child: Container(
width: controlButtonWidth,
height: controlButtonWidth,
decoration: BoxDecoration(color: Colors.redAccent, borderRadius: BorderRadius.circular(controlButtonWidth / 2)),
child: Center(
child: Icon(
Icons.refresh_rounded,
color: Colors.white,
size: controlButtonWidth - 5,
),
),
),
),
),
),
Positioned(
right: 0,
bottom: 0,
child: Offstage(
offstage: !stickersViewNotifier.shouldShowControl,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
double dx = details.delta.dx;
double dy = details.delta.dy;
stickersViewNotifier.zoom(dx, dy);
},
child: Container(
width: controlButtonWidth,
height: controlButtonWidth,
decoration: BoxDecoration(color: Colors.redAccent, borderRadius: BorderRadius.circular(controlButtonWidth / 2)),
child: Center(
child: Icon(
Icons.zoom_out_map_rounded,
color: Colors.white,
size: controlButtonWidth - 8,
),
),
),
),
),
),
],
),
),
)));
},
),
);
}
这里有一个演示:希望你能明白。在顶级小部件上移动按钮。并旋转整个容器,包括按钮。也为此目的使用多堆栈。
import 'dart:math';
import 'package:flutter/material.dart';
class DeleteOnRotate extends StatefulWidget {
DeleteOnRotate({Key? key}) : super(key: key);
@override
_DeleteOnRotateState createState() => _DeleteOnRotateState();
}
class _DeleteOnRotateState extends State<DeleteOnRotate> {
double _angle = 0;
bool _visible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: TextButton(
child: Text("ChangeVisibility"),
onPressed: () {
setState(() {
_visible = !_visible;
});
},
),
),
///stickerBox
if (_visible)
Container(
height: constraints.maxHeight * .6,
width: constraints.maxWidth,
color: Colors.cyanAccent.withOpacity(.2),
child: Stack(
children: [
Align(
alignment: Alignment(0, 0),
child: Transform.rotate(
angle: _angle / 180 * pi,
child: Container(
height: constraints.maxHeight * .35,
width: constraints.maxWidth * .6,
decoration: BoxDecoration(
border: Border.all(
style: BorderStyle.solid,
),
),
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
child: IconButton(
onPressed: () {
setState(() {
_visible = !_visible;
});
},
icon: Icon(
Icons.delete,
),
),
),
Positioned(
top: 0,
right: 0,
child: IconButton(
onPressed: () {
setState(() {
_angle += 45;
});
},
icon: Icon(
Icons.rotate_right,
),
),
),
],
),
),
),
)
],
),
),
],
),
),
);
}
}
```
当我将容器旋转45度或其他弧度时,删除按钮、展开按钮没有执行'onTap'、'onPanUpdate'手势。我发现用 'RotatedBox' 旋转容器很好,但是它的参数 'quarterTurns' 只支持 int 类型值。我知道 'Transform.rotate' 和 'RotatedBox' 之间的区别。 'Transform.rotate' 仅刷新 UI,'Rotatedbox' 影响其子布局。我不知道怎么办。
请帮助我,谢谢。
这是我的示例代码:
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: stickersViewNotifier,
child: Consumer<KSStickersViewNotifier>(
builder: (context, notifier, child) {
return Positioned(
left: stickersViewNotifier._left,
top: stickersViewNotifier._top,
child: GestureDetector(
onTap: () {
stickersViewNotifier.updateShouldShowControl(!stickersViewNotifier.shouldShowControl);
},
onPanDown: (DragDownDetails e) {
print("${e.globalPosition}");
},
onPanUpdate: (DragUpdateDetails e) {
stickersViewNotifier.panContainer(e.delta.dx, e.delta.dy);
},
onPanEnd: (DragEndDetails e) {
//打印滑动结束时在x、y轴上的速度
print(e.velocity);
},
child: Transform.rotate(
angle: 45 / 180 * math.pi,
child: Container(
width: stickersViewNotifier._width,
height: stickersViewNotifier._height,
child: Stack(
children: [
Padding(
padding: EdgeInsets.all(controlButtonWidth * 0.33),
child: DottedBorder(
color: stickersViewNotifier.shouldShowControl ? Colors.black : Colors.transparent,
strokeWidth: 1,
dashPattern: [5, 5, 5, 5],
child: Container(
width: double.infinity,
height: double.infinity,
child: Padding(
padding: EdgeInsets.all(controlButtonWidth * 0.67),
child: Center(
child: containerWidget,
),
),
),
),
),
Offstage(
offstage: !stickersViewNotifier.shouldShowControl,
child: GestureDetector(
onTap: () {
onDelete(notifier.tag);
},
child: Container(
width: controlButtonWidth,
height: controlButtonWidth,
decoration: BoxDecoration(color: Colors.redAccent, borderRadius: BorderRadius.circular(controlButtonWidth / 2)),
child: Center(
child: Icon(
Icons.close_rounded,
color: Colors.white,
size: controlButtonWidth - 5,
),
),
),
),
),
Positioned(
right: 0,
child: Offstage(
offstage: !stickersViewNotifier.shouldShowControl,
child: GestureDetector(
child: Container(
width: controlButtonWidth,
height: controlButtonWidth,
decoration: BoxDecoration(color: Colors.redAccent, borderRadius: BorderRadius.circular(controlButtonWidth / 2)),
child: Center(
child: Icon(
Icons.refresh_rounded,
color: Colors.white,
size: controlButtonWidth - 5,
),
),
),
),
),
),
Positioned(
right: 0,
bottom: 0,
child: Offstage(
offstage: !stickersViewNotifier.shouldShowControl,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
double dx = details.delta.dx;
double dy = details.delta.dy;
stickersViewNotifier.zoom(dx, dy);
},
child: Container(
width: controlButtonWidth,
height: controlButtonWidth,
decoration: BoxDecoration(color: Colors.redAccent, borderRadius: BorderRadius.circular(controlButtonWidth / 2)),
child: Center(
child: Icon(
Icons.zoom_out_map_rounded,
color: Colors.white,
size: controlButtonWidth - 8,
),
),
),
),
),
),
],
),
),
)));
},
),
);
}
这里有一个演示:希望你能明白。在顶级小部件上移动按钮。并旋转整个容器,包括按钮。也为此目的使用多堆栈。
import 'dart:math';
import 'package:flutter/material.dart';
class DeleteOnRotate extends StatefulWidget {
DeleteOnRotate({Key? key}) : super(key: key);
@override
_DeleteOnRotateState createState() => _DeleteOnRotateState();
}
class _DeleteOnRotateState extends State<DeleteOnRotate> {
double _angle = 0;
bool _visible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: TextButton(
child: Text("ChangeVisibility"),
onPressed: () {
setState(() {
_visible = !_visible;
});
},
),
),
///stickerBox
if (_visible)
Container(
height: constraints.maxHeight * .6,
width: constraints.maxWidth,
color: Colors.cyanAccent.withOpacity(.2),
child: Stack(
children: [
Align(
alignment: Alignment(0, 0),
child: Transform.rotate(
angle: _angle / 180 * pi,
child: Container(
height: constraints.maxHeight * .35,
width: constraints.maxWidth * .6,
decoration: BoxDecoration(
border: Border.all(
style: BorderStyle.solid,
),
),
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
child: IconButton(
onPressed: () {
setState(() {
_visible = !_visible;
});
},
icon: Icon(
Icons.delete,
),
),
),
Positioned(
top: 0,
right: 0,
child: IconButton(
onPressed: () {
setState(() {
_angle += 45;
});
},
icon: Icon(
Icons.rotate_right,
),
),
),
],
),
),
),
)
],
),
),
],
),
),
);
}
}
```