在flutter中改变BottomNavigationBarItem中图标的显示条件时更新导航菜单

时间:2021-06-14 13:07:09

标签: flutter dart

我有一个为测试应用程序制作的导航菜单,如果我没有登录应用程序,我想隐藏一些选项卡。登录后,这些选项卡应该会出现。问题是,登录后,我转到所需的页面,但没有看到所有导航菜单图标。为了让它们出现,我需要单击可用图标之一(只有 2 个图标可用于授权),然后导航菜单才会更新,一切都将如此。所有 6 个图标都将可见!有人可以帮我弄这个吗?在这里,我描述了我正在使用的代码的问题。如有任何帮助,我将不胜感激。

import 'package:flutter/material.dart';
import 'package:flutter_app_seals/model/object_main/Status.dart';
import 'package:flutter_app_seals/model/seals/Seals_List.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_app_seals/Setting_glob.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:flutter_app_seals/model/add_seals/JsonAddSeals.dart';
import 'package:flutter_app_seals/model/user_page/page.dart';
import  'package:flutter_app_seals/model/setting/globalvar.dart' as global;
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:io';
import 'package:flutter_aes_ecb_pkcs5/flutter_aes_ecb_pkcs5.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/foundation.dart';


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


class Main_Page extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
        home:  HomePage());
  }
}

class HomePage extends StatefulWidget {

  @override
  _HomePageState createState() => _HomePageState();
}
var test;
class _HomePageState extends State<HomePage> {

  Future<bool> _onBackPressed() {
    return showDialog(
      context: context,
      builder: (context) => new AlertDialog(
        title: new Text('Ви впевнині?'),
        content: new Text('Ви хочете вийти з додатку',
          style: TextStyle(
            fontSize: 20,
          ),
        ),
        actions: <Widget>[
          new GestureDetector(
            onTap: () => Navigator.of(context).pop(false),
            child:
            Text("Ні",
              style: TextStyle(
                fontSize: 25,
              ),
            ),
          ),
          SizedBox(height: 40),
          new GestureDetector(
            onTap: () => Navigator.of(context).pop(true),
            child: Text("Так",
              style: TextStyle(
                fontSize: 25,
              ),
            ),
          ),
        ],
      ),
    ) ??
        false;
  }


  int _pageIndex = 0;
  PageController _pageController;

  List<Widget> tabPages = [
    Login(),
    Setting(),
    UserPage(),
    Status_Obj(),
    Status_Seals(),
    Add_Seals(),
  ] ;

  @override
  void initState(){
    super.initState();
    _pageController = PageController(initialPage: _pageIndex);
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }




  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onBackPressed,
      child: new Scaffold(
        resizeToAvoidBottomInset: false,
        bottomNavigationBar: BottomNavigationBar(
          showSelectedLabels: true,   // <-- HERE
          showUnselectedLabels: true, // <-- AND
          currentIndex: _pageIndex,
          onTap: onTabTapped,
          backgroundColor: Colors.blue,
          items: <BottomNavigationBarItem>[
            new BottomNavigationBarItem( icon: Icon(Icons.admin_panel_settings_outlined), title: Text(" Вхід"),backgroundColor: Colors.lightBlue),
            new BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text("Налаштування"),backgroundColor: Colors.lightBlue),
            if( global.nameUser ?.isNotEmpty == true)...[
              new BottomNavigationBarItem(icon: Icon(Icons.person_pin), title: Text("Користувач"),backgroundColor: Colors.lightBlue),
              new BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Пломбування"),backgroundColor: Colors.lightBlue),
              new BottomNavigationBarItem(icon: Icon(Icons.qr_code), title: Text("Пломби"),backgroundColor: Colors.lightBlue),
              new BottomNavigationBarItem(icon: Icon(Icons.add_outlined), title: Text("Акт приймання"),backgroundColor: Colors.lightBlue),
            ]

          ],

        ),
        body: PageView(
          children: tabPages,
          onPageChanged: onPageChanged,
          controller: _pageController,
        ),
      ),
    );



  }
  void onPageChanged(int page) {
    setState(() {
      this._pageIndex = page;
    });
  }

  void onTabTapped(int index) {
    this._pageController.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
  }
}


class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        home: new LoginPage(
            storage: Storage()
        )
    );
  }
}

class LoginPage extends StatefulWidget {

  final Storage storage;

  LoginPage({Key key, @required this.storage}) : super(key: key);

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

class _LoginPageState extends State<LoginPage> {
  //Info about users
  String state;

  @override
  void initState() {
    super.initState();
    widget.storage.readData().then((String value) {
      setState(() {
        global.urlVar = value;
      });
    });
  }

  bool _isLoading = false;

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(statusBarColor: Colors.transparent));
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
              colors: [Colors.blue, Colors.white],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter),
        ),
        child: _isLoading ? Center(child: CircularProgressIndicator()) : ListView(
          children: <Widget>[
            headerSection(),
            textSection(),
            buttonSection(),

          ],
        ),
      ),
    );
  }


  signIn(String login, pass) async {
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();

    var AESLogin = login;
    var AESpass = pass;
    //generate a 16-byte random key
    var key = '11111';

    print(key);
    //encrypt
    var encryptLogin = await FlutterAesEcbPkcs5.encryptString(AESLogin, key);
    var encryptPass = await FlutterAesEcbPkcs5.encryptString(AESpass, key);




    HttpClient client = new HttpClient();
    client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);


    String url = global.urlVar + "/auth_user";

    Map map = {
      "login": encryptLogin,
      "pass": encryptPass
    };

    HttpClientRequest request = await client.postUrl(Uri.parse(url));

    request.headers.set('content-type', 'application/json');

    request.add(utf8.encode(json.encode(map)));

    HttpClientResponse response = await request.close();


    var responseBody = await response.transform(utf8.decoder).join();

    Map jsonResponse = json.decode(responseBody);

    print(jsonResponse);

    if (response.statusCode == 200) {
      if (jsonResponse['message'] ==
          '200') { //if( jsonResponse['message'] == '200') {
        setState(() {



          _isLoading = false;


        });

        global.nameUser = jsonResponse['name'];
        global.dataArea = jsonResponse['data_area'];

        Navigator.pushReplacement(
          context,
          MaterialPageRoute(builder: (context) => UserPage()),
        );
      }
      else {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => Error_Auth()),
        );
      }
    }

    else   {
      setState(() {
        _isLoading = false;
      });
    }
  }

  Container buttonSection() {
    return Container(
      width: MediaQuery.of(context).size.width,
      height: 40.0,
      padding: EdgeInsets.symmetric(horizontal: 15.0),
      margin: EdgeInsets.only(top: 15.0),
      child: RaisedButton(
        onPressed: emailController.text == "" || passwordController.text == "" ? null : () {
          setState(() {
            _isLoading = true;
          });
          signIn(emailController.text, passwordController.text);
        },
        elevation: 0.0,
        color: Colors.purple,
        child: Text("Авторизація", style: TextStyle(color: Colors.white70)),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
      ),
    );
  }

  final TextEditingController emailController = new TextEditingController();
  final TextEditingController passwordController = new TextEditingController();

  Container textSection() {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
      child: Column(
        children: <Widget>[
          TextFormField(
            controller: emailController,
            cursorColor: Colors.white,

            style: TextStyle(color: Colors.white70),
            decoration: InputDecoration(
              icon: Icon(Icons.login, color: Colors.white70),
              hintText: "Логін",
              border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
              hintStyle: TextStyle(color: Colors.white70),
            ),
          ),
          SizedBox(height: 30.0),
          TextFormField(
            controller: passwordController,
            cursorColor: Colors.white,
            obscureText: true,
            style: TextStyle(color: Colors.white70),
            decoration: InputDecoration(
              icon: Icon(Icons.lock, color: Colors.white70),
              hintText: "Пароль",
              border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
              hintStyle: TextStyle(color: Colors.white70),
            ),
          ),

        ],
      ),

    );
  }

  Container headerSection() {
    return Container(
      alignment: Alignment.topCenter,
      margin: EdgeInsets.only(top: 50.0),
      child: Text("Пломби",
          style: TextStyle(
              color: Colors.white70,
              fontSize: 40.0,
              fontWeight: FontWeight.bold)),
    );
  }
}
class Error_Auth extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final AlertDialog dialog = AlertDialog(
      title: Text('Помилка при авторизації'),
      content:
      Text('Повторити спробу авторизації'),
      actions: [
        FlatButton(
          textColor: Color(0xFF6200EE),
          onPressed: () => SystemNavigator.pop(),
          child: Text('Ні'),
        ),
        FlatButton(
          textColor: Color(0xFF6200EE),
          onPressed: () {  Navigator.push(
            context,MaterialPageRoute(builder: (context) => Login()),
          );
          },
          child: Text('Так'),
        ),
      ],
    );
    return Scaffold(
        body:dialog
    );
  }
}

class Storage {
  Future<String> get localPath async {
    final dir = await getApplicationDocumentsDirectory();
    return dir.path;
  }

  Future<File> get localFile async {
    final path = await localPath;
    return File('$path/db.txt');
  }

  Future<String> readData() async {
    try {
      final file = await localFile;
      String body = await file.readAsString();

      return body;
    } catch (e) {
      return e.toString();
    }
  }

  Future<File> writeData(String data) async {
    final file = await localFile;
    return file.writeAsString("$data");
  }
}

在这部分代码中,我是自动化的,如果状态代码是 200,那么我会解析 Jason 并为变量 global.nameUser 添加一个名称。在导航菜单中,我检查它是否不为零,然后显示导航菜单的所有图标。但是第一次不行。我再次点击了这个菜单,然后它才会起作用。

   if (response.statusCode == 200) {
      if (jsonResponse['message'] ==
          '200') { //if( jsonResponse['message'] == '200') {
        setState(() {
          _isLoading = false;
        });
        global.nameUser = jsonResponse['name'];
        global.dataArea = jsonResponse['data_area'];

        Navigator.pushReplacement(
          context,
          MaterialPageRoute(builder: (context) => UserPage()),
        );
      }

检查导航菜单要显示哪些图标!

items: <BottomNavigationBarItem>[
            new BottomNavigationBarItem( icon: Icon(Icons.admin_panel_settings_outlined), title: Text(" Вхід"),backgroundColor: Colors.lightBlue),
            new BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text("Налаштування"),backgroundColor: Colors.lightBlue),
            if( global.nameUser ?.isNotEmpty == true)...[
              new BottomNavigationBarItem(icon: Icon(Icons.person_pin), title: Text("Користувач"),backgroundColor: Colors.lightBlue),
              new BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Пломбування"),backgroundColor: Colors.lightBlue),
              new BottomNavigationBarItem(icon: Icon(Icons.qr_code), title: Text("Пломби"),backgroundColor: Colors.lightBlue),
              new BottomNavigationBarItem(icon: Icon(Icons.add_outlined), title: Text("Акт приймання"),backgroundColor: Colors.lightBlue),
            ]

          ],

1 个答案:

答案 0 :(得分:1)

您的页面在用户登录后不会重新构建,这就是您的导航栏没有更新的原因。当您单击按钮时,它会刷新并正确显示新元素。

您可以查看状态管理包,而不是使用全局变量,以使登录用户可以在整个应用程序中使用。 (article 对于 getx 来说是最简单的)

如果这只是一个原型并且您想要一些快速和肮脏的东西,我想您可以通过使用一个公开重建方法的小部件包装您的应用程序来在用户登录后触发您的应用程序的重新加载。 (article)

编辑:Getx 示例:

class UserController extends GetxController {
  var nameUser = "".obs;

  void setName(String str) => nameUser = str;
}

class Home extends StatelessWidget {
  final UserController c = Get.put(UserController());

  @override
  Widget build(context)
      ...
          Obx(() => /// You are watching your controller
             ...
             items: <BottomNavigationBarItem>[
             if( c.nameUser.isNotEmpty)...[
                ...
             ]
          )))   
      ...


class LoginPage extends StatelessWidget {
  // You can ask Get to find a Controller that is being used by another page and redirect you to it.
  final UserController c = Get.find();

  @override
  Widget build(context){
      ...
      onPressed: () => c.setName(username);
  }
}

相关问题