Flutter - 如何在页面上动态显示或隐藏应用栏

33

我设计了一个屏幕,当从导航抽屉或其他屏幕中的意图出现时。

现在我想要在从导航抽屉中出现时隐藏应用栏,所以请指导我,以下是我的代码

导航屏幕代码

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:pwc/src/home/HomeScreen.dart';
import 'package:pwc/src/model/UserModel.dart';
import 'package:pwc/src/property/BuyerPropertyListScreen.dart';
import 'package:pwc/src/property/RentPropertyListScreen.dart';
import 'package:pwc/src/property/MyPropertyListScreen.dart';
import 'package:pwc/src/property/PostPropertyScreen.dart';
import 'package:pwc/src/home/FeedbackScreen.dart';
import 'package:pwc/src/utility/ColorsConstant.dart' as ColorConstant;
import 'package:pwc/src/utility/DrawableConstant.dart' as DrawableConstant;
import 'package:pwc/src/utility/StringConstant.dart' as StringConstant;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:pwc/src/utility/globals.dart' as globals;
import 'package:pwc/src/utility/KeyConstant.dart' as KeyConstant;
import 'package:pwc/src/property/PropertyListScreen.dart';

class DrawerItem {
  String title;
  ImageIcon icon;

  DrawerItem(this.title, this.icon);
}

class NavigationDrawerScreen extends StatefulWidget {
  static String tag = 'navigation-page';

  @override
  _NavigationDrawerState createState() => new _NavigationDrawerState();
}

class _NavigationDrawerState extends State<NavigationDrawerScreen> {
  int selectedDrawerItem = 0;
  var appBarTitleText = StringConstant.home;

  var homeIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_home),
    size: 30.0,
  );

  var buyPropertyIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_buy_property),
    size: 30.0,
  );

  var rentPropertyIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_rent_property),
    size: 30.0,
  );

  var postPropertyIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_post_property),
    size: 30.0,
  );

  var myPropertiesIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_my_properties),
    size: 30.0,
  );

  var feedbackIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_feedback),
    size: 30.0,
  );

  var ratingIcon = new ImageIcon(
    new AssetImage(DrawableConstant.ic_rating),
    size: 30.0,
  );


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

  @override
  Widget build(BuildContext context) {
    var nav_header_exact_bg =
        new ExactAssetImage(DrawableConstant.nav_header_bg);

    return new Scaffold(
      appBar: AppBar(
        backgroundColor: ColorConstant.theme_color,
        title: new Text(appBarTitleText),
        centerTitle: true,
      ),
      drawer: Drawer(
        child: new ListView(
          children: <Widget>[
            new UserAccountsDrawerHeader(
              accountName: new Text(userModel.name),
              accountEmail: new Text(userModel.email),
              decoration: new BoxDecoration(
                image: new DecorationImage(
                  image: nav_header_exact_bg,
                  fit: BoxFit.cover,
                ),
              ),
            ),
            new ListTile(
                leading: homeIcon,
                title: new Text(StringConstant.home),
                onTap: () {
                  setAPPBarTitleText(StringConstant.home);
                  Navigator.pop(context);
                  setState(() {
                    selectedDrawerItem = 0;
                  });
                }),
            new Divider(
              height: 1,
            ),
            new ListTile(
                leading: buyPropertyIcon,
                title: new Text(StringConstant.properties_for_buy),
                onTap: () {
                  setAPPBarTitleText(StringConstant.properties_for_buy);
                  Navigator.pop(context);
                  setState(() {
                    selectedDrawerItem = 1;
                  });
                }),
            new Divider(
              height: 1,
            ),
          ],
        ),
      ),
      body: getDrawerScreenBody(selectedDrawerItem),
    );
  }

  getDrawerScreenBody(int pos) {
    switch (pos) {
      case 0:
        return new HomeScreen();
      case 1:
        return new BuyerPropertyListScreen();
    }
  }

  void setAPPBarTitleText(String title) {
    setState(() {
      appBarTitleText = title;
    });
  }

}

当我打开BuyerPropertyListScreen时,内部应用栏也会显示出来,我希望能动态隐藏它,请看下面的截图。

enter image description here

6个回答

73
您可以尝试这种方式。
appBar: boolTrue ? AppBar(...) : null

15
有没有办法以动画方式呈现它? - bks

27

屏幕截图(空值安全):

在此输入图片描述


创建此类。

class SlidingAppBar extends StatelessWidget implements PreferredSizeWidget {
  SlidingAppBar({
    required this.child,
    required this.controller,
    required this.visible,
  });

  final PreferredSizeWidget child;
  final AnimationController controller;
  final bool visible;
  
  @override
  Size get preferredSize => child.preferredSize;
  
  @override
  Widget build(BuildContext context) {
    visible ? controller.reverse() : controller.forward();
    return SlideTransition(
      position: Tween<Offset>(begin: Offset.zero, end: Offset(0, -1)).animate(
        CurvedAnimation(parent: controller, curve: Curves.fastOutSlowIn),
      ),
      child: child,
    );
  }
}

使用方法:

class MyPage extends StatefulWidget {
  @override
  _MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
  bool _visible = true;
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 400),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // extendBodyBehindAppBar: !_visible, // Uses entire screen after hiding AppBar
      floatingActionButton: FloatingActionButton.extended(
        label: Text(_visible ? 'Hide' : 'Show'),
        onPressed: () => setState(() => _visible = !_visible),
      ),
      appBar: SlidingAppBar(
        controller: _controller,
        visible: _visible,
        child: AppBar(title: Text('AppBar')),
      ),
    );
  }
}

4
好的做法:在State类中覆写dispose方法,并调用_controller.dispose() - CopsOnRoad

11
您可以像这样使用PreferredSize小部件: true ? Appbar() : PreferredSize(preferredSize: Size(0.0, 0.0),child: Container(),) 如果条件为false,则将隐藏应用程序栏。

在我的情况下,容器的宽度和高度为零。因为它有一些顶部填充。 - Amarnath Baitha

7
下面的代码也可以隐藏AppBar。kToolbarHeight在这里被定义。
 toolbarHeight: boolTrue ? kToolbarHeight : 0.0

0

所有的代码看起来都没问题,但它却不能正常工作。在我的情况下,我需要添加SetState:

setState(() => showAppBar = !request.isForMainFrame);

在这里找到了答案: 如何在双击时动态隐藏AppBar?


这并没有真正回答问题。如果您有不同的问题,可以通过点击提问来提出。如果您想在此问题获得新的答案时得到通知,您可以关注此问题。一旦您拥有足够的声望,您还可以添加悬赏以吸引更多关注。- 来自审核 - David

0

试试这个

bool myBool = false;

//...
appBar: isEditable == true
            ? AppBar( .. ):null

完整代码

appBar: isEditable == true
            ? AppBar(
                title: Text("Teacher Profile"),
                leading: IconButton(
                  icon: Icon(Icons.arrow_back_ios),
                  onPressed: () {
                    Util().navigateToBack(context);
                  },
                ),
                centerTitle: true,
              )
            : null,

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接