Как изменить значок меню гамбургера в навигационном ящике на значок стрелки при открытии / закрытии расположения ящика — трепетание?

#flutter

#трепетание

Вопрос:

Когда я создал макет ящика после Добавления ящика в документы экрана, все работает нормально. Однако у меня проблема, это значок меню.

В Android я настраиваю макет ящика с помощью DrawerToggle, и когда я открываю ящик, значок меню изменится на значок стрелки, а когда я закрываю ящик, значок стрелки изменится на значок меню.

В Flutter это работает не так, как указано выше.

Если вы понимаете мою проблему, пожалуйста, помогите мне. Я много искал, но не нашел решения. Итак, я хочу спросить всех. Большое вам спасибо.

введите описание изображения здесь

 import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  final appTitle = 'Drawer Demo';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(child: Text('My Page!')),
      drawer: Drawer(
        // Add a ListView to the drawer. This ensures the user can scroll
        // through the options in the Drawer if there isn't enough vertical
        // space to fit everything.
        child: ListView(
          // Important: Remove any padding from the ListView.
          padding: EdgeInsets.zero,
          children: <Widget>[
            DrawerHeader(
              child: Text('Drawer Header'),
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
            ),
            ListTile(
              title: Text('Item 1'),
              onTap: () {
                // Update the state of the app
                // ...
                // Then close the drawer
                Navigator.pop(context);
              },
            ),
            ListTile(
              title: Text('Item 2'),
              onTap: () {
                // Update the state of the app
                // ...
                // Then close the drawer
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}
  

Комментарии:

1. Почему вы хотите изменить значок ящика, поскольку при открытии ящика он скроет его. flutter.dev /изображения / кулинарная книга /drawer.png

2. В большинстве случаев то, что вы говорите, верно. Но иногда расположение ящика находится под значком меню и панелью инструментов, например: i.stack.imgur.com/hK4mD.png

3. Если это так, проверьте мой ответ

Ответ №1:

Используйте, StateFulWidget чтобы вы могли получить доступ setState к способу изменения значка

В вашем state классе

Определите Global Key

 final GlobalKey<ScaffoldState> _key = GlobalKey();
  

Определите, boolean чтобы проверить, Drawer открыто ли.

 bool _isDrawerOpen = false;
  

Добавьте их в свой state класс

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Title'),
        leading: IconButton(
          icon: _isDrawerOpen ? Icon(Icons.menu) : Icon(Icons.arrow_back), 
          onPressed: onPressed,
        ),
      ),
      drawer: WillPopScope(child: Drawer(), onWillPop: onPop),
      body: //body
      key: this._key,
    );
  }

void onPressed() {
  if (!_isDrawerOpen) {
    this._key.currentState.openDrawer();
  } else {
    Navigator.pop(context);
  }
  setState(() {
    _isDrawerOpen = !_isDrawerOpen;
  });
}

void onPop() {
  if (_isDrawerOpen) {
    setState(() {
      _isDrawerOpen = false;
    });
  }
  Navigator.pop(context);
} 
  

Комментарии:

1. Я понимаю вашу идею. Это работало довольно хорошо, хотя были некоторые незначительные ошибки. И вы, и код @ android сработали для меня. Большое вам спасибо.

Ответ №2:

Чтобы изменить значок гамбургера при открытом ящике, а также отобразить ящик под панелью приложений:

Я объявил «МЕТОД 1» и «МЕТОД 2» в своем коде, которые указаны в комментариях.

«МЕТОД 1» позволяет открыть ящик и изменить значок с обратным вызовом контроллера ящика.

«МЕТОД 2» позволяет открывать ящик, когда мы нажимаем значок гамбургера, Проблема в том, что мы не можем щелкнуть значок гамбургера при использовании контроллера ящика.

 import 'package:flutter/material.dart';

class MyNavDrawerController extends StatefulWidget {
  createState() {
    return StateKeeper();
  }
}

class StateKeeper extends State<MyNavDrawerController> {
  // Declare a new variable which will increment on FAB tap
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  final appBarColor = const Color(0xFFd2527f);
  var myIcon = new Icon(Icons.list);

  DrawerCallback drawerCallback(bool status) {
    Fluttertoast.showToast(
        msg: "Drawer "   status.toString(),
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
        timeInSecForIos: 1,
        backgroundColor: appBarColor,
        textColor: Colors.white,
        fontSize: 14.0);
    setState(() {
      setMenuIcon(status);
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      primary: true,
      appBar: AppBar(
        title: Text("Parent Scaffold"),
          leading: new IconButton(icon: myIcon,
              onPressed:(){
                _scaffoldKey.currentState.openDrawer();

              }
          )
      ),


      // METHOD 1
      /*body: DrawerController(
        child: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text('Andy Rubin'),
                decoration: BoxDecoration(color: Colors.blue),
              ),
              ListTile(
                title: Text('Home'),
                onTap: () {
                  setState(() {
                    Navigator.pop(context);
                  });
                },
              ),
              ListTile(
                title: Text('About us'),
                onTap: () {
                  Navigator.pop(context);
                  Fluttertoast.showToast(
                      msg: "About us clicked! :)",
                      toastLength: Toast.LENGTH_SHORT,
                      gravity: ToastGravity.CENTER,
                      timeInSecForIos: 1,
                      backgroundColor: Colors.red,
                      textColor: Colors.white,
                      fontSize: 16.0);
                },
              ),
              ListTile(
                title: Text('Notifications'),
                onTap: () {
                  Navigator.pop(context);
                  Fluttertoast.showToast(
                      msg: "Notifications clicked! :)",
                      toastLength: Toast.LENGTH_SHORT,
                      gravity: ToastGravity.CENTER,
                      timeInSecForIos: 1,
                      backgroundColor: Colors.blue,
                      textColor: Colors.white,
                      fontSize: 18.0);
                },
              )
            ],
          ),
        ),
          alignment: DrawerAlignment.start, drawerCallback: drawerCallback
      ),*/


      // METHOD 2
      /*body: Scaffold(
        key: _scaffoldKey,
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text('Andy Rubin'),
                decoration: BoxDecoration(color: Colors.blue),
              ),
              ListTile(
                title: Text('Home'),
                onTap: () {
                  Fluttertoast.showToast(
                      msg: "Home clicked! :)",
                      toastLength: Toast.LENGTH_SHORT,
                      gravity: ToastGravity.CENTER,
                      timeInSecForIos: 1,
                      backgroundColor: appBarColor,
                      textColor: Colors.white,
                      fontSize: 14.0);
                  setState(() {
                    Navigator.pop(context);
                  });
                },
              ),
              ListTile(
                title: Text('About us'),
                onTap: () {
                  Navigator.pop(context);
                  Fluttertoast.showToast(
                      msg: "About us clicked! :)",
                      toastLength: Toast.LENGTH_SHORT,
                      gravity: ToastGravity.CENTER,
                      timeInSecForIos: 1,
                      backgroundColor: Colors.red,
                      textColor: Colors.white,
                      fontSize: 16.0);
                },
              ),
              ListTile(
                title: Text('Notifications'),
                onTap: () {
                  Navigator.pop(context);
                  Fluttertoast.showToast(
                      msg: "Notifications clicked! :)",
                      toastLength: Toast.LENGTH_SHORT,
                      gravity: ToastGravity.CENTER,
                      timeInSecForIos: 1,
                      backgroundColor: Colors.blue,
                      textColor: Colors.white,
                      fontSize: 18.0);
                },
              )
            ],
          ),
        ),
      )*/

    );
  }

  void setMenuIcon(bool isDrawerOpen){
    if(isDrawerOpen){
      myIcon = new Icon(Icons.list);
    }else{
      myIcon = new Icon(Icons.arrow_back);
    }
  }

}
  

Комментарии:

1. Ваше объяснение отличное, подробное. МЕТОД 1 сработал нормально, МЕТОД 2 выдает небольшую ошибку: _scaffoldKey. И вы, и код @Mangaldeep Pannu сработали для меня. Большое вам спасибо.

Ответ №3:

Ниже я прикрепляю фрагмент моего кода, который, на мой взгляд, является самым простым способом создать пользовательский значок гамбургера. Основная часть кода заключается в использовании ведущего:!

 return Scaffold(
    backgroundColor: Colors.white,
    appBar: AppBar(
      backgroundColor: Colors.transparent,
      elevation: 0.0,
      leading: Builder(
          builder: (context) => IconButton(
                icon: Icon(
                  Icons.sort,
                  color: Colors.black54,
                ),
                onPressed: () => Scaffold.of(context).openDrawer(),
                tooltip:
                    MaterialLocalizations.of(context).openAppDrawerTooltip,
              )),
    ),
    drawer: Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: <Widget>[
          DrawerHeader(
            decoration: BoxDecoration(
              color: Colors.blue,
            ),
            child: Text('App'),
          ),
          ListTile(
            title: Text('Item 1'),
            onTap: () {
              Navigator.pop(context);
            },
          ),
          ListTile(
            title: Text('Item 2'),
            onTap: () {
              Navigator.pop(context);
            },
          ),
        ],
      ),
    ),)