微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Flutter中从另一个页面调用选项卡控制器

如何解决如何在Flutter中从另一个页面调用选项卡控制器

我有带有4个选项卡的底部导航栏,并且都可以正常工作,但是我还有一个类名为BannerImageItem,我想从那里调用选项卡2。我尝试使用Gloabal键,但从Tab控制器获取null时请帮助我,我被卡住了。

我有带有4个选项卡的底部导航栏,并且都可以正常工作,但是我还有一个类名为BannerImageItem,我想从那里调用选项卡2。我尝试使用Gloabal键,但是从Tab控制器获取null时请帮助我,我被卡住了。

const int tabCount = 3;
const int turnsToRotateRight = 1;
const int turnsToRotateLeft = 3;

class MainTabControlDelegate {
  int index;
  Function(String naMetab) changeTab;
  Function(int index) tabAnimateto;

  static MainTabControlDelegate _instance;
  static MainTabControlDelegate getInstance() {
    return _instance ??= MainTabControlDelegate._();
  }

  MainTabControlDelegate._();
}

class MainTabs extends StatefulWidget {
  MainTabs({Key key}) : super(key: key);

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

class MainTabsstate extends State<MainTabs>
    with
        WidgetsBindingObserver,SingleTickerProviderStateMixin,AfterLayoutMixin {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  final PageStorageBucket bucket = PageStorageBucket();

  final StreamController<String> _controllerRouteWeb =
      StreamController<String>.broadcast();

  final _auth = FirebaseAuth.instance;
  var tabData;
  Map saveIndexTab = Map();

  FirebaseUser loggedInUser;
  bool isAdmin = false;

  final List<Widget> _tabView = [];
  TabController tabController;

  @override
  void afterFirstLayout(BuildContext context) {
    loadTabBar(context);
  }

  Widget tabView(Map<String,dynamic> data) {
    switch (data['layout']) {
      case 'category':
        return CategoriesScreen(
          key: Key("category"),layout: data['categoryLayout'],categories: data['categories'],images: data['images'],showChat: data['showChat'],);
      case 'search':
        return SearchScreen(key: Key("search"),showChat: data['showChat']);
      case 'cart':
        return CartScreen(showChat: data['showChat']);
      case 'profile':
        return UserScreen(
            settings: data['settings'],background: data['background'],showChat: data['showChat']);
      case 'blog':
        return HorizontalSliderList(config: data);
      case 'wishlist':
        return screen.WishList(canPop: false,showChat: data['showChat']);
      case 'page':
        return WebViewScreen(
            title: data['title'],url: data['url'],showChat: data['showChat']);
      case 'html':
        return StaticSite(data: data['data'],showChat: data['showChat']);
      case 'static':
        return StaticPage(data: data['data'],showChat: data['showChat']);
      case 'postScreen':
        return PostScreen(
            pageId: data['pageId'],pageTitle: data['pageTitle'],isLocatedInTabbar: true,showChat: data['showChat']);
      case 'dynamic':
      default:
        return HomeScreen();
    }
  }

  void changeTab(String naMetab) {
    if (kLayoutWeb) {
      _controllerRouteWeb.sink
          .add(naMetab.contains("/") ? naMetab : '/$naMetab');
    } else {
      tabController?.animateto(saveIndexTab[naMetab] ?? 0);
    }
  }

  void loadTabBar(context) {
    tabData = Provider.of<AppModel>(context,listen: false).appConfig['TabBar']
        as List;

    for (var i = 0; i < tabData.length; i++) {
      Map<String,dynamic> _dataOfTab = Map.from(tabData[i]);

      saveIndexTab[_dataOfTab['layout']] = i;
      _tabView.add(tabView(_dataOfTab));
    }

    setState(() {
      tabController = TabController(length: _tabView.length,vsync: this);
    });

    if (MainTabControlDelegate.getInstance().index != null) {
      tabController.animateto(MainTabControlDelegate.getInstance().index);
    } else {
      MainTabControlDelegate.getInstance().index = 0;
    }

    // Load the Design from FluxBuilder
    tabController.addListener(() {
      eventBus.fire('tab_${tabController.index}');
      if (_tabView[tabController.index] is SearchScreen) {
        eventBus.fire(UpdateSearchFilterEvent());
      }
      MainTabControlDelegate.getInstance().index = tabController.index;
    });
  }

  Future<void> getCurrentUser() async {
    try {
      //Provider.of<usermodel>(context).getUser();
      final user = await _auth.currentUser();
      if (user != null) {
        setState(() {
          loggedInUser = user;
        });
      }
    } catch (e) {
      printLog("[tabbar] getCurrentUser error ${e.toString()}");
    }
  }

  bool checkIsAdmin() {
    if (loggedInUser.email == adminemail) {
      isAdmin = true;
    } else {
      isAdmin = false;
    }
    return isAdmin;
  }

  @override
  void initState() {
    if (!kIsWeb) {
      getCurrentUser();
    }
    MainTabControlDelegate.getInstance().changeTab = changeTab;
    MainTabControlDelegate.getInstance().tabAnimateto = (int index) {
      tabController?.animateto(index);
    };
    super.initState();

    WidgetsBinding.instance.addobserver(this);
  }

  @override
  void dispose() {
    tabController?.dispose();
    _controllerRouteWeb?.close();
    WidgetsBinding.instance.removeObserver(this);

    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.paused) {
      // went to Background
    }
    if (state == AppLifecycleState.resumed) {
      // came back to Foreground
      final appModel = Provider.of<AppModel>(context,listen: false);
      if (appModel.deeplink?.isNotEmpty ?? false) {
        if (appModel.deeplink['screen'] == 'NotificationScreen') {
          appModel.deeplink = null;
          Navigator.push(
            context,MaterialPageRoute(builder: (context) => NotificationScreen()),);
        }
      }
    }

    super.didChangeAppLifecycleState(state);
  }

  @override
  Widget build(BuildContext context) {
    printLog('[tabbar] ============== tabbar.dart DASHBOARD ==============');
    final isDesktop = isdisplayDesktop(context);
    Utils.setStatusBarWhiteForeground(false);
    kLayoutWeb = (kIsWeb || isDesktop);

    if (_tabView.isEmpty) {
      return Container(
        color: Colors.white,child: kLoadingWidget(context),);
    }

    return renderBody(context);
  }

  Widget renderBody(BuildContext context) {
    final ThemeData theme = Theme.of(context);

    if (kLayoutWeb) {
      final isDesktop = isdisplayDesktop(context);

      return Scaffold(
        backgroundColor: Theme.of(context).backgroundColor,body: SafeArea(
          // For desktop layout we do not want to have SafeArea at the top and
          // bottom to display 100% height content on the accounts view.
          top: !isDesktop,bottom: !isDesktop,child: Theme(
              // This theme effectively removes the default visual touch
              // Feedback for tapping a tab,which is replaced with a custom
              // animation.
              data: theme.copyWith(
                splashColor: Colors.transparent,highlightColor: Colors.transparent,),child: LayoutWebCustom(
                menu: MenuBar(controllerRouteWeb: _controllerRouteWeb),content: StreamBuilder<String>(
                  initialData: RouteList.homeScreen,stream: _controllerRouteWeb.stream,builder: (context,snapshot) {
                    return Navigator(
                      key: Key(snapshot.data),initialRoute: snapshot.data,onGenerateRoute: (RouteSettings settings) {
                        return MaterialPageRoute(
                          builder: Routes.getRouteByName(settings.name),settings: settings,maintainState: false,fullscreenDialog: true,);
                      },);
                  },)),);
    } else {
      final screenSize = MediaQuery.of(context).size;
      return Container(
        color: Theme.of(context).backgroundColor,child: Scaffold(
          backgroundColor: Theme.of(context).backgroundColor,resizetoAvoidBottomPadding: false,key: _scaffoldKey,body: WillPopScope(
            onWillPop: () async {
              if (tabController.index != 0) {
                tabController.animateto(0);
                return false;
              } else {
                return showDialog(
                      context: context,builder: (context) => AlertDialog(
                        title: Text(S.of(context).areYouSure),content: Text(S.of(context).doYouWantToExitApp),actions: <Widget>[
                          FlatButton(
                            onpressed: () => Navigator.of(context).pop(false),child: Text(S.of(context).no),FlatButton(
                            onpressed: () => Navigator.of(context).pop(true),child: Text(S.of(context).yes),],) ??
                    false;
              }
            },child: TabBarView(
              controller: tabController,physics: NeverScrollableScrollPhysics(),children: _tabView,drawer: Drawer(child: MenuBar()),bottomNavigationBar: SafeArea(
            top: false,child: Container(
              width: screenSize.width,child: FittedBox(
                child: Container(
                  width: screenSize.width /
                      (2 / (screenSize.height / screenSize.width)),child: TabBar(
                    controller: tabController,tabs: renderTabbar(),isScrollable: false,labelColor: Theme.of(context).primaryColor,indicatorSize: TabBarIndicatorSize.label,indicatorPadding: EdgeInsets.all(4.0),indicatorColor: Theme.of(context).primaryColor,);
    }
  }

  List<Widget> renderTabbar() {
    final isTablet = Tools.isTablet(MediaQuery.of(context));
    var totalCart = Provider.of<CartModel>(context).totalCartQuantity;
    final tabData = Provider.of<AppModel>(context,listen: false)
        .appConfig['TabBar'] as List;

    List<Widget> list = [];

    tabData.forEach((item) {
      var icon = !item["icon"].contains('/')
          ? Icon(
              feathericons[item["icon"]],color: Theme.of(context).accentColor,size: 22,)
          : (item["icon"].contains('http')
              ? Image.network(
                  item["icon"],width: 24,)
              : Image.asset(
                  item["icon"],));

      if (item["layout"] == "cart") {
        icon = Stack(
          children: <Widget>[
            Container(
              width: 30,height: 25,padding: const EdgeInsets.only(right: 6.0,top: 4),child: icon,if (totalCart > 0)
              Positioned(
                right: 0,top: 0,child: Container(
                  padding: const EdgeInsets.all(1),decoration: Boxdecoration(
                    color: Colors.red,borderRadius: BorderRadius.circular(8),constraints: BoxConstraints(
                    minWidth: 16,minHeight: 16,child: Text(
                    totalCart.toString(),style: TextStyle(
                      color: Colors.white,fontSize: isTablet ? 14 : 12,textAlign: TextAlign.center,)
          ],);
      }

      if (item["label"] != null) {
        list.add(Tab(icon: icon,text: item["label"]));
      } else {
        list.add(Tab(icon: icon));
      }
    });

    return list;
  }
}

这是BannerImageItem

/// The Banner type to display the image
class BannerImageItem extends StatefulWidget {
  @override
  final Key key;
  final dynamic config;
  final double width;
  final double padding;
  final BoxFit BoxFit;
  final double radius;

  BannerImageItem({
    this.key,this.config,this.padding,this.width,this.BoxFit,this.radius,}) : super(key: key);

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

class _BannerImageItemState extends State<BannerImageItem>
    with AfterLayoutMixin {
  List<Product> _products;

  GlobalKey<MainTabsstate> _scaffoldKey = GlobalKey<MainTabsstate>();

  @override
  void afterFirstLayout(BuildContext context) {
    /// for pre-load the list product
    if (widget.config['data'] != null) {
      print(widget.config['data']);
      _products = widget.config['data'];
    }
  }

  @override
  Widget build(BuildContext context) {
    double _padding =
        Tools.formatDouble(widget.config["padding"] ?? widget.padding ?? 10.0);
    double _radius = Tools.formatDouble(widget.config['radius'] ??
        (widget.radius != null ? widget.radius : 0.0));

    final screenSize = MediaQuery.of(context).size;
    final screenWidth =
        screenSize.width / (2 / (screenSize.height / screenSize.width));
    final itemWidth = widget.width ?? screenWidth;

    return GestureDetector(key: _scaffoldKey,onTap: () { _scaffoldKey.currentState.tabController.animateto(1);
      },child: Container(
        width: itemWidth,child: Padding(
          padding: EdgeInsets.only(left: _padding,right: _padding),child: ClipRRect(
            borderRadius: BorderRadius.circular(_radius),child: Tools.image(
              fit: widget.BoxFit ?? BoxFit.fitWidth,url: widget.config["image"],);
  }
}

解决方法

return GestureDetector(key: _scaffoldKey,onTap: () { _scaffoldKey.currentState.tabController.animateTo(1);
      },child: Container(
        width: itemWidth,child: Padding(
          padding: EdgeInsets.only(left: _padding,right: _padding),child: ClipRRect(
            borderRadius: BorderRadius.circular(_radius),child: Tools.image(
              fit: widget.boxFit ?? BoxFit.fitWidth,url: widget.config["image"],),);

替换为

return GestureDetector(
      onTap: () { MainTabControlDelegate.getInstance().tabAnimateTo(1);
      },);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。