在 flutter 中使用 setState() 的替代方法是什么?

What is the alternative of using setState() in flutter?

我正在我的 Flutter 项目 中实施 Curved_Navigation_Bar 并且我 没有使用任何 class(即有状态/无状态)。我想更改 curved_navigation_bar 中图标的状态,这意味着我想要导航栏上的动画效果。因为这些图标的相应页面正在导航而不是那些项目。无论我点击哪个图标,它仍然只显示第一个图标。 图标 animation/interpolation 没有发生。

因为我没有使用任何 Stateful/Stateless class,所以 我没有使用脚手架 。在 Scaffold 内部,我们可以使用 setState(() { }).

更改当前对象的状态

那么如何更改导航栏的状态?

下面是我的代码:

navigation_bar.dart

import 'package:flutter/material.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'package:thehelpdesk/components/home/history.dart';
import 'package:thehelpdesk/components/home/home.dart';
import 'package:thehelpdesk/components/home/menu.dart';
import 'package:thehelpdesk/components/home/notification.dart';
import 'package:thehelpdesk/components/home/person.dart';

int currentIndex = 0 ;
Widget navBarSection(Color color, Color btnColor, BuildContext context) {
  return CurvedNavigationBar(
      index: 0,
      items:
      [
        Icon(Icons.home, color: Colors.white),
        Icon(Icons.notifications, color: Colors.white),
        Icon(Icons.menu, color: Colors.white),
        Icon(Icons.history, color: Colors.white),
        Icon(Icons.person, color: Colors.white),
      ],
      color: color,
      buttonBackgroundColor: btnColor,
      animationCurve: Curves.easeInCubic,
      animationDuration: Duration(milliseconds: 600),
onTap: (index) {
if(currentIndex == 0){
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => HomePage()));
          currentIndex = index ;
        }
        if(currentIndex == 1){
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => NotificationPage()));
          currentIndex = index ;
        }
        if(currentIndex == 2){
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => MenuPage()));
          currentIndex = index ;
        }
        if(currentIndex == 3){
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => HistoryPage()));
          currentIndex = index ;
        }
        if(currentIndex == 4){
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => PersonPage()));
          currentIndex = index ;
        }
      }
  );

我想通过点击图标导航的页面之一:

home.dart

import 'package:flutter/material.dart';
import 'package:thehelpdesk/widgets/appbar.dart';
import 'package:thehelpdesk/widgets/navigation_bar.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: aapBarSection('Home', Colors.blueAccent[700], context),
        bottomNavigationBar: navBarSection(
          Colors.blueAccent[700],
          Colors.blueAccent[700],
          context
        ),
    );
  }
}

点击第二个图标的另一页:

notification.dart

import 'package:flutter/material.dart';
import 'package:thehelpdesk/widgets/appbar.dart';
import 'package:thehelpdesk/widgets/navigation_bar.dart';

class NotificationPage extends StatefulWidget {
  @override
  _NotificationPageState createState() => _NotificationPageState();
}

class _NotificationPageState extends State<NotificationPage> {

  final message = [
    'Hi Xyz,your invoice for It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.',
    'Hi Xyz, Agility Rehab Care wishing you a very happy birthday! for It has survived not only five centuries, but also the leap remaining essentially unchanged.',
    'Hi Xyz, From our Agility Rehab Care you are being reminded that you have an appointment with us on this Friday.',
    'Hi Xyz, This is a reminder for you from Agility Rehab Care It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
  ];

  final images = [
    'assets/images/Invoice.png',
    'assets/images/cake.png',
    'assets/images/calender.png',
    'assets/images/Reminder.png'
  ];
  String date = '22/02/2021';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: aapBarSection('Notification',Colors.blueAccent[700],context),
      bottomNavigationBar: navBarSection(
        Colors.blueAccent[700],
        Colors.blueAccent[700],
        context
      ),
      body: ListView.builder(
          itemCount: message.length,
          itemBuilder: (context, index) {
            return Padding(
              padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
              child: SizedBox(
                height: 200,
                child: Card(
                    elevation: 5.0,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10.0),
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Container(
                        child: Column(
                          children: [
                            Flexible(
                              flex: 7,
                              child: Container(
                                child: Row(
                                  children: [
                                    Expanded(
                                      flex: 2,
                                      child: Container(
                                        decoration: BoxDecoration(
                                            image: DecorationImage(
                                                image: AssetImage(
                                                    images[index]))),
                                      ),
                                    ),
                                    Expanded(
                                      flex: 8,
                                      child: Container(
                                        child: Text(message[index]),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                            Flexible(
                              flex: 3,
                              child: Padding(
                                padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
                                child: Container(
                                  child: Row(
                                    mainAxisAlignment: MainAxisAlignment.end,
                                    children: [Text(date)],
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    )),
              ),
            );
          })
    );
  }
}

简短的回答是只需添加 currentIndex 作为 navBarSection 中的参数之一。

navigation_bar.dart

Widget navBarSection(
  int currentIndex,
  Color color,
  Color btnColor,
  BuildContext context,
) {
  return CurvedNavigationBar(
      index: currentIndex,
      items: [
        Icon(Icons.home, color: Colors.white),
        Icon(Icons.notifications, color: Colors.white),
        Icon(Icons.menu, color: Colors.white),
        Icon(Icons.history, color: Colors.white),
        Icon(Icons.person, color: Colors.white),
      ],
      color: color,
      buttonBackgroundColor: btnColor,
      animationCurve: Curves.easeInCubic,
      animationDuration: Duration(milliseconds: 600),
      onTap: (index) {
        if (currentIndex == 0) {
          Navigator.of(context)
              .push(MaterialPageRoute(builder: (context) => HomePage()));
          currentIndex = index;
        }
        if (currentIndex == 1) {
          Navigator.of(context).push(
              MaterialPageRoute(builder: (context) => NotificationPage()));
          currentIndex = index;
        }
        if (currentIndex == 2) {
          Navigator.of(context)
              .push(MaterialPageRoute(builder: (context) => MenuPage()));
          currentIndex = index;
        }
        if (currentIndex == 3) {
          Navigator.of(context)
              .push(MaterialPageRoute(builder: (context) => HistoryPage()));
          currentIndex = index;
        }
        if (currentIndex == 4) {
          Navigator.of(context)
              .push(MaterialPageRoute(builder: (context) => PersonPage()));
          currentIndex = index;
        }
      });
}

home.dart里面,只要传递页面的currentIndex即可。

home.dart

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: aapBarSection('Home', Colors.blueAccent[700], context),
      bottomNavigationBar: navBarSection(
        0,
        Colors.blueAccent[700],
        Colors.blueAccent[700],
        context,
      ),
    );
  }
}

这应该可以解决您的问题,但如您所见,这不是实现 bottomnavigationbar 和小部件的最佳方式,原因是:

  1. 您将丢失软件包提供的动画。
  2. 它不符合底部导航行为,因为它将导航到新页面而不是替换它。

为了解决这个问题,创建一个新的有状态小部件,对于这个例子,我称之为main_page.dart

main_page.dart

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  int _currentIndex = 0;
  List<Widget> _pages = [
    HomePage(),
    NotificationPage(),
    MenuPage(),
    HistoryPage(),
    PersonPage(),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages.elementAt(_currentIndex),
      bottomNavigationBar: CurvedNavigationBar(
        backgroundColor: Colors.blueAccent,
        items: [
          Icon(Icons.home, color: Colors.white),
          Icon(Icons.notifications, color: Colors.white),
          Icon(Icons.menu, color: Colors.white),
          Icon(Icons.history, color: Colors.white),
          Icon(Icons.person, color: Colors.white),
        ],
        color: Colors.blueAccent[700],
        buttonBackgroundColor: Colors.blueAccent[700],
        animationCurve: Curves.easeInCubic,
        animationDuration: Duration(milliseconds: 600),
        onTap: (index) {
          setState(() {
            _currentIndex = index;
          });
        },
      ),
    );
  }
}

在您的 main.dart 中调用了 main_page.dart

main.dart

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MainPage(),
    );
  }
}

最后,从主页、历史记录、菜单、通知和人员页面中删除任何 bottomNavigationBar

结果是