首页 > 解决方案 > 使用提供程序从底部导航栏项目当前索引将平面按钮导航到另一个屏幕

问题描述

我创建了一个provider使用 来provider package判断BottomNavigationBar是否按下了 的项目,以便显示的页面与BottomNavigationBar的 body 属性中的项目匹配Scaffold。我已经在第一个项目TextFormField上制作了一个屏幕。我想要做的是,我想将所有已输入的数据添加到我创建的第三个屏幕项目中,然后在第一个屏幕上显示添加到数据中的第三个项目页面. 这几天我一直在寻找这个问题的解决方案,但我也没有找到答案。FlatButtonBottomNavigationBarTextFromFieldBottomNavigationBarBottomNavigationBarFlatButton

我的底部导航栏提供商

import 'package:flutter/material.dart';

class Index with ChangeNotifier {
  int _currentindex = 0;
  get currentindex => _currentindex;

  set currentindex(int index){
    _currentindex = index;
    notifyListeners();
  }
}

我的脚手架

import 'package:flutter/material.dart';
import 'package:kakeiboo/View/balance_screen.dart';
import 'package:kakeiboo/View/bignote_screen.dart';
import 'package:kakeiboo/View/daily_screen.dart';
import 'package:provider/provider.dart';
import 'package:kakeiboo/controller/notifier.dart';
import 'package:kakeiboo/constant.dart';

class BottomNavigate extends StatefulWidget {
  @override
  _BottomNavigateState createState() => _BottomNavigateState();
}

class _BottomNavigateState extends State<BottomNavigate> {
  var currentTab = [
    BigNotePage(),
    DailyExpensesPage(),
    BalancePage(),
  ];

  @override
  Widget build(BuildContext context) {
    var provider = Provider.of<Index>(context);
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: currentTab[provider.currentindex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: (index) {
          provider.currentindex = index;
        },
        currentIndex: provider.currentindex,
        backgroundColor: Color(0xff2196f3),
        showUnselectedLabels: false,
        selectedItemColor: Color(0xffffffff),
        type: BottomNavigationBarType.fixed,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.book),
            title: Text(
              'Big Note',
              style: kBottomNavigateStyle,
            ),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.receipt),
            title: Text(
              'Daily',
              style: kBottomNavigateStyle,
            ),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_balance_wallet),
            title: Text(
              'Balance',
              style: kBottomNavigateStyle,
            ),
          ),
        ],
      ),
    );
  }
}

我的第一个屏幕

import 'package:flutter/material.dart';
import 'package:kakeiboo/View/balance_screen.dart';
import 'package:kakeiboo/constant.dart';
class BigNotePage extends StatefulWidget {
  @override
  _BigNotePageState createState() => _BigNotePageState();
}

class _BigNotePageState extends State<BigNotePage> {
  bool _validate = false;
  final _formKey = GlobalKey<FormState>();
  final _incomeController = TextEditingController();
  final _expensesController = TextEditingController();
  final _savingsController = TextEditingController();

  @override
  void dispose() {
    _incomeController.dispose();
    _expensesController.dispose();
    _savingsController.dispose();
    super.dispose();
  }

  void cek() {
    String income = _incomeController.text;
    String expenses = _expensesController.text;
    String savings = _savingsController.text;

    if (int.parse(income) >= int.parse(expenses) + int.parse(savings)) {
      _formKey.currentState.save();
      Navigator.push(context, MaterialPageRoute(builder: (context)=>BalancePage()));
    } else {
      setState(() {
        _validate = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: kPading,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TitlePage('Big Note'),
          Expanded(
            child: Form(
              key: _formKey,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  TxtField(
                    controler: _incomeController,
                    label: 'Income',
                  ),
                  TxtField(
                    controler: _expensesController,
                    label: 'Expenses',
                    error: _validate
                        ? 'Expenses + Savings Are More Than Income'
                        : null,
                  ),
                  TxtField(
                    controler: _savingsController,
                    label: 'Savings',
                    error: _validate
                        ? 'Expenses + Savings Are More Than Income'
                        : null,
                  ),
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 12.0),
                    child: FlatButton(
                      padding: EdgeInsets.symmetric(vertical: 14.0),
                      onPressed: cek,
                      child: Text(
                        'WRITE THAT',
                        style: TextStyle(letterSpacing: 1.25),
                      ),
                      color: Colors.yellow,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(30.0),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          Container(
            width: 250.0,
            child: Text(
              '*if you get another income for this mounth, input the income again.',
              style: TextStyle(fontSize: 12.0),
            ),
          ),
        ],
      ),
    );
  }
}

class TxtField extends StatelessWidget {
  TxtField({this.label, this.controler, this.error});

  final String label;
  final TextEditingController controler;
  final String error;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 12.0),
      child: TextFormField(
        controller: controler,
        keyboardType: TextInputType.numberWithOptions(decimal: true),
        decoration: InputDecoration(
          errorText: error,
          labelText: label,
          prefix: Container(
            padding: EdgeInsets.all(8.0),
            child: Text(
              'IDR',
              style:
                  TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
            ),
          ),
        ),
      ),
    );
  }
}

我的第三屏

import 'package:flutter/material.dart';
import 'package:kakeiboo/constant.dart';

class BalancePage extends StatefulWidget {
  @override
  _BalancePageState createState() => _BalancePageState();
}

class _BalancePageState extends State<BalancePage> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: kPading,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TitlePage('Balance'),
          Expanded(
            child: Padding(
              padding: EdgeInsets.only(top: 24.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Container(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'Savings',
                          style: TextStyle(fontSize: 24.0),
                        ),
                        Row(
                          textBaseline: TextBaseline.alphabetic,
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.baseline,
                          children: [
                            Text('IDR'),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text(
                                '5.000.000',
                                style: TextStyle(
                                    fontSize: 56.0, color: Colors.green),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                  Container(
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(10.0),
                    ),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'Budget',
                          style: TextStyle(fontSize: 24.0),
                        ),
                        Row(
                          textBaseline: TextBaseline.alphabetic,
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.baseline,
                          children: [
                            Text('IDR'),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text(
                                '5.000.000',
                                style: TextStyle(
                                    fontSize: 56.0, color: Colors.red),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          )
        ],
      ),
    );
  }
}

我的第一个屏幕外观 我的第三个屏幕外观

标签: flutter

解决方案


因为您已经在使用 Provider,我建议您使用 PageController 而不是您的类 Index(),这是因为它的作用完全相同,但 PageController 具有其他一些优点(如控制 PageView,并且它已经存在以避免更多样板换页时)

//Your Savings model
class MySavings{
  int savings = 0;
  int income = 0;
  int expenses = 0;

}

import 'package:flutter/material.dart';
import 'package:kakeiboo/View/balance_screen.dart';
import 'package:kakeiboo/View/bignote_screen.dart';
import 'package:kakeiboo/View/daily_screen.dart';
import 'package:provider/provider.dart';
import 'package:kakeiboo/controller/notifier.dart';
import 'package:kakeiboo/constant.dart';
//import your Savings model

class BottomNavigate extends StatefulWidget {
  @override
  _BottomNavigateState createState() => _BottomNavigateState();
}

class _BottomNavigateState extends State<BottomNavigate> {

PageController _pageController;

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

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

  @override
  Widget build(BuildContext context) {
    var provider = Provider.of<Index>(context);

    return MultiProvider(
      providers: [
        ChangeNotifierProvider<PageController>.value(value: _pageController), //now the PageController can be seen as any other Provider
        Provider<MySavings>(create: (_) => MySavings())
      ],
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        body: PageView(
          controller: _pageController,
          physics: NeverScrollableScrollPhysics(), //So the user doesn't scroll and move only when you pressed the buttons
          children: <Widget>[
            BigNotePage(),
            DailyExpensesPage(),
            BalancePage(),
          ],
        ),
        bottomNavigationBar: MyBottomBar()
     )
   );
  }
}

class MyBottomBar extends StatlessWidget{

  @override
  Widget build(BuildContext context){
    final PageController pageController = Provider.of<PageController>(context, listen: false);
    final int index = context.select<PageController, int>((pageController) => pageController.hasClients ? pageController.page.round() : pageController.initialPage);// the index the pageController currently is (if there is no client attached it uses the initialPAge that defaults to index 0)
    return BottomNavigationBar(
            onTap: (index) {
              pageController.jumpToPage(index);
              //In case you want it animated uncomment the next line and comment jumpToPage()
              //pageController.animateToPage(index, duration: const Duration(milliseconds: 300), curve: Curves.ease);
            },
            currentIndex: index,
            backgroundColor: Color(0xff2196f3),
            showUnselectedLabels: false,
            selectedItemColor: Color(0xffffffff),
            type: BottomNavigationBarType.fixed,
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.book),
                title: Text(
                  'Big Note',
                  style: kBottomNavigateStyle,
                ),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.receipt),
                title: Text(
                  'Daily',
                  style: kBottomNavigateStyle,
                ),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.account_balance_wallet),
                title: Text(
                  'Balance',
                  style: kBottomNavigateStyle,
                ),
              ),
            ],
          ),
         );
  }
}

现在在屏幕 1

import 'package:flutter/material.dart';
import 'package:kakeiboo/View/balance_screen.dart';
import 'package:kakeiboo/constant.dart';
//import your Savings model

class BigNotePage extends StatefulWidget {
  @override
  _BigNotePageState createState() => _BigNotePageState();
}

class _BigNotePageState extends State<BigNotePage> {
  bool _validate = false;
  final _formKey = GlobalKey<FormState>();
  final _incomeController = TextEditingController();
  final _expensesController = TextEditingController();
  final _savingsController = TextEditingController();

  @override
  void dispose() {
    _incomeController.dispose();
    _expensesController.dispose();
    _savingsController.dispose();
    super.dispose();
  }

  void cek() {
    String income = _incomeController.text;
    String expenses = _expensesController.text;
    String savings = _savingsController.text;

    if (int.parse(income) >= int.parse(expenses) + int.parse(savings)) {
      final PageController pageController = Provider.of<PageController>(context, listen: false);
      final MySavings mySavings = Provider.of<MySavings>(context, listen: false);
      mySavings..income = int.parse(income)..expenses = int.parse(expenses)..savings= int.parse(savings);
      _formKey.currentState.save();
      pageController.jumpToPage(2); //Index 2 is BalancePage
      //In case you want it animated uncomment the next line and comment jumpToPage()
      //pageController.animateToPage(2, duration: const Duration(milliseconds: 300), curve: Curves.ease);
    } else {
      setState(() {
        _validate = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: kPading,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TitlePage('Big Note'),
          Expanded(
            child: Form(
              key: _formKey,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  TxtField(
                    controler: _incomeController,
                    label: 'Income',
                  ),
                  TxtField(
                    controler: _expensesController,
                    label: 'Expenses',
                    error: _validate
                        ? 'Expenses + Savings Are More Than Income'
                        : null,
                  ),
                  TxtField(
                    controler: _savingsController,
                    label: 'Savings',
                    error: _validate
                        ? 'Expenses + Savings Are More Than Income'
                        : null,
                  ),
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 12.0),
                    child: FlatButton(
                      padding: EdgeInsets.symmetric(vertical: 14.0),
                      onPressed: cek,
                      child: Text(
                        'WRITE THAT',
                        style: TextStyle(letterSpacing: 1.25),
                      ),
                      color: Colors.yellow,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(30.0),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          Container(
            width: 250.0,
            child: Text(
              '*if you get another income for this mounth, input the income again.',
              style: TextStyle(fontSize: 12.0),
            ),
          ),
        ],
      ),
    );
  }
}

class TxtField extends StatelessWidget {
  TxtField({this.label, this.controler, this.error});

  final String label;
  final TextEditingController controler;
  final String error;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 12.0),
      child: TextFormField(
        controller: controler,
        keyboardType: TextInputType.numberWithOptions(decimal: true),
        decoration: InputDecoration(
          errorText: error,
          labelText: label,
          prefix: Container(
            padding: EdgeInsets.all(8.0),
            child: Text(
              'IDR',
              style:
                  TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
            ),
          ),
        ),
      ),
    );
  }
}

最后在屏幕 3 中,您只需调用

final MySavings mysavings = Provider.of<MySavings>(context, listen: false);

并使用其值(储蓄、支出和收入)显示在每个文本中,如果您愿意,请进行一些数学运算或更改其值(如果您想在更改它们后立即更新,则将 MySavings 设置为 ChangeNotifier)。

如果您不想使用 PageView 并坚持使用 Index 类,只需检查逻辑并使用您的索引提供程序更改所有 PageController,它应该可以正常工作


推荐阅读