尝试保持抽屉处于活动状态(打开/关闭抽屉时不要重建):
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
drawer: const AutomaticKeepAlive(
child: Drawer(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
return const Column(
children: [
Text('Input Name:'),
SizedBox(
width: 50,
height: 30,
child: TextField(),
),
],
);
}
}
运行时错误:
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget KeepAlive(keepAlive: false) wants to apply ParentData of type KeepAliveParentDataMixin to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
Usually, this means that the KeepAlive widget has the wrong ancestor RenderObjectWidget. Typically, KeepAlive widgets are placed directly inside SliverWithKeepAliveWidget or TwoDimensionalViewport widgets.
The offending KeepAlive is currently placed inside a Semantics widget.
The ownership chain for the RenderObject that received the incompatible parent data was:
Semantics ← Drawer ← NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← _FocusInheritedScope ← Semantics ← FocusScope-[GlobalKey#b1269] ← RepaintBoundary ← Align ← ⋯
当您关闭抽屉时,AutomaticKeepAlive 也会与其所有子项一起被处置。
要保留抽屉小部件,您将需要一个全局键,并且需要将抽屉对象移动到隐藏在小部件树中的某个位置,以便抽屉不会被释放。
这是示例代码。
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey drawerKey = GlobalKey();
bool isDrawerOpened = false;
Widget get drawer => Drawer(
key: drawerKey,
child: const MyWidget(),
);
@override
Widget build(BuildContext context) {
return Stack(
children: [
Visibility(
visible: !isDrawerOpened,
child: drawer,
),
Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
onDrawerChanged: (isOpened) {
Future.delayed(Duration.zero, () {
isDrawerOpened = isOpened;
setState(() {});
});
},
drawer: isDrawerOpened ? drawer : const Drawer(),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {});
},
child: const Icon(Icons.add),
),
),
],
);
}
}
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return const Column(
children: [
Text('Input Name:'),
SizedBox(
width: 50,
height: 30,
child: TextField(),
),
],
);
}
}