美文网首页
Flutter Go 源码分析(五)

Flutter Go 源码分析(五)

作者: Hedgehog___ | 来源:发表于2019-06-10 10:12 被阅读0次
    - (7)CollectionPage--组件收藏页面

    CollectionPage页面相对比较简单,就一个列表页面,开始吧。
    初始化方法:

    _CollectionPageState() {
        final eventBus = new EventBus();
        ApplicationEvent.event = eventBus;
      }
      CollectionControlModel _collectionControl = new CollectionControlModel();
      List<Collection> _collectionList = [];
      ScrollController _scrollController = new ScrollController();
      var _icons;
    
      @override
      void initState() {
        super.initState();
        _getList();
        ApplicationEvent.event.on<CollectionEvent>().listen((event) {//订阅
          _getList();
        });
      }
    
    1. ApplicationEvent
      ApplicationEvent是通过event_bus三方进行组件间事件传递的工具。event_bus这个库大家有兴趣可以自行去了解。
      订阅:
    ApplicationEvent.event.on<CollectionEvent>().listen((event) {//订阅
          _getList();
        });
    

    发送通知:

    ApplicationEvent.event
                    .fire(CollectionEvent(widget.title, _router, true));
    
    1. CollectionControlModel
      CollectionControlModel负责收藏数据的存取,和上面的CatControlModel差不多:
    final String table = 'collection';
      Sql sql;
    
      CollectionControlModel() {//set 表名
        sql = Sql.setTable(table);
      }
    
      // 获取所有的收藏
    
      // 插入新收藏
      Future insert(Collection collection) {
        var result =
            sql.insert({'name': collection.name, 'router': collection.router});
        return result;
      }
    
      // 获取全部的收藏
      Future<List<Collection>> getAllCollection() async {
        List list = await sql.getByCondition();
        List<Collection> resultList = [];
        list.forEach((item){
          print(item);
          resultList.add(Collection.fromJSON(item));
        });
        return resultList;
      }
    
      // 通过收藏名获取router
      Future getRouterByName(String name) async {
        List list = await sql.getByCondition(conditions: {'name': name});
        return list;
      }
    
      // 删除
      Future deleteByName(String name) async{
        return await sql.delete(name,'name');
      }
    
    1. build函数
      build的主要内容在_renderList方法里面:
    Widget _renderList(context, index) {
        if (index == 0) {
          return Container(//头部标题
            height: 40.0,
            padding: const EdgeInsets.only(left: 10.0),
            child: Row(
              children: <Widget>[
                Icon(
                  Icons.warning,
                  size: 22.0,
                ),
                SizedBox(
                  width: 5.0,
                ),
                Text('模拟器重新运行会丢失收藏'),
              ],
            ),
          );
        }
        if (_collectionList[index - 1].router.contains('http')) {
          if (_collectionList[index - 1].name.endsWith('Doc')) {
            _icons = Icons.library_books;
          } else {
            _icons = Icons.language;
          }
        } else {
          _icons = Icons.extension;
        }
        return Container(
          padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0),
          margin: const EdgeInsets.only(bottom: 7.0),
          decoration: BoxDecoration(
            color: Colors.white,
            boxShadow: [
              new BoxShadow(
                color: const Color(0xFFd0d0d0),
                blurRadius: 1.0,
                spreadRadius: 2.0,
                offset: Offset(3.0, 2.0),
              ),
            ],
          ),
          child: ListTile(
            leading: Icon(
              _icons,
              size: 30.0,
              color: Theme.of(context).primaryColor,
            ),
            title: Text(
              Uri.decodeComponent(_collectionList[index - 1].name),
              overflow: TextOverflow.ellipsis,
              style: TextStyle(fontSize: 17.0),
            ),
            trailing:
                Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
            onTap: () {
              if (_collectionList[index - 1].router.contains('http')) {//如果是网页就直接跳转
                // 注意这里title已经转义过了
                Application.router.navigateTo(context,
                    '${Routes.webViewPage}?title=${_collectionList[index - 1].name}&url=${Uri.encodeComponent(_collectionList[index - 1].router)}');
              } else {//不是网页就跳转相应的页面
                Application.router
                    .navigateTo(context, "${_collectionList[index - 1].router}");
              }
            },
          ),
        );
      }
    
    - (8)FourthPage--第四个页面

    这个页面看似比较复杂,但是实际层级结构还是很清晰的:

    Widget build(BuildContext context) {
        return new Stack(
          children: [
            new Page(
              // page 的主要内容
              viewModel: pages[activeIndex],
              percentVisible: 1.0,
            ),
            new PageReveal(//动画page
              revealPercent: slidePercent,
              child: new Page(
                viewModel: pages[nextPageIndex],
                percentVisible: slidePercent,
              ),
            ),
            new PagerIndicator(//指示
              viewModel: new PagerIndicatorViewModel(
                pages,
                activeIndex,
                slideDirection,
                slidePercent,
              ),
            ),
            new PageDragger(//负责滑动-->手势
              canDragLeftToRight: activeIndex > 0,
              canDragRightToLeft: activeIndex < pages.length - 1,
              slideUpdateStream: this.slideUpdateStream,
            )
          ],
        );
      }
    

    代码我已经尽量添加了详细的注释,可以看到分成四个部分:Page(主要内容的显示页面activePage)、PageReveal(用于操作nextPage执行滑动动画)、PagerIndicator(滑动指示条)、PageDragger(滑动手势)

    1. Page(主要内容的显示页面)
      初始化相关:
    final PageViewModel viewModel;
      final double percentVisible;
      Page({
        this.viewModel,//页面信息
        this.percentVisible = 1.0,//滑动百分百
      });
    

    build函数

    Widget build(BuildContext context) {
        return Stack(
            //alignment: const Alignment(1.2, 0.6),
            children: [
              Container(
                  width: double.infinity,
                  /// height:MediaQuery.of(context).size.height-200.0,
                  color: viewModel.color,
                  padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
                  child: Opacity(
                    opacity: percentVisible,
                    child: ListView(
                      children: <Widget>[
                        layout(context),
                      ],
                    ),
                  )
              ),
              Positioned(//右上角GitHub 按钮
                  right: -5.0,
                  top: 2.0,
                  child: creatButton(context, 'GitHub', Icons.arrow_forward, 'goGithub')
              ),
            ]
        );
      }
    

    build函数中我们可以看到结构分为两部分,layout(主要视图)、creatButton(左上角github按钮)。

    • layout
    Column layout(BuildContext context) {
        return Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Transform(//这个动画效果是 向上慢慢移动的效果
                transform: Matrix4.translationValues(
                    0.0, 50.0 * (1.0 - percentVisible), 0.0),
                child: Padding(
                  padding: EdgeInsets.only(top: 20.0, bottom: 10.0),
                  child: Image.asset(viewModel.heroAssetPath,
                      width: 160.0, height: 160.0),
                ),
              ),
              Transform(//这个动画效果是 向上慢慢移动的效果
                transform: Matrix4.translationValues(
                    0.0, 30.0 * (1.0 - percentVisible), 0.0),
                child: Padding(
                  padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
                  child: Text(
                    viewModel.title,
                    style: TextStyle(
                      color: Colors.white,
                      fontFamily: 'FlamanteRoma',
                      fontSize: 28.0,
                    ),
                  ),
                ),
              ),
              Transform(//这个动画效果是 向上慢慢移动的效果
                transform: Matrix4.translationValues(
                    0.0, 30.0 * (1.0 - percentVisible), 0.0),
                child: Padding(
                  padding: EdgeInsets.only(bottom: 10.0),
                  child: Text(
                    viewModel.body,
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      height: 1.2,
                      color: Colors.white,
                      fontFamily: 'FlamanteRomaItalic',
                      fontSize: 18.0,
                    ),
                  ),
                ),
              ),
    //          ButtonBar(
    //            alignment: MainAxisAlignment.center,
    //            children: <Widget>[
    //              creatButton(context, '开始使用', Icons.add_circle_outline, 'start'),
    //              creatButton(context, 'GitHub', Icons.arrow_forward, 'goGithub'),
    //            ],
    //          )
            ]);
      }
    
    • creatButton
    Widget creatButton(
          BuildContext context, String txt, IconData iconName, String type) {
        return RaisedButton.icon(
            onPressed: () async {
              if (type == 'start') {//这是看代码应该是关闭 欢迎页
                await SpUtil.getInstance()
                  ..putBool(SharedPreferencesKeys.showWelcome, false);
                _goHomePage(context);
              } else if (type == 'goGithub') {//跳转 github
                Application.router.navigateTo(context,
                    '${Routes.webViewPage}?title=${Uri.encodeComponent(txt)} Doc&&url=${Uri.encodeComponent("https://github.com/alibaba/flutter-go")}');
              }
            },
            elevation: 10.0,
            color: Colors.black26,
            // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
            shape: RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(20.0))),
            //如果不手动设置icon和text颜色,则默认使用foregroundColor颜色
            icon: Icon(iconName, color: Colors.white, size: 14.0),
            label: Text(
              txt,
              maxLines: 1,
              style: TextStyle(
                  color: Colors.white, fontSize: 14, fontWeight: FontWeight.w700),
            ));
      }
    

    这里我都在原来的基础上加上了一些注释,可以结合看,我不多说了。

    相关文章

      网友评论

          本文标题:Flutter Go 源码分析(五)

          本文链接:https://www.haomeiwen.com/subject/ezypxctx.html