具有BLoC模式的BottomNavigationBar

时间:2018-10-26 16:34:34

标签: flutter

我真的很喜欢BLoC模式,并且我试图理解它。但是我似乎无法弄清楚该如何与BottomNavigationBar一起使用。

制作导航页面列表并在导航栏上点击事件设置当前索引会导致整个应用程序因setState()而重绘。

我可以使用Navigator来显示单击的导航页面而不丢失导航栏吗?

有人用BottomNavigationBar使用BLoC模式吗?我该怎么做呢 ?我很想看看示例代码。

1 个答案:

答案 0 :(得分:3)

我终于明白了。我将整个代码放在这里以帮助其他人。

首先阅读Didier boelens撰写的精彩文章:https://www.didierboelens.com/2018/08/reactive-programming---streams---bloc/

使用他的集团供应商和基础集团创建集团。我的是这样的:

import 'dart:async';
import 'bloc_provider.dart';
import 'package:rxdart/rxdart.dart';

class NewsfeedBloc implements BlocBase {
  BehaviorSubject<int> _ctrl = new BehaviorSubject<int>();

  NewsfeedBloc(
      // listen _ctrl event and do other business logic
  );

  void dispose() {
    _ctrl.close();
  }
}

然后创建将使用集团的页面:

import 'package:flutter/material.dart';
import '../blocs/newsfeed_bloc.dart';
import '../blocs/bloc_provider.dart';

class NewsfeedPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final NewsfeedBloc bloc = BlocProvider.of<NewsfeedBloc>(context);
    // here you should use a stream builder or such to build the ui
    return Container(
      child: Card(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            const ListTile(
              leading: Icon(Icons.album),
              title: Text('The Enchanted Nightingale'),
              subtitle: Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
            ),
            ButtonTheme.bar(
              // make buttons use the appropriate styles for cards
              child: ButtonBar(
                children: <Widget>[
                  FlatButton(
                    child: const Text('BUY TICKETS'),
                    onPressed: () {/* do something with the bloc */},
                  ),
                  FlatButton(
                    child: const Text('LISTEN'),
                    onPressed: () {/* do something with the bloc */},
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

最后是main.dart文件,其中包含Navigationbottombar和抽屉:

import 'dart:async';
import 'package:flutter/material.dart';

import 'blocs/bloc_provider.dart';
import 'blocs/application_bloc.dart';
import 'blocs/newsfeed_bloc.dart';
import 'blocs/tracking_bloc.dart';
import 'blocs/notifications_bloc.dart';
import 'blocs/item1_bloc.dart';
import 'blocs/item2_bloc.dart';

import 'pages/newsfeed.dart';
import 'pages/tracking.dart';
import 'pages/notifications.dart';
import 'pages/item1.dart';
import 'pages/item2.dart';

Future<void> main() async {
  return runApp(BlocProvider<ApplicationBloc>(
    bloc: ApplicationBloc(),
    child: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // define your blocs here so that you dont lose the state when your app rebuilds for some reason. thanks boformer for pointing that out.
  NewsfeedBloc _newsfeedBloc;

  PageController _pageController;
  var _page = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Movies',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new Scaffold(
        appBar: AppBar(
          title: new Text('App Title'),
        ),
        body: PageView(
          children: <Widget>[
            BlocProvider<NewsfeedBloc>(
              bloc: _newsfeedBloc(),
              child: NewsfeedPage(),
            ),
            // ...
          ],
          controller: _pageController,
          onPageChanged: onPageChanged,
        ),
        bottomNavigationBar: BottomNavigationBar(
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.timeline),
              title: Text("Timeline"),
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.art_track),
              title: Text("Some Page"),
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.notifications),
              title: Text("Notifications"),
            ),
          ],
          onTap: navigationTapped,
          currentIndex: _page,
        ),
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text('Settings'),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              ListTile(
                title: Text('Item 1'),
                onTap: () {
                    Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) { 
                        return BlocProvider<Item1Bloc>(
                            bloc: Item1Bloc(),
                            child: Item1Page(),
                        );
                    }
                },
              ),
              ListTile(
                title: Text('Item 2'),
                onTap: () {
                    Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) { 
                        return BlocProvider<Item2Bloc>(
                            bloc: Item2Bloc(),
                            child: Item2Page(),
                        );
                    }
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  void navigationTapped(int page) {
    _pageController.animateToPage(
      page,
      duration: Duration(milliseconds: 300),
      curve: Curves.easeIn,
    );
  }

  void onPageChanged(int page) {
    setState(() {
      this._page = page;
    });
  }

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

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