将密钥传递给 child 时无法正常工作 |扑
Key doesn't work properly when passing it on to child | Flutter
所以我的脚手架中有一把脚手架钥匙:
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
在我的脚手架中,我有一个自定义抽屉和一个自定义应用栏:
Scaffold(
key: _scaffoldKey,
backgroundColor: Color(0xFF3FC1C9),
drawer: HomeDrawer(),
body: StartAppBar(_scaffoldKey.currentState?.openDrawer),
),
我将打开抽屉功能传递给自定义AppBar。我的自定义 AppBar 接受这样的功能:
class StartAppBar extends StatelessWidget {
void Function()? openDrawer;
StartAppBar(this.openDrawer);
and references it here:
leading: IconButton(
onPressed: () {
openDrawer!();
// _key.currentState!.openEndDrawer();
},
icon: Icon(
Icons.view_headline_rounded,
),
),
问题是抽屉从一开始就打不开。当我通过点击我的底部栏(下面的代码)切换我的屏幕主体时,抽屉打开。我猜我的钥匙在我第一次加载应用程序时有一个空值,因此抽屉没有打开。如果是这种情况,我需要为键设置一个默认值。完整代码如下。
这是完整的代码,也许它比简化的代码更相关:
我创建密钥的 class 如下所示:
class HomeScreen extends StatefulWidget {
final marken;
const HomeScreen({Key? key, this.marken}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late List<Widget> _widgetOptions;
@override
initState() {
_widgetOptions = <Widget>[
Favorites(),
BodyHomeScreen(
marken: widget.marken,
),
Kontakt(),
];
}
DateTime? lastPressed;
final HideNavbar hiding = HideNavbar();
int _selectedIndex = 1;
void _onItemTap(int index) {
setState(() {
_selectedIndex = index;
});
}
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Scaffold(
key: _scaffoldKey,
backgroundColor: Color(0xFF3FC1C9),
drawer: HomeDrawer(),
body: StartAppBar(_selectedIndex, hiding, lastPressed, _widgetOptions,
_scaffoldKey.currentState?.openDrawer),
bottomNavigationBar: BottomBar(
_onItemTap,
_selectedIndex,
hiding,
),
),
);
}
}
如上所示,我将密钥传递给 StartAppBar,如下所示:
import 'package:flutter/material.dart';
class StartAppBar extends StatelessWidget {
final int selectedIndex;
final hiding;
List<Widget> widgetOptions;
var lastPressed;
void Function()? openDrawer;
StartAppBar(this.selectedIndex, this.hiding, this.lastPressed,
this.widgetOptions, this.openDrawer);
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final now = DateTime.now();
final maxDuration = Duration(seconds: 2);
final isWarning =
lastPressed == null || now.difference(lastPressed!) > maxDuration;
if (isWarning) {
lastPressed = DateTime.now();
final snackBar = SnackBar(
content: Container(
//color: Colors.white,
decoration: BoxDecoration(
color: Color(0xFF03DAC6),
borderRadius: BorderRadius.circular(20)),
margin: EdgeInsets.fromLTRB(0, 0, 0, 20),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Doppelklick zum verlassen',
textAlign: TextAlign.center,
),
),
),
backgroundColor: Colors.transparent,
elevation: 1000,
behavior: SnackBarBehavior.floating,
duration: maxDuration,
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(snackBar);
return false;
} else {
return true;
}
},
child: CustomScrollView(
controller: hiding.controller,
slivers: [
SliverAppBar(
backgroundColor: Color(0xFF3FC1C9),
automaticallyImplyLeading: false,
elevation: 0,
title: Text(
"AutoLab",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
leading: IconButton(
onPressed: () {
openDrawer?.call();
// _key.currentState!.openEndDrawer();
},
icon: Icon(
Icons.view_headline_rounded,
),
),
centerTitle: true,
expandedHeight: 120,
floating: false,
flexibleSpace: FlexibleSpaceBar(
title: selectedIndex == 1
? Text("Marke auswählen")
: selectedIndex == 2
? Text("Schreibe uns!")
: Text("Deine Modelle"),
centerTitle: true,
),
),
SliverToBoxAdapter(child: widgetOptions.elementAt(selectedIndex)),
],
),
);
}
}
有什么办法可以解决这个问题吗?
您不必创建一个GlobalKey,您只需这样写:
onPressed: () {
Scaffold.of(context).openDrawer();
},
因为在你的widget树中,你已经只有一个Scaffold,所以你不需要用key让它唯一,所以你的IconButton知道打开哪个Scaffold和Drawer。
现在剩下的就是删除 void Function()?打开抽屉;
所以我的脚手架中有一把脚手架钥匙:
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
在我的脚手架中,我有一个自定义抽屉和一个自定义应用栏:
Scaffold(
key: _scaffoldKey,
backgroundColor: Color(0xFF3FC1C9),
drawer: HomeDrawer(),
body: StartAppBar(_scaffoldKey.currentState?.openDrawer),
),
我将打开抽屉功能传递给自定义AppBar。我的自定义 AppBar 接受这样的功能:
class StartAppBar extends StatelessWidget {
void Function()? openDrawer;
StartAppBar(this.openDrawer);
and references it here:
leading: IconButton(
onPressed: () {
openDrawer!();
// _key.currentState!.openEndDrawer();
},
icon: Icon(
Icons.view_headline_rounded,
),
),
问题是抽屉从一开始就打不开。当我通过点击我的底部栏(下面的代码)切换我的屏幕主体时,抽屉打开。我猜我的钥匙在我第一次加载应用程序时有一个空值,因此抽屉没有打开。如果是这种情况,我需要为键设置一个默认值。完整代码如下。
这是完整的代码,也许它比简化的代码更相关:
我创建密钥的 class 如下所示:
class HomeScreen extends StatefulWidget {
final marken;
const HomeScreen({Key? key, this.marken}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late List<Widget> _widgetOptions;
@override
initState() {
_widgetOptions = <Widget>[
Favorites(),
BodyHomeScreen(
marken: widget.marken,
),
Kontakt(),
];
}
DateTime? lastPressed;
final HideNavbar hiding = HideNavbar();
int _selectedIndex = 1;
void _onItemTap(int index) {
setState(() {
_selectedIndex = index;
});
}
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Scaffold(
key: _scaffoldKey,
backgroundColor: Color(0xFF3FC1C9),
drawer: HomeDrawer(),
body: StartAppBar(_selectedIndex, hiding, lastPressed, _widgetOptions,
_scaffoldKey.currentState?.openDrawer),
bottomNavigationBar: BottomBar(
_onItemTap,
_selectedIndex,
hiding,
),
),
);
}
}
如上所示,我将密钥传递给 StartAppBar,如下所示:
import 'package:flutter/material.dart';
class StartAppBar extends StatelessWidget {
final int selectedIndex;
final hiding;
List<Widget> widgetOptions;
var lastPressed;
void Function()? openDrawer;
StartAppBar(this.selectedIndex, this.hiding, this.lastPressed,
this.widgetOptions, this.openDrawer);
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final now = DateTime.now();
final maxDuration = Duration(seconds: 2);
final isWarning =
lastPressed == null || now.difference(lastPressed!) > maxDuration;
if (isWarning) {
lastPressed = DateTime.now();
final snackBar = SnackBar(
content: Container(
//color: Colors.white,
decoration: BoxDecoration(
color: Color(0xFF03DAC6),
borderRadius: BorderRadius.circular(20)),
margin: EdgeInsets.fromLTRB(0, 0, 0, 20),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Doppelklick zum verlassen',
textAlign: TextAlign.center,
),
),
),
backgroundColor: Colors.transparent,
elevation: 1000,
behavior: SnackBarBehavior.floating,
duration: maxDuration,
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(snackBar);
return false;
} else {
return true;
}
},
child: CustomScrollView(
controller: hiding.controller,
slivers: [
SliverAppBar(
backgroundColor: Color(0xFF3FC1C9),
automaticallyImplyLeading: false,
elevation: 0,
title: Text(
"AutoLab",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
leading: IconButton(
onPressed: () {
openDrawer?.call();
// _key.currentState!.openEndDrawer();
},
icon: Icon(
Icons.view_headline_rounded,
),
),
centerTitle: true,
expandedHeight: 120,
floating: false,
flexibleSpace: FlexibleSpaceBar(
title: selectedIndex == 1
? Text("Marke auswählen")
: selectedIndex == 2
? Text("Schreibe uns!")
: Text("Deine Modelle"),
centerTitle: true,
),
),
SliverToBoxAdapter(child: widgetOptions.elementAt(selectedIndex)),
],
),
);
}
}
有什么办法可以解决这个问题吗?
您不必创建一个GlobalKey,您只需这样写:
onPressed: () {
Scaffold.of(context).openDrawer();
},
因为在你的widget树中,你已经只有一个Scaffold,所以你不需要用key让它唯一,所以你的IconButton知道打开哪个Scaffold和Drawer。
现在剩下的就是删除 void Function()?打开抽屉;