Flutter:如何以编程方式打开Drawer

z2acfund  于 2023-01-18  发布在  Flutter
关注(0)|答案(8)|浏览(205)

我想以编程方式打开Drawer,而不是通过滑动,如何禁用滑动功能(抽屉的触摸功能)

6kkfgxo0

6kkfgxo01#

空安全代码

  • 使用GlobalKey
final GlobalKey<ScaffoldState> _key = GlobalKey(); // Create a key

@override
Widget build(BuildContext context) {
  return Scaffold(
    key: _key, // Assign the key to Scaffold.
    drawer: Drawer(),
    floatingActionButton: FloatingActionButton(
      onPressed: () => _key.currentState!.openDrawer(), // <-- Opens drawer
    ),
  );
}
  • 使用Builder
@override
Widget build(BuildContext context) {
  return Scaffold(
    drawer: Drawer(),
    floatingActionButton: Builder(builder: (context) {
      return FloatingActionButton(
        onPressed: () => Scaffold.of(context).openDrawer(), // <-- Opens drawer.
      );
    }),
  );
}

如果要禁用使用拖动手势打开Drawer,可以设置

Scaffold(
  drawerEnableOpenDragGesture: false
  // above code ...
)
nbewdwxp

nbewdwxp2#

1.要禁用幻灯片打开功能,可以将Scaffold上的属性drawerEnableOpenDragGesture设置为false。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        // this to prevent the default sliding behaviour
        drawerEnableOpenDragGesture: false,
        drawer: Drawer(),
        appBar: AppBar(
          leading: Builder(builder: (context) => // Ensure Scaffold is in context
            IconButton(
              icon: Icon(Icons.menu),
              onPressed: () => Scaffold.of(context).openDrawer()
            ),
          ),
        )
      )
    );
  }
}

1.要使用Scaffold.of(context)以编程方式打开抽屉,您必须确保(感谢Krolaw!)在其中进行调用的上下文知道Scaffold。
一个简洁的方法是将按钮 Package 在一个构建器中。我已经编辑了答案,包括了一个最小的完整的工作示例。
Scaffold是一个实现材料设计原则的小部件,因此要知道,要能够调用此方法,您需要import 'package:flutter/material.dart';,并且您的小部件需要有一个MaterialApp作为祖先。
Codepen demo
与许多Flutter一样,还有其他解决方案可以确保Scaffold符合上下文。
错误消息是IMO flutter框架最好的特性之一,请允许我谦虚地建议您始终彻底阅读它们,并探索它们所指向的文档。
例如,如果在正确的上下文之外调用openDrawer,则会收到错误消息的一部分:

使用不包含Scaffold的上下文调用了Scaffold.of()。

从传递给Scaffold.of()的上下文开始,找不到任何Scaffold祖先。当提供的上下文与其构建函数实际创建所查找的Scaffold小部件的上下文来自同一StatefulWidget时,通常会发生这种情况。
有几种方法可以避免这个问题。最简单的方法是使用构建器来获取一个在Scaffold“下面”的上下文。有关这个方法的示例,请参阅Scaffold.of()的文档:https://api.flutter.dev/flutter/material/Scaffold/of.html
一个更有效的解决方案是将构建函数拆分为几个小部件。这引入了一个新的上下文,您可以从中获取Scaffold。在这个解决方案中,您将有一个外部小部件,它创建由新的内部小部件的示例填充的Scaffold,然后在这些内部小部件中,您将使用Scaffold.of()。
一个不太优雅但更方便的解决方案是为Scaffold分配一个GlobalKey,然后使用key.currentState属性获取ScaffoldState,而不是使用Scaffold.of()函数。

roejwanj

roejwanj3#

调用Scaffold.of不起作用,因为上下文不包含Scaffold。上面的一些解决方案忽略了这一点,另一些则使用了GlobalKey。我相信最干净的解决方案是将按钮 Package 在Builder中:

Scaffold(
   drawerEnableOpenDragGesture: false, // Prevent user sliding open
   appBar: AppBar(
      automaticallyImplyLeading: false,
      title: Text("Some Title"),
      actions: [
         Builder(builder: (context) => // Ensure Scaffold is in context
            IconButton(
               icon: Icon(Icons.settings),
               onPressed: () => Scaffold.of(context).openDrawer()
         )),
      ],
   ),
   // TODO ...
)
nlejzf6q

nlejzf6q4#

下面是另一个通过编程方式从汉堡包图标打开抽屉的例子,并且不使用Appbar:-

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  var scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        key: scaffoldKey,
        drawer: new Drawer(
          child: new ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text('Drawer Header'),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              ListTile(
                title: Text('Item 1'),
                onTap: () {
                  //Do some stuff here
                  //Closing programmatically - very less practical use
                  scaffoldKey.currentState.openEndDrawer();
                },
              )
            ],
          ),
        ),
        body: Stack(
          children: <Widget>[
            new Center(
                child: new Column(
              children: <Widget>[],
            )),
            Positioned(
              left: 10,
              top: 20,
              child: IconButton(
                icon: Icon(Icons.menu),
                onPressed: () => scaffoldKey.currentState.openDrawer(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
zwghvu4y

zwghvu4y5#

appBar: AppBar(

      automaticallyImplyLeading: false,
      title: Text(
        "Infilon Technologies",
        style:
            TextStyle(fontFamily: "Poppins", fontWeight: FontWeight.w600),
      ),
      actions: <Widget>[
        IconButton(
          icon: Icon(Icons.menu),
          onPressed: () {
            if (_scaffoldKey.currentState.isEndDrawerOpen) {
              _scaffoldKey.currentState.openDrawer();
            } else {
              _scaffoldKey.currentState.openEndDrawer();
            }
          },
        ),
      ],
    ),
7hiiyaii

7hiiyaii6#

如果在Scaffold中使用endDrawer(从右到左),则应用途:

Scaffold.of(context).openEndDrawer();

如果在Scaffold中使用drawer(从左到右),则应用途:

Scaffold.of(context).openDrawer();
2sbarzqh

2sbarzqh7#

你可以用这个完美的方法来打开抽屉它的工作与零安全模块以上Flutter2.12

class DashBoardScreen extends StatefulWidget {
  final String? screen;
  const DashBoardScreen(this.screen, {super.key});

  @override
  State<DashBoardScreen> createState() => _DashBoardScreenState();
}

class _DashBoardScreenState extends State<DashBoardScreen> {
  DashBoardScreenController controller =
      Get.put(getIt<DashBoardScreenController>());

  @override
  Widget build(BuildContext context) {
    controller.scaffoldKey = GlobalKey<ScaffoldState>();
    return Obx(() => Scaffold(
          key: controller.scaffoldKey,
          onDrawerChanged: (isOpened) {
            if (!isOpened) {
              setState(() {});
            }
          },
          appBar: AppBar(
            title: const Text("Test drawer App"),
            actions: const [
              const Padding(
                  padding: EdgeInsets.only(right: 20),
                  child: Icon(Icons.search))
            ],
            leading: UnconstrainedBox(
              child: GestureDetector(
                onTap: () {
                  controller.scaffoldKey.currentState!.openDrawer();
                },
                child: const AbsorbPointer(
                  absorbing: true,
                  child: SizedBox(
                    height: 50,
                    child: CircleAvatar(
                        backgroundImage: CachedNetworkImageProvider(
                      "https://cdn.pixabay.com/photo/2014/07/09/10/04/man-388104_960_720.jpg",
                    )),
                  ),
                ),
              ),
            ),
          ),
          drawerEdgeDragWidth:
              kIsWeb ? MediaQuery.of(context).size.width * 0.2 : null,
          drawer: Drawer(
              key: controller.scaffoldKey,
              child: ListView(
                children: [
                  DropdownMenuItem(onTap: () {}, child: const Text("Add Anime"))
                ],
              )),
          body: widget.screen == StringVariables.ADD_ANIME
              ? AddAnimeFragment(widget.screen!)
              : Container(),
          bottomNavigationBar: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                label: 'Add Anime',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.business),
                label: 'Favourite',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.settings),
                label: 'Settings',
              ),
            ],
            currentIndex: controller.bottomSheetIndex.value,
            selectedItemColor: ColorName.primaryColor,
            onTap: (s) {
              controller.bottomSheetIndex.value = s;
            },
          ),
        ));
  }
}
cyej8jka

cyej8jka8#

只需执行以下步骤
在类中创建一个变量,如下所示

var scaffoldKey = GlobalKey<ScaffoldState>();

然后像这样在脚手架上使用这把钥匙

Scaffold(
    key: scaffoldKey,
    appBar: AppBar(
        automaticallyImplyLeading: false,
        leading: IconButton(
            onPressed: () {
              scaffoldKey.currentState?.openDrawer();
            },
            icon: Icon(
              Icons.menu,
              color: ExtraColors.PRIMARY_800,
            )),
        title: Text(
          '${AppStrings.appName}',
        ),
        centerTitle: true,
      ),
   )

相关问题