如何检测抽屉是否在颤动下关闭?

时间:2018-09-17 15:25:25

标签: dart flutter

作为标题。既然我们可以检测到抽屉是否打开,但是是否可以检查抽屉是否关闭?谢谢。

6 个答案:

答案 0 :(得分:3)

声明一个GlobalKey来引用您的抽屉:

GlobalKey _drawerKey = GlobalKey();

将钥匙放入抽屉中

 drawer: Drawer(
                  key: _drawerKey,

检查抽屉是否可见:

 final RenderBox box = _drawerKey.currentContext?.findRenderObject();
 if (box != null){
    //is visible
 } else {
   //not visible  
} 

答案 1 :(得分:1)

您可以在下面复制粘贴运行完整代码
您可以用Drawer包裹StatefulWidget并将callback放在initState()dispose()
initState()将调用widget.callback(true);表示打开
dispose()将调用widget.callback(false);表示关闭
幻灯片在这种情况下也可以使用

代码段

drawer: CustomDrawer(
        callback: (isOpen) {
          print("isOpen ${isOpen}");
          WidgetsBinding.instance.addPostFrameCallback((_) {
            setState(() {
              _isDrawerOpen = isOpen;
            });
          });
        },
...
class CustomDrawer extends StatefulWidget {
  CustomDrawer({
    Key key,
    this.elevation = 16.0,
    this.child,
    this.semanticLabel,
    this.callback,
  })  : assert(elevation != null && elevation >= 0.0),
        super(key: key);

  final double elevation;
  final Widget child;
  final String semanticLabel;

  final DrawerCallback callback;
  @override
  _CustomDrawerState createState() => _CustomDrawerState();
}

class _CustomDrawerState extends State<CustomDrawer> {
  @override
  void initState() {
    if (widget.callback != null) {
      widget.callback(true);
    }

    super.initState();
  }

  @override
  void dispose() {
    if (widget.callback != null) {
      widget.callback(false);
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
        key: widget.key,
        elevation: widget.elevation,
        semanticLabel: widget.semanticLabel,
        child: widget.child);
  }
}

工作演示

enter image description here

完整代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isDrawerOpen = false;
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      drawer: CustomDrawer(
        callback: (isOpen) {
          print("isOpen ${isOpen}");
          WidgetsBinding.instance.addPostFrameCallback((_) {
            setState(() {
              _isDrawerOpen = isOpen;
            });
          });
        },
        child: ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            DrawerHeader(
              child: Text('Drawer Header'),
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
            ),
            ListTile(
              title: Text('Item 1'),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SecondRoute()),
                );
              },
            ),
            ListTile(
              title: Text('Item 2'),
              onTap: () {
                // Update the state of the app.
                // ...
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Align(
              alignment: Alignment.centerRight,
              child: Text(
                _isDrawerOpen.toString(),
              ),
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class CustomDrawer extends StatefulWidget {
  CustomDrawer({
    Key key,
    this.elevation = 16.0,
    this.child,
    this.semanticLabel,
    this.callback,
  })  : assert(elevation != null && elevation >= 0.0),
        super(key: key);

  final double elevation;
  final Widget child;
  final String semanticLabel;

  final DrawerCallback callback;
  @override
  _CustomDrawerState createState() => _CustomDrawerState();
}

class _CustomDrawerState extends State<CustomDrawer> {
  @override
  void initState() {
    if (widget.callback != null) {
      widget.callback(true);
    }

    super.initState();
  }

  @override
  void dispose() {
    if (widget.callback != null) {
      widget.callback(false);
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
        key: widget.key,
        elevation: widget.elevation,
        semanticLabel: widget.semanticLabel,
        child: widget.child);
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("route test"),
        ),
        body: Text("SecondRoute"));
  }
}

答案 2 :(得分:1)

很高兴地通知您,我已经开发了此功能并已在 Flutter 2.0.0 中引入。

只需在 Scaffold 中使用回调

return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      drawer: NavDrawer(),
      onDrawerChanged: (isOpen) {
        // write your callback implementation here
        print('drawer callback isOpen=$isOpen');
      },
      endDrawer: NavDrawerEnd(),
      onEndDrawerChanged: (isOpen) {
        // write your callback implementation here
        print('end drawer callback isOpen=$isOpen');
      },
      body:
      ...

在 2.0.0 中合并的拉取请求:https://github.com/flutter/flutter/pull/67249

快乐编码!

答案 3 :(得分:0)

当单击“抽屉项目”以导航到新屏幕时,在Navigator.push(..)调用中,您可以添加.then(..)子句,然后知道何时弹出了“抽屉项目屏幕” 。

这是一个Drawer项目的ListTile,它在单击时会进行Navigator.push(..)调用,以及相关的.then(..)回调块:

     ListTile(
          title: Text('About App'),
          onTap: () {
            Navigator.push(
              _ctxt,
              MaterialPageRoute(builder: (context) => AboutScreen()),
            ).then(
              (value) {
                print('Drawer callback for About selection');
                if (_onReadyCallback != null) {
                  _onReadyCallback();
                }
              },
            );
          }),

_onReadyCallback()表示您可以传递的功能参数。

我发现这是一种方法-利用.then()调用中的.push()回调-是一个非常有用的概念,通常可以理解Flutter。

非常感谢这里的2个主要答案: Force Flutter navigator to reload state when popping

这是完整的Drawer代码:

Drawer drawer = Drawer(
  child: ListView(
    padding: EdgeInsets.zero,
    children: <Widget>[
      DrawerHeader(
        decoration: BoxDecoration(
          color: Color(0xFF7FAD5F),
        ),
        child: Text(App.NAME_MENU),
      ),
      ListTile(
          title: Text('About App'),
          onTap: () {
            Navigator.push(
              _ctxt,
              MaterialPageRoute(builder: (context) => AboutScreen()),
            ).then(
              (value) {
                print('Drawer callback for About selection');
                if (_onReadyCallback != null) {
                  _onReadyCallback();
                }
              },
            );
          }),
    ],
  ),
);

答案 4 :(得分:0)

我建议您使用此软件包:https://pub.dev/packages/visibility_detector.

此后,您应该将一个GlobalKey(例如_drawerKey)分配给Drawer小部件,之后您将能够检测出何时关闭抽屉,如下所示:

VisibilityDetector(
              key: _drawerKey,
              child: Container(),
              onVisibilityChanged: (info) {
                if (info.visibleFraction == 0.0) {
                  // drawer not visible.
                }
              },
            )

答案 5 :(得分:0)

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

财产:

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

示例:

@override Widget build(BuildContext context) {

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