如何在应用启动时初始化变量?

时间:2019-11-29 00:59:07

标签: flutter dart

我在使用flutter启动应用程序时初始化变量时遇到问题。我有一个名为SizeConfig的类,我想初始化这些变量并将其输入到自定义AppBar中,但是,一旦我启动该应用程序,这就是我得到的。

Image of what I get on app startup

点击选项卡按钮之一后,它将获取所有变量并修复应用栏,如下所示。

After tapping on one of the items

我希望该应用程序首先初始化所有内容,并在绘制导航栏之前设置变量,以使其看起来像第二张图像。

main.dart

import 'package:SportsLink/SizeConfig.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:SportsLink/Home.dart';
import 'package:SportsLink/Maps.dart';
import 'package:SportsLink/Clubs.dart';
import 'package:SportsLink/SearchPage.dart';
import 'package:SportsLink/Profile.dart';
import 'my_flutter_app_icons.dart';
import 'BottomAppBarCustom/src/BottomAppBarCustom.dart';

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

class myApp extends StatefulWidget {
  myAppState createState() => myAppState();
}

class myAppState extends State<myApp> {

  final PageStorageBucket bucket = PageStorageBucket();


  int _currentIndex = 0;
  Widget callPage(int currentIndex) {
    switch (currentIndex) {
      case 0: return new Home();
      case 1: return new Maps();
      case 2: return new SearchPage();
      case 3: return new Clubs();
      case 4: return new Profile();
    }
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("Initiation!");
    SizeConfig().init(context);
    print("End");

  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "SportsLink",
      theme: ThemeData(fontFamily: 'OpenSans'),
      home: Builder(
        builder: (context) => Scaffold(
        appBar: AppBar(
          title: Text('SportsLink'),
        ),
        body: PageStorage(
            child: callPage(_currentIndex),
          bucket: bucket,
        ),
        bottomNavigationBar: BottomAppBarCustom(
          selectedIndex: _currentIndex,
          onIndexChanged: (current) {
            setState(() {
              _currentIndex = current;
            });
          },
        ),
      ),
    ),
    );
  }
}

AnimatedBottomNavigationBar.dart

import 'package:SportsLink/Clubs.dart';
import 'package:SportsLink/Home.dart';
import 'package:SportsLink/Maps.dart';
import 'package:SportsLink/Profile.dart';
import 'package:flutter/material.dart';
import 'package:SportsLink/SizeConfig.dart';

class AnimatedBottomNavigationBar extends StatefulWidget {

  final List<BarItem> barItems;
  final Duration animationDuration;
  final Function onTabTap;




  AnimatedBottomNavigationBar({this.barItems, this.animationDuration = const Duration(milliseconds: 500), this.onTabTap});

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

class _AnimatedBottomNavigationBarState extends State<AnimatedBottomNavigationBar> with TickerProviderStateMixin{

  double bottomPadding = SizeConfig.blockSizeHorizontal*6;
  double leftPadding = SizeConfig.blockSizeHorizontal * 4;

  int _selectedIndex = 0;


  @override
  Widget build(BuildContext context) {
    return Material(
      elevation: 10.0,
      child: InkWell(
        splashColor: Colors.transparent,
        onTap: () {
          setState(() {

          });
        },
        child: Padding(
          padding: EdgeInsets.only(bottom: SizeConfig.blockSizeHorizontal*5, left:SizeConfig.blockSizeHorizontal*2.5, top: SizeConfig.blockSizeHorizontal*5, right: 8.0),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: _buildBarItems(),
          ),
        ),
      ),
    );
  }

  List<Widget> _buildBarItems() {
    List<Widget> _barItems = List();
    for (int i = 0;i<widget.barItems.length;i++) {
      BarItem item = widget.barItems[i];
      bool isSelected = _selectedIndex == i;
      _barItems.add(InkWell(
        splashColor: Colors.transparent,
        onTap: () {
          setState(() {
            _selectedIndex = i;
            widget.onTabTap(_selectedIndex);
          });
        },
        child: AnimatedContainer(
          padding: EdgeInsets.only(right: SizeConfig.blockSizeHorizontal*3.5, top: 8.0, bottom: 8.0, left: SizeConfig.blockSizeHorizontal*3.5),
          duration: widget.animationDuration,
          decoration: BoxDecoration(
            color: isSelected ? item.color.withOpacity(0.15) : Colors.transparent,
            borderRadius: BorderRadius.all(Radius.circular(30.0)),
          ),
          child: Row(
            children: <Widget>[
              Icon(item.icon,
                color: isSelected ? item.color : Colors.black,
              size: 28.0,),
              SizedBox(
                width: 5.0,
              ),
              AnimatedSize(
                duration: widget.animationDuration,
                curve: Curves.easeInOut,
                vsync: this,
                child: Text(
                    isSelected ? item.text : "",
                  style: TextStyle(color: item.color, fontWeight: FontWeight.w600),
                ),
              ),
            ],
          ),
        ),
      ));
    }
    return _barItems;
  }
}


class BarItem {
  String text;
  IconData icon;
  Color color;

  BarItem({this.text, this.icon, this.color});
}

SizeConfig.dart

import 'package:geolocator/geolocator.dart';

class SizeConfig {
  static MediaQueryData _mediaQueryData;
  static double screenWidth;
  static double screenHeight;
  static double blockSizeHorizontal;
  static double blockSizeVertical;
  static double _safeAreaHorizontal;
  static double _safeAreaVertical;
  static double safeBlockHorizontal;
  static double safeBlockVertical;
  static Map<String, double> userLocation;
  static Position position;

  void init(BuildContext context) async {
    _mediaQueryData = MediaQuery.of(context);
    screenWidth = _mediaQueryData.size.width;
    screenHeight = _mediaQueryData.size.height;
    blockSizeHorizontal = screenWidth/100;
    blockSizeVertical = screenHeight/100;
    _safeAreaHorizontal = _mediaQueryData.padding.left +
        _mediaQueryData.padding.right;
    _safeAreaVertical = _mediaQueryData.padding.top +
        _mediaQueryData.padding.bottom;
    safeBlockHorizontal = (screenWidth - _safeAreaHorizontal)/100;
    safeBlockVertical = (screenHeight - _safeAreaVertical)/100;
    getCurrentLocation();

  }

  void getCurrentLocation() async {
    Position res = await Geolocator().getCurrentPosition();
    position = res;
  }
}

BottomAppBarCustom.dart

import 'package:flutter/material.dart';
import 'package:SportsLink/BottomAppBarCustom/src/AnimatedBottomNavigationBar.dart';


class BottomAppBarCustom extends StatefulWidget {

  final ValueChanged<int> onIndexChanged;
  final int selectedIndex;

  final List<BarItem> barItems = [
    BarItem(
      text: "Home",
      icon: Icons.home,
        color: Colors.teal
    ),
    BarItem(
      text: "Maps",
      icon: Icons.map,
        color: Colors.teal
    ),
    BarItem(
        text: "Search",
        icon: Icons.search,
        color: Colors.teal
    ),
    BarItem(
      text: "Clubs",
      icon: Icons.assignment_ind,
        color: Colors.teal
    ),
    BarItem(
      text: "Profile",
      icon: Icons.person,
        color: Colors.teal
    ),

  ];

  BottomAppBarCustom({
    @required this.onIndexChanged,
    @required this.selectedIndex,
  });

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



class _BottomAppBarCustomState extends State<BottomAppBarCustom> {


  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return AnimatedBottomNavigationBar(
        barItems: widget.barItems,
        animationDuration: const Duration(milliseconds: 250),
        onTabTap: (index) {
          _selectedIndex = index;
          widget.onIndexChanged(index);
        }
    );
  }
}

2 个答案:

答案 0 :(得分:2)

这样更改您的 AnimatedBottomNavigationBar.dart

import 'package:flutter/material.dart';

import 'SizeConfig.dart';

class AnimatedBottomNavigationBar extends StatefulWidget {
  final List<BarItem> barItems;
  final Duration animationDuration;
  final Function onTabTap;

  AnimatedBottomNavigationBar(
      {this.barItems,
      this.animationDuration = const Duration(milliseconds: 500),
      this.onTabTap});

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

class _AnimatedBottomNavigationBarState
    extends State<AnimatedBottomNavigationBar> with TickerProviderStateMixin {
  double bottomPadding;
  double leftPadding;

  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    SizeConfig1().init(context);
    bottomPadding = SizeConfig1.blockSizeHorizontal * 6;
    leftPadding = SizeConfig1.blockSizeHorizontal * 4;
    return Material(
      elevation: 10.0,
      child: InkWell(
        splashColor: Colors.transparent,
        onTap: () {
          setState(() {});
        },
        child: Padding(
          padding: EdgeInsets.only(
              bottom: SizeConfig1.blockSizeHorizontal * 5,
              left: SizeConfig1.blockSizeHorizontal * 2.5,
              top: SizeConfig1.blockSizeHorizontal * 5,
              right: 8.0),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: _buildBarItems(),
          ),
        ),
      ),
    );
  }

  List<Widget> _buildBarItems() {
    List<Widget> _barItems = List();
    for (int i = 0; i < widget.barItems.length; i++) {
      BarItem item = widget.barItems[i];
      bool isSelected = _selectedIndex == i;
      _barItems.add(InkWell(
        splashColor: Colors.transparent,
        onTap: () {
          setState(() {
            _selectedIndex = i;
            widget.onTabTap(_selectedIndex);
          });
        },
        child: AnimatedContainer(
          padding: EdgeInsets.only(
              right: SizeConfig1.blockSizeHorizontal * 3.5,
              top: 8.0,
              bottom: 8.0,
              left: SizeConfig1.blockSizeHorizontal * 3.5),
          duration: widget.animationDuration,
          decoration: BoxDecoration(
            color:
                isSelected ? item.color.withOpacity(0.15) : Colors.transparent,
            borderRadius: BorderRadius.all(Radius.circular(30.0)),
          ),
          child: Row(
            children: <Widget>[
              Icon(
                item.icon,
                color: isSelected ? item.color : Colors.black,
                size: 28.0,
              ),
              SizedBox(
                width: 5.0,
              ),
              AnimatedSize(
                duration: widget.animationDuration,
                curve: Curves.easeInOut,
                vsync: this,
                child: Text(
                  isSelected ? item.text : "",
                  style:
                      TextStyle(color: item.color, fontWeight: FontWeight.w600),
                ),
              ),
            ],
          ),
        ),
      ));
    }
    return _barItems;
  }
}

class BarItem {
  String text;
  IconData icon;
  Color color;

  BarItem({this.text, this.icon, this.color});
}

答案 1 :(得分:0)

首先,正确指定异步方法的返回类型:

  // Async functions always return Future
  Future<void> init(BuildContext context) async {
    ...
    // Awaiting for resolving
    await getCurrentLocation();
  }

  // Async functions always return Future
  Future<void> getCurrentLocation() async {
    ...

在初始化值后,通过调用setState来重建窗口小部件:

SizeConfig().init(context).then((_) => setState(() {}));