SnackBar重叠FAB(基础)
要使 SnackBar 重叠在 FAB 上,FAB 应该放置在嵌套的 Scaffold 上。
class BasicOverlapFAB extends StatelessWidget {
const BasicOverlapFAB();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Basic Overlap'),
),
body: Scaffold(
body: Center(child: Text('SnackBar will overlap FAB'),),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.keyboard_double_arrow_down),
onPressed: () => ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('This overlaps the FAB'),)
),
),
)
);
}
}
这是因为 SnackBar 显示在最接近 ScaffoldMessenger 的最高层级 Scaffold 上。默认情况下,最近的 ScaffoldMessenger 包含在 MaterialApp 中。
在上面的代码中,显示 SnackBar 的 Scaffold 是父级/高于带有 FAB 的 Scaffold,因此 Snack 会覆盖 FAB。
MaterialApp
ScaffoldMessenger
Scaffold ← Snacks here
Scaffold
FAB
嵌套的Scaffolds
和ScaffoldMessengers
这个例子有几个嵌套的 Scaffolds。
Scaffolds 就像玻璃窗格一样。我们可以将一个窗格叠加在另一个上面。我们可以在每个窗格上显示 FABs、SnackBars 和其他小部件。
为了更容易看到 Scaffolds 的层次,每个 Scaffold 都较小,并用不同的颜色轮廓线标出:蓝色、绿色、红色。红色是最下面的。(嵌套的窗格在下面。)
Scaffolds
默认不提供 ScaffoldMessenger
,但 MaterialApp
提供了默认的 ScaffoldMessenger
。大多数情况下,我们与这个默认的“根”ScaffoldMessenger
交互,但我们也可以添加自己的。
在这个例子中,对于每个 Scaffold 层(AnotherScaffold
自定义类),我们手动添加了它自己的 ScaffoldMessenger
。每个层还有一个 FAB,在其自己的 ScaffoldMessenger
上显示 SnackBars。
在模拟器中复制/粘贴并尝试操作,以了解 Scaffolds/ScaffoldMessengers 如何形成层次结构,如何重叠和相互作用。
class NestedScaffoldsPage extends StatelessWidget {
const NestedScaffoldsPage();
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.blue)
),
child: Scaffold(
appBar: AppBar(
title: Text('Nested Scaffolds'),
),
body: AnotherScaffold(
level: 1,
color: Colors.green,
body: AnotherScaffold(
level: 2,
color: Colors.red,
body: Center(child: Text('3 Total Scaffolds')),
),
),
floatingActionButton: FloatingActionButton(
child: Text('0'),
onPressed: () => ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Snack level 0'),
duration: const Duration(seconds: 2),
)
),
),
),
);
}
}
class AnotherScaffold extends StatelessWidget {
final int level;
final Widget body;
final Color color;
final GlobalKey<ScaffoldMessengerState> smState;
AnotherScaffold({
required this.level,
required this.color,
required this.body,
}) : smState = GlobalKey<ScaffoldMessengerState>();
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
key: smState,
child: Container(
margin: EdgeInsets.all(5),
decoration: BoxDecoration(
border: Border.all(color: color),
),
child: Scaffold(
body: body,
floatingActionButton: Padding(
padding: EdgeInsets.only(right: (level) * 40),
child: FloatingActionButton(
heroTag: GlobalKey(),
backgroundColor: color,
child: Text('$level'),
onPressed: () =>
smState.currentState!.showSnackBar(SnackBar(
duration: Duration(milliseconds: 2500),
content: Text('Snack level $level'),
)),
),
),
),
),
);
}
}
SnackBar
小部件无法直接实现。您可能需要创建自己的自定义小部件,然后将其包装在Stack
中。 此外,根据 Google 官方的Material Design Guidelines,不建议使用重叠的SnackBar
。 - thedarthcoder