根据延迟在两个小部件之间切换
Switch between two widgets depending on a delay
我有一个状态变量a
。如果变量 a
是 100.0
,我想显示小部件 A
。如果变量 a
不同,那么我想显示小部件 B
.
这很简单,看起来像这样:
child: aOrB(a), // somewhere in the top-level Scaffold
...
Widget aOrB(double a) {
if (a == 100.0) {
return A;
} else {
return B;
}
}
但问题是:如果变量 a
更改为 100.0
,我想先显示小部件 B
,然后在延迟一段时间后切换到小部件 A
.
还有一个问题:如果用户点击小部件 A
,我想显示小部件 B
一段时间,然后在延迟一段时间后再次显示小部件 A
。
条件加起来就是table:
|---------------------|------------------|
| a == 100.0 | A |
|---------------------|------------------|
| a != 100.0 | B |
|---------------------|------------------|
| a == 100.0; t < 5 s | B |
| A.onTap; t < 5 s | |
|---------------------|------------------|
我已经尝试过 Future.delayed、计时器和可见性小部件,但没有成功。
这是我理解的例子!
它适用于 a == 100、a != 00 和时间延迟。
根据您的要求修改它!
double a = 100;
Widget focusedWidget;
@override
void initState() {
super.initState();
//if you want to predefine a initial widget call the initWidget method !
//or call the changeWidget for instant output
changeWidget(a);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Let\'s parse some JSON'),
),
body: Container(
padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
child: focusedWidget,
));
}
void initWidget(flag) {
if (flag == 100) {
setState(() {
focusedWidget = Card(
color: Colors.green,
child: ListTile(
onTap: () {
changeWidget(50);
//or some value
},
title: Text('Widget A',
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center)),
);
});
} else {
setState(() {
focusedWidget = Card(
color: Colors.red,
child: ListTile(
onTap: () {
changeWidget(100);
},
title: Text('Widget B',
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center)),
);
});
}
}
void changeWidget(flag) {
if (flag == 100) {
setState(() {
focusedWidget = Card(
color: Colors.red,
child: ListTile(
onTap: () {
changeWidget(100);
//or some value
},
title: Text('Widget B',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
),
);
});
Future.delayed(Duration(seconds: 5), () {
setState(() {
focusedWidget = Card(
color: Colors.green,
child: ListTile(
onTap: () {
changeWidget(50);
},
title: Text('Widget A',
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
),
);
});
});
} else {
setState(() {
focusedWidget = Card(
color: Colors.red,
child: ListTile(
onTap: () {
changeWidget(100);
},
title: Text('Widget B',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
),
);
});
}
}
最后,以下对我有用。 Future.delayed 很好,但是当 Future 连续调用几次时,它不能被取消。这样,用户可以在几秒钟内 运行 多个 5 秒延迟的 Futures(通过 onTap,或通过更改 a
的值,或通过 运行ning setState 过于频繁)。这使得 onTap 完全无法使用,因为 运行ning Futures 击败了 onTaps 并隐藏了小部件 B
而不管用户的操作如何。这使得@Naveen Avidi 的回答在现实中不太有用。
所以你需要一个计时器来做到这一点。你需要 运行 它在后台异步。我发现,唯一可以在后台 运行 计时器的地方是 build()
方法中的 return 之前。每次重绘app时都会调用这里的代码,所以你可以检查一下,如果a
真的改变了,如果你真的想要运行一个Timer,取消之前的Timer并运行一个新的一.
监听 a
中 setState 变化的最简单方法是复制 a
的值并在每次重绘应用程序时进行比较。代码中完全相同的地方。
double previousA;
bool showB;
Timer bTimer;
...
@override
Widget build(BuildContext context) {
if (previousA != a) {
if (a == 100.0) {
showB = true;
bTimer?.cancel();
bTimer = Timer(Duration(seconds: 5), () {
setState(() => showB = false);
});
} else {
showB = true;
}
previousA = a;
}
return Scaffold(
...
child: aOrB(showB),
...
aOrB(showB){
if (showB == true) {
} else {
}
}
如果您还想在代码中的某处设置 showB,无论 a
是否更改,您也可以复制 showB 并监听其更改:
if (previousShowB != showB) {
if (showB == true) {
bTimer?.cancel();
bTimer = Timer(Duration(seconds: 5), () {
setState(() => showB = false);
});
}
}
...
setState(() => showB = true);
我有一个状态变量a
。如果变量 a
是 100.0
,我想显示小部件 A
。如果变量 a
不同,那么我想显示小部件 B
.
这很简单,看起来像这样:
child: aOrB(a), // somewhere in the top-level Scaffold
...
Widget aOrB(double a) {
if (a == 100.0) {
return A;
} else {
return B;
}
}
但问题是:如果变量 a
更改为 100.0
,我想先显示小部件 B
,然后在延迟一段时间后切换到小部件 A
.
还有一个问题:如果用户点击小部件 A
,我想显示小部件 B
一段时间,然后在延迟一段时间后再次显示小部件 A
。
条件加起来就是table:
|---------------------|------------------|
| a == 100.0 | A |
|---------------------|------------------|
| a != 100.0 | B |
|---------------------|------------------|
| a == 100.0; t < 5 s | B |
| A.onTap; t < 5 s | |
|---------------------|------------------|
我已经尝试过 Future.delayed、计时器和可见性小部件,但没有成功。
这是我理解的例子! 它适用于 a == 100、a != 00 和时间延迟。 根据您的要求修改它!
double a = 100;
Widget focusedWidget;
@override
void initState() {
super.initState();
//if you want to predefine a initial widget call the initWidget method !
//or call the changeWidget for instant output
changeWidget(a);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Let\'s parse some JSON'),
),
body: Container(
padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
child: focusedWidget,
));
}
void initWidget(flag) {
if (flag == 100) {
setState(() {
focusedWidget = Card(
color: Colors.green,
child: ListTile(
onTap: () {
changeWidget(50);
//or some value
},
title: Text('Widget A',
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center)),
);
});
} else {
setState(() {
focusedWidget = Card(
color: Colors.red,
child: ListTile(
onTap: () {
changeWidget(100);
},
title: Text('Widget B',
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center)),
);
});
}
}
void changeWidget(flag) {
if (flag == 100) {
setState(() {
focusedWidget = Card(
color: Colors.red,
child: ListTile(
onTap: () {
changeWidget(100);
//or some value
},
title: Text('Widget B',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
),
);
});
Future.delayed(Duration(seconds: 5), () {
setState(() {
focusedWidget = Card(
color: Colors.green,
child: ListTile(
onTap: () {
changeWidget(50);
},
title: Text('Widget A',
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
),
);
});
});
} else {
setState(() {
focusedWidget = Card(
color: Colors.red,
child: ListTile(
onTap: () {
changeWidget(100);
},
title: Text('Widget B',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
),
);
});
}
}
最后,以下对我有用。 Future.delayed 很好,但是当 Future 连续调用几次时,它不能被取消。这样,用户可以在几秒钟内 运行 多个 5 秒延迟的 Futures(通过 onTap,或通过更改 a
的值,或通过 运行ning setState 过于频繁)。这使得 onTap 完全无法使用,因为 运行ning Futures 击败了 onTaps 并隐藏了小部件 B
而不管用户的操作如何。这使得@Naveen Avidi 的回答在现实中不太有用。
所以你需要一个计时器来做到这一点。你需要 运行 它在后台异步。我发现,唯一可以在后台 运行 计时器的地方是 build()
方法中的 return 之前。每次重绘app时都会调用这里的代码,所以你可以检查一下,如果a
真的改变了,如果你真的想要运行一个Timer,取消之前的Timer并运行一个新的一.
监听 a
中 setState 变化的最简单方法是复制 a
的值并在每次重绘应用程序时进行比较。代码中完全相同的地方。
double previousA;
bool showB;
Timer bTimer;
...
@override
Widget build(BuildContext context) {
if (previousA != a) {
if (a == 100.0) {
showB = true;
bTimer?.cancel();
bTimer = Timer(Duration(seconds: 5), () {
setState(() => showB = false);
});
} else {
showB = true;
}
previousA = a;
}
return Scaffold(
...
child: aOrB(showB),
...
aOrB(showB){
if (showB == true) {
} else {
}
}
如果您还想在代码中的某处设置 showB,无论 a
是否更改,您也可以复制 showB 并监听其更改:
if (previousShowB != showB) {
if (showB == true) {
bTimer?.cancel();
bTimer = Timer(Duration(seconds: 5), () {
setState(() => showB = false);
});
}
}
...
setState(() => showB = true);