FlatButton 翻译后 Flutter onPressed 不起作用
Flutter onPressed not works after FlatButton translate
我在使用 ScrollView
和 Transform
时遇到了一些事件处理问题。布局结构是这样的,ScrollView
和Transform
存在于Stack
.
里面
我想让ScrollView
在Container(Colors.cyan)
中滚动到FlatButton
外时滚动,事件可以穿透到ScrollView。
点击FlatButton
onPress to work。实际上,点击FlatButton
两次后,无论点击初始位置还是当前位置,都不再移动。 FlatButton
控件在尺寸范围内离开初始位置,不再检测到点击事件,但我没看懂。代码如下:
class EventListener extends StatefulWidget {
@override
_EventListenerState createState() => _EventListenerState();
}
class _EventListenerState extends State<EventListener> {
Offset offset = Offset(0, 0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventListener"),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.teal,
height: 300,
),
Container(
color: Colors.orange,
height: 400,
)
],
),
),
Container(
color: Colors.cyan,
width: double.infinity,
height: 400,
alignment: Alignment.center,
child: SizedBox(
width: 100,
height: 100,
child: Transform.translate(
offset: offset,
child: FlatButton(
color: Colors.orange,
onPressed: () {
setState(() {
offset += Offset(50, 50);
});
print('click !');
},
child: Text("translate"),
),
),
),
)
],
),
);
}
}
这是 Buttons and Stacks 的一个已知问题,我建议遇到此类问题的任何人查看 this discussion on Github。
TL;DR:
翻译小部件时,您可以点击的区域由两部分组成:
- 父控件的面积
- 子区域(这里的Flatbutton)
见下图:
通常的解决方法:
正在扩展父级的大小。
这给了我们这样的东西:
Container(
width: double.infinity,
height: 400,
child: Transform.translate(
offset: offset,
child: SizedBox(
width: 100,
height: 100,
child: FlatButton(
onPressed: () => print('tap button'),
child: Text("translate"),
),
),
),
),
在这里您可以点击父容器中的任意位置。
为您解决
您实际上想要一些不同的东西:除了按钮之外的任何东西都是可点击的。为此你需要:
- GestureDetector 是可点击区域的父级
- 带有不执行任何操作的 onPressed 方法的 FlatButton
如果我们只希望蓝色容器可点击,那么这是最终代码:
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(
home: EventListener(),
));
class EventListener extends StatefulWidget {
@override
_EventListenerState createState() => _EventListenerState();
}
class _EventListenerState extends State<EventListener> {
Offset offset = Offset(0, 0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventListener"),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.teal,
height: 300,
),
Container(
color: Colors.orange,
height: 400,
)
],
),
),
GestureDetector(
onTap: () {
setState(() {
offset += Offset(50, 50);
});
},
child: Container(
width: double.infinity,
height: 400,
color: Colors.cyan,
alignment: Alignment.center,
child: Transform.translate(
offset: offset,
child: SizedBox(
width: 100,
height: 100,
child: FlatButton(
color: Colors.orange,
onPressed: () {},
child: Text("translate"),
),
),
),
),
)
],
),
);
}
}
为什么这有效
如前所述,父容器是青色容器,此容器中的任何区域都将使按钮可点击。
此外,在此 Container 之上添加 GestureDetector 使我们能够捕获此 Container 内的任何点击。
所以最后这就是当你点击时会发生什么,如果你点击:
- 在青色Container之外,没有任何反应。
- 青色容器内
- 在按钮外部,GestureController 捕捉点击并使按钮移动
- 在按钮内部,Button 捕捉点击,不对其执行任何操作(空方法),并将此点击标记为已处理这会导致它不会在树中冒泡因此 GestureController 什么也得不到,什么也没有发生。
希望这可以帮助您和其他人理解所有这些工作的棘手方式。一旦你拥抱它,它就会变得很美 ;)
尽管我做了上面所说的事情,但它对我不起作用。所以我调试了几个小时,找到了解决方案。我希望它对某人有所帮助。
如果您的父窗口小部件是 Column/Row/Wrap 并且如果您将窗口小部件转换到另一个窗口小部件的顶部,出于某种原因手势检测器将不起作用。因此,您需要删除 Column/Row/Wrap 小部件才能使其正常工作。
this blue button isn't clickable on red area, bottom side clickable
示例代码:
SingleChildScrollView(
controller: _scrollViewController,
child: Column(children: [
Container(
height: 500,
color: Colors.red,
),
Wrap(
children: [
FractionalTranslation(
translation: Offset(0.0, -0.5),
child: FlatButton(
child: Container(
color: Colors.blue,
height: 100,
),
onPressed: () {
print("INGA");
},
)),
],
),])
移除 Wrap 小部件后,按钮再次变为完全可点击。
我在使用 ScrollView
和 Transform
时遇到了一些事件处理问题。布局结构是这样的,ScrollView
和Transform
存在于Stack
.
我想让ScrollView
在Container(Colors.cyan)
中滚动到FlatButton
外时滚动,事件可以穿透到ScrollView。
点击FlatButton
onPress to work。实际上,点击FlatButton
两次后,无论点击初始位置还是当前位置,都不再移动。 FlatButton
控件在尺寸范围内离开初始位置,不再检测到点击事件,但我没看懂。代码如下:
class EventListener extends StatefulWidget {
@override
_EventListenerState createState() => _EventListenerState();
}
class _EventListenerState extends State<EventListener> {
Offset offset = Offset(0, 0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventListener"),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.teal,
height: 300,
),
Container(
color: Colors.orange,
height: 400,
)
],
),
),
Container(
color: Colors.cyan,
width: double.infinity,
height: 400,
alignment: Alignment.center,
child: SizedBox(
width: 100,
height: 100,
child: Transform.translate(
offset: offset,
child: FlatButton(
color: Colors.orange,
onPressed: () {
setState(() {
offset += Offset(50, 50);
});
print('click !');
},
child: Text("translate"),
),
),
),
)
],
),
);
}
}
这是 Buttons and Stacks 的一个已知问题,我建议遇到此类问题的任何人查看 this discussion on Github。
TL;DR:
翻译小部件时,您可以点击的区域由两部分组成:
- 父控件的面积
- 子区域(这里的Flatbutton)
见下图:
通常的解决方法:
正在扩展父级的大小。
这给了我们这样的东西:
Container(
width: double.infinity,
height: 400,
child: Transform.translate(
offset: offset,
child: SizedBox(
width: 100,
height: 100,
child: FlatButton(
onPressed: () => print('tap button'),
child: Text("translate"),
),
),
),
),
在这里您可以点击父容器中的任意位置。
为您解决
您实际上想要一些不同的东西:除了按钮之外的任何东西都是可点击的。为此你需要:
- GestureDetector 是可点击区域的父级
- 带有不执行任何操作的 onPressed 方法的 FlatButton
如果我们只希望蓝色容器可点击,那么这是最终代码:
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(
home: EventListener(),
));
class EventListener extends StatefulWidget {
@override
_EventListenerState createState() => _EventListenerState();
}
class _EventListenerState extends State<EventListener> {
Offset offset = Offset(0, 0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventListener"),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.teal,
height: 300,
),
Container(
color: Colors.orange,
height: 400,
)
],
),
),
GestureDetector(
onTap: () {
setState(() {
offset += Offset(50, 50);
});
},
child: Container(
width: double.infinity,
height: 400,
color: Colors.cyan,
alignment: Alignment.center,
child: Transform.translate(
offset: offset,
child: SizedBox(
width: 100,
height: 100,
child: FlatButton(
color: Colors.orange,
onPressed: () {},
child: Text("translate"),
),
),
),
),
)
],
),
);
}
}
为什么这有效
如前所述,父容器是青色容器,此容器中的任何区域都将使按钮可点击。
此外,在此 Container 之上添加 GestureDetector 使我们能够捕获此 Container 内的任何点击。
所以最后这就是当你点击时会发生什么,如果你点击:
- 在青色Container之外,没有任何反应。
- 青色容器内
- 在按钮外部,GestureController 捕捉点击并使按钮移动
- 在按钮内部,Button 捕捉点击,不对其执行任何操作(空方法),并将此点击标记为已处理这会导致它不会在树中冒泡因此 GestureController 什么也得不到,什么也没有发生。
希望这可以帮助您和其他人理解所有这些工作的棘手方式。一旦你拥抱它,它就会变得很美 ;)
尽管我做了上面所说的事情,但它对我不起作用。所以我调试了几个小时,找到了解决方案。我希望它对某人有所帮助。
如果您的父窗口小部件是 Column/Row/Wrap 并且如果您将窗口小部件转换到另一个窗口小部件的顶部,出于某种原因手势检测器将不起作用。因此,您需要删除 Column/Row/Wrap 小部件才能使其正常工作。
this blue button isn't clickable on red area, bottom side clickable
示例代码:
SingleChildScrollView(
controller: _scrollViewController,
child: Column(children: [
Container(
height: 500,
color: Colors.red,
),
Wrap(
children: [
FractionalTranslation(
translation: Offset(0.0, -0.5),
child: FlatButton(
child: Container(
color: Colors.blue,
height: 100,
),
onPressed: () {
print("INGA");
},
)),
],
),])
移除 Wrap 小部件后,按钮再次变为完全可点击。