Flutter 如何为共享相同状态类的两个小部件使用两个全局键
我正在尝试创建我自己的自定义部分在颤振。该部分有两个按钮,一个用于教师,另一个用于学生。我想做的是,它将按钮封装在一个有状态的小部件中,以处理两个按钮的设置状态,因为我希望按钮是一个动画容器,如果我从父级重建子级(按钮),转换将不起作用 请注意,按钮是堆栈定位的,我对内容进行了重新排序,以使点击的按钮超过另一个按钮(这将在我在点击的按钮中设置更多宽度时生效,现在还没有创建) 这是我的密码:Flutter 如何为共享相同状态类的两个小部件使用两个全局键,flutter,dart,statefulwidget,Flutter,Dart,Statefulwidget,我正在尝试创建我自己的自定义部分在颤振。该部分有两个按钮,一个用于教师,另一个用于学生。我想做的是,它将按钮封装在一个有状态的小部件中,以处理两个按钮的设置状态,因为我希望按钮是一个动画容器,如果我从父级重建子级(按钮),转换将不起作用 请注意,按钮是堆栈定位的,我对内容进行了重新排序,以使点击的按钮超过另一个按钮(这将在我在点击的按钮中设置更多宽度时生效,现在还没有创建) 这是我的密码: import 'package:flutter/cupertino.dart'; import '../
import 'package:flutter/cupertino.dart';
import '../../app_localizations.dart';
import '../../styles.dart';
GlobalKey<_ButtonState> teachersButtonKey = GlobalKey();
GlobalKey<_ButtonState> studentsButtonKey = GlobalKey();
String _globalTappedButtonId = 'teachersButton';
class FiltersAppBarSegment extends StatefulWidget {
@override
_FiltersAppBarSegmentState createState() => _FiltersAppBarSegmentState();
}
class _FiltersAppBarSegmentState extends State<FiltersAppBarSegment> {
List<Widget> buildStackChildren(SegmentChangedCallBack handleSegmentChanged) {
if (_globalTappedButtonId == 'teachersButton') {
return <Widget>[
Container(
key: UniqueKey(),
child: _Button(
key: studentsButtonKey,
id: 'studentsButton',
label: 'seeStudents',
rightPosition: 1,
onSegmentChanged: handleSegmentChanged,
),
),
Container(
key: UniqueKey(),
child: _Button(
key: teachersButtonKey,
id: 'teachersButton',
label: 'amTeacher',
rightPosition: null,
onSegmentChanged: handleSegmentChanged,
),
),
];
} else {
return <Widget>[
Container(
key: UniqueKey(),
child: _Button(
key: driverButtonKey,
id: 'driverButton',
label: 'amDriver',
rightPosition: null,
onSegmentChanged: handleSegmentChanged,
),
),
Container(
key: UniqueKey(),
child: _Button(
key: studentsButtonKey,
id: 'studentButton',
label: 'amStudent',
rightPosition: 1,
onSegmentChanged: handleSegmentChanged,
),
),
];
}
}
void handleSegmentChanged(String clickedButtonId) {
teachersButtonKey.currentState._handleButtonTapped();
studentsButtonKey.currentState._handleButtonTapped();
}
@override
Widget build(BuildContext context) {
return Container(
height: 42,
padding: EdgeInsets.symmetric(horizontal: 20),
child: Stack(children: buildStackChildren(handleSegmentChanged)),
);
}
}
class _Button extends StatefulWidget {
final String id;
final String label;
final double rightPosition;
final void onSegmentChanged;
_Button({
Key key,
this.id,
this.label,
this.rightPosition,
this.onSegmentChanged,
}) : super(key: key);
@override
_ButtonState createState() => _ButtonState();
}
class _ButtonState extends State<_Button> {
bool _tapped;
double _topPosition;
double _width;
double _height;
double _getTopPosition() => _tapped ? 0 : 5;
double _getHeight() => _tapped ? 42 : 32;
Gradient _getGradient() {
if (_tapped) {
return Styles.darkAccentColorGradient;
} else {
return Styles.darkAccentColorGradientDisabled;
}
}
void _handleButtonTapped() {
setState(() {
_globalTappedButtonId = widget.id;
_tapped = (widget.id == _globalTappedButtonId);
_topPosition = _getTopPosition();
_height = _getHeight();
});
}
@override
void initState() {
super.initState();
_tapped = (widget.id == _globalTappedButtonId);
_topPosition = _getTopPosition();
_height = _getHeight();
}
@override
Widget build(BuildContext context) {
return Positioned(
top: _topPosition,
right: widget.rightPosition,
child: GestureDetector(
onTap: () {
widget.onSegmentChanged('test');
},
child: AnimatedContainer(
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
width: _width,
height: _height,
decoration: BoxDecoration(
gradient: _getGradient(),
borderRadius: BorderRadius.circular(13),
),
child: Center(
child: Text(
AppLocalizations.of(context).translate(widget.label),
style: Styles.bodyWhiteText,
textAlign: TextAlign.center,
),
),
),
),
);
}
}
import'包装:flift/cupertino.dart';
导入“../app_localizations.dart”;
导入“../styles.dart”;
GlobalKey教师按钮键=GlobalKey();
GlobalKey studentsButtonKey=GlobalKey();
字符串_globalTappedButtonId='teachersButton';
类过滤器AppBarSegment扩展StatefulWidget{
@凌驾
_FiltersAppBarSegmentState createState()=>\u FiltersAppBarSegmentState();
}
类_过滤器AppBarSegmentState扩展状态{
列表buildStackChildren(分段更改回调句柄分段更改){
如果(_globalTappedButtonId=='teachersButton'){
返回[
容器(
键:UniqueKey(),
孩子:_按钮(
键:学生按钮键,
id:“学生按钮”,
标签:“SeeSeestudents”,
正确位置:1,
onSegmentChanged:handleSegmentChanged,
),
),
容器(
键:UniqueKey(),
孩子:_按钮(
键:教师按钮键,
id:“教师按钮”,
标签:“amTeacher”,
rightPosition:null,
onSegmentChanged:handleSegmentChanged,
),
),
];
}否则{
返回[
容器(
键:UniqueKey(),
孩子:_按钮(
钥匙:驾驶员按钮钥匙,
id:'驾驶员按钮',
标签:“amDriver”,
rightPosition:null,
onSegmentChanged:handleSegmentChanged,
),
),
容器(
键:UniqueKey(),
孩子:_按钮(
键:学生按钮键,
id:'学生按钮',
标签:“amStudent”,
正确位置:1,
onSegmentChanged:handleSegmentChanged,
),
),
];
}
}
无效handleSegmentChanged(字符串clickedButtonId){
teachersButtonKey.currentState._handleButtonTapped();
studentsButtonKey.currentState._handleButtonTapped();
}
@凌驾
小部件构建(构建上下文){
返回容器(
身高:42,
填充:边缘组。对称(水平:20),
子:堆栈(子:buildStackChildren(handleSegmentChanged)),
);
}
}
类_按钮扩展StatefulWidget{
最终字符串id;
最终字符串标签;
最终双右位;
分段变更的最终无效;
_钮扣({
关键点,
这个身份证,
这个标签,
这是正确的立场,,
这个.onSegmentChanged,
}):super(key:key);
@凌驾
_ButtonState createState()=>\u ButtonState();
}
类_ButtonState扩展状态{
布尔!;
双顶位;
双倍宽度;
双倍高度;
双击0:5;
双_getHeight()=>_分接?42:32;
梯度_getGradient(){
如果(点击){
返回Styles.darkAccentColorGradient;
}否则{
返回Styles.darkAccentColorGradientDisabled;
}
}
void(车把钮扣){
设置状态(){
_globalTappedButtonId=widget.id;
_点击=(widget.id=_globalTappedButtonId);
_topPosition=_get反对派();
_高度=_getHeight();
});
}
@凌驾
void initState(){
super.initState();
_点击=(widget.id=_globalTappedButtonId);
_topPosition=_get反对派();
_高度=_getHeight();
}
@凌驾
小部件构建(构建上下文){
返回定位(
顶部:_顶部位置,
右:widget.rightPosition,
儿童:手势检测器(
onTap:(){
widget.onSegmentChanged('test');
},
子:动画容器(
持续时间:持续时间(秒数:1),
曲线:Curves.FastOutSwowin,
宽度:_宽度,
高度:_高度,
装饰:盒子装饰(
渐变:_getGradient(),
边界半径:边界半径。圆形(13),
),
儿童:中心(
子:文本(
AppLocalizations.of(context.translate)(widget.label),
样式:Styles.bodyWhiteText,
textAlign:textAlign.center,
),
),
),
),
);
}
}
我确信您现在已经找到了问题的解决方案,但当查看此错误时,此问题是第一个搜索结果之一
如您所知,根据GlobalKey上的
“不能在树中同时包含两个具有
相同的全局键。尝试这样做将在运行时断言。“
您可以定义自己的单个关键点,如:
import'package:flatter/widgets.dart';
类测试键{
静态最终测试键1=常量键(“测试键1”);
静态最终测试键2=常量键(“测试键2”);
...
}
然后在小部件中使用key:TestKeys.testKey1
这是在中描述的,因此可能它可以帮助需要类似用例的人
也列出了一些解决方案,但您如何才能掌握当前状态?键没有currentState属性