颤振:是否可以检测抽屉何时打开?

boe*_*edi 4 flutter

是否可以检测到抽屉何时打开,以便我们可以运行一些例程来更新其内容?

我的典型用例是显示关注者,喜欢者的数量……为此,我需要轮询服务器以获取此信息,然后进行显示。

我尝试实现NavigatorObserver来捕捉使抽屉可见/隐藏但NavigatorObserver没有检测到有关抽屉的任何事件。

这是链接到NavigatorObserver的代码:

import 'package:flutter/material.dart';

typedef void OnObservation(Route<dynamic> route, Route<dynamic> previousRoute);
typedef void OnStartGesture();

class NavigationObserver extends NavigatorObserver {
  OnObservation onPushed;
  OnObservation onPopped;
  OnObservation onRemoved;
  OnObservation onReplaced;
  OnStartGesture onStartGesture;

  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    if (onPushed != null) {
      onPushed(route, previousRoute);
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
    if (onPopped != null) {
      onPopped(route, previousRoute);
    }
  }

  @override
  void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
    if (onRemoved != null)
      onRemoved(route, previousRoute);
  }

  @override
  void didReplace({ Route<dynamic> oldRoute, Route<dynamic> newRoute }) {
    if (onReplaced != null)
      onReplaced(newRoute, oldRoute);
  }

  @override
  void didStartUserGesture() { 
    if (onStartGesture != null){
      onStartGesture();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

和这个观察者的初始化

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final NavigationObserver _observer = new NavigationObserver()
                                              ..onPushed = (Route<dynamic> route, Route<dynamic> previousRoute) {
                                                print('** pushed route: $route');
                                              }
                                              ..onPopped = (Route<dynamic> route, Route<dynamic> previousRoute) {
                                                print('** poped route: $route');
                                              }
                                              ..onReplaced = (Route<dynamic> route, Route<dynamic> previousRoute) {
                                                print('** replaced route: $route');
                                              }
                                              ..onStartGesture = () {
                                                print('** on start gesture');
                                              };

  @override
  void initState(){
    super.initState();
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Title',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new SplashScreen(),
        routes: <String, WidgetBuilder> {
          '/splashscreen': (BuildContext context) => new SplashScreen(),
        },
        navigatorObservers: <NavigationObserver>[_observer],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助。

Viv*_*sal 15

最佳解决方案

ScaffoldState有一个有用的方法isDrawerOpen可以提供打开/关闭的状态。

示例:在背面按下时,它首先检查抽屉是否打开,如果是,则首先将在退出前关闭。

/// create a key for the scaffold in order to access it later.
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

@override
Widget build(context) {
   return WillPopScope(
  child: Scaffold(
    // assign key (important)
    key: _scaffoldKey,
    drawer: SideNavigation(),
  onWillPop: () async {
    // drawer is open then first close it
    if (_scaffoldKey.currentState.isDrawerOpen) {
      Navigator.of(context).pop();
      return false;
    }
    // we can now close the app.
    return true;
  });}
Run Code Online (Sandbox Code Playgroud)


pep*_*pen 12

这对我有用。

通过任何操作打开抽屉时运行initState。

当关闭抽屉时,请执行任何操作处置。

希望对您有所帮助。

class MyDrawer extends StatefulWidget {
  @override
  _MyDrawerState createState() => _MyDrawerState();
}

class _MyDrawerState extends State<MyDrawer> {

  @override
  void initState() {
    super.initState();
    print("open");
  }

  @override
  void dispose() {
    print("close");
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: Column(
        children: <Widget>[
          Text("test1"),
          Text("test2"),
          Text("test3"),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么这不被接受?这说明按下按钮和滑动抽屉打开 (3认同)
  • 这个解决方案对我来说非常有效。应该已经被接受了。 (3认同)

Vis*_*wal 8

您可以简单地使用onDrawerChanged来检测 Scaffold 小部件中抽屉是否打开或关闭。

财产 :

{无效函数(布尔)?onDrawerChanged}
类型:void Function(bool)?
打开或关闭 Scaffold.drawer 时调用的可选回调。

例子 :

@override Widget build(BuildContext context) {

return Scaffold(
  onDrawerChanged:(val){
    if(val){
      setState(() {
        //foo bar;
      });
    }else{
      setState(() {
        //foo bar;
      });
    }
},     
  drawer: Drawer(        
      child: Container(
      )
  ));
Run Code Online (Sandbox Code Playgroud)

}


dee*_*s91 7

由于https://github.com/flutter/flutter/pull/67249已经与 Flutter 2.0 合并并发布,这里是检测抽屉打开/关闭的正确方法:

Scaffold(
      onDrawerChanged: (isOpened) {
        //todo what you need for left drawer
      },
      onEndDrawerChanged: (isOpened) {
        //todo what you need for right drawer
      },
)
Run Code Online (Sandbox Code Playgroud)

  • 现在这个功能已经内置,这篇文章应该更新为正确的答案。谢谢 (2认同)

azi*_*iza 5

我认为一个简单的解决方案是覆盖leading您的属性,AppBar以便您可以在按下菜单图标时访问并基于此运行API调用。

但是我可能会误解您的问题,因为对于您提供的用例,通常需要以一种可以监听任何会自动更新值的更改的方式来管理它,所以我不确定您尝试在什么情况下触发什么抽屉是打开的。

无论如何,这是示例。

在此处输入图片说明

class DrawerExample extends StatefulWidget {
  @override
  _DrawerExampleState createState() => new _DrawerExampleState();
}

class _DrawerExampleState extends State<DrawerExample> {
  GlobalKey<ScaffoldState> _key = new GlobalKey<ScaffoldState>();
  int _counter =0;
  _handleDrawer(){
      _key.currentState.openDrawer();

           setState(() {
          ///DO MY API CALLS
          _counter++;
        });

  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _key,
      appBar: new AppBar(
        title: new Text("Drawer Example"),
        centerTitle: true,
        leading: new IconButton(icon: new Icon(
          Icons.menu
        ),onPressed:_handleDrawer,),
      ),
      drawer: new Drawer(
        child: new Center(
          child: new Text(_counter.toString(),style: Theme.of(context).textTheme.display1,),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 不会通过用户滑动动作检测到抽屉打开。 (2认同)