美文网首页Flutter
Flutter笔记-控件3

Flutter笔记-控件3

作者: 叶落清秋 | 来源:发表于2019-01-04 18:27 被阅读14次

    1. 路由Navigator

    基础使用

    //路由跳转
     Navigator.of(context).push(MaterialPageRoute(builder: (context)=>Container()));
    //关闭路由
    Navigator.pop(context);
    

    带返回值

    //路由跳转,接收返回值
    Future<int> result = Navigator.of(context).push(MaterialPageRoute(builder: (context)=>Container()));
    //关闭路由,传递值1(泛型,当然也可以是其他值)
    Navigator.pop(context,1);
    

    定制路由
    PageRouteBuilder 可以定制动画或其他样式

    //路由自定义动画,改为左边进入
    Navigator.of(context).push(PageRouteBuilder(
                            pageBuilder: (context,Animation animation,_)=>FadeTransition(
                              opacity: animation,
                              child: SlideTransition(position: Tween<Offset>(begin: Offset(-1.0, 0.0),end: Offset(0.0, 0.0)).animate(animation),child: AnimationContain(),),
                            )
                        ));                    
    

    命名导航器路由(静态路由)

    //注册  MaterialApp 的routes参数,传递map
    //统一定制路由,MaterialApp 的onGenerateRoute参数
    var map = <String, WidgetBuilder> {
            '/a': (context) =>Container()};
    //使用
    Navigator.of(context).pushName('/a');
    //关闭
    Navigator.pop(context);
    

    静态路由和动态路由内部其实是一样的,但是更方便管理,可以用一个map,而map的实例放在一个文件里,这个文件即可集中管理所有路由,修改起来非常方便

    ModalRoute
    常用路由:

    router 关系 用途
    PageRoute 子类 页面路由
    PopupRoute 子类 弹框路由
    WillPopScope 组合 导航返回拦截

    a. PageRoute
    MaterialPageRoutePageRouteBuilder都是其的子类,与页面有关,覆盖全屏
    b. PopupRoute
    与弹框有关,无需覆盖全屏
    showDialog、showMenu和showModalBottomSheet等内部创建了PopupRoute实例,并调用了路由
    c.WillPopScope
    可实现返回拦截,如短时间连续点击二次退出
    内部创建了ModalRoute实例


    源码层简析:https://segmentfault.com/a/1190000011590792?utm_source=tag-newest

    2.主题 Theme

    先从MaterialApptheme来看,源码的build方法可以看出其实内部创建了AnimatedTheme控件,而AnimatedTheme控件内部其实就是创建了Theme控件
    所以还是要看Theme
    Theme内部创建了_InheritedTheme

    class _InheritedTheme extends InheritedWidget {
      const _InheritedTheme({
        Key key,
        @required this.theme,
        @required Widget child
      }) : assert(theme != null),
           super(key: key, child: child);
    
      final Theme theme;
    
      @override
      bool updateShouldNotify(_InheritedTheme old) => theme.data != old.theme.data;
    }
    

    InheritedWidget控件比较重要,可用于数据共享,Theme内部明显共享着ThemeData,这意味着一旦MaterialApp使用了theme,后续的控件如果不新建ThemeData,将共享这主题数据
    InheritedWidget后续再研究,相关信息:https://book.flutterchina.club/chapter7/inherited_widget.html

    //修改accentColor,其他默认
    Theme(
      data: Theme.of(context).copyWith(accentColor: Colors.yellow),  
    );
    //单独使用
    color: Theme.of(context).accentColor
    //使用新创建的
    Theme(
          data: ThemeData(
              primarySwatch: _themeColor, //用于导航栏、FloatingActionButton的背景色等
              iconTheme: IconThemeData(color: _themeColor) //用于Icon颜色
          )
    

    3.手势

    Listener原始事件
    与android的onTouchEvent一样,有4个基础手势

    • onPointerDown: 手指按下
    • onPointerMove: 手指移动
    • onPointerUp: 手指抬起
    • onPointerCancel: 手指取消
      一个HitTestBehavior
    enum HitTestBehavior {
      //子widget会一个接一个的进行命中测试,如果子Widget中有测试通过的,则当前Widget通过,
      //这就意味着,如果指针事件作用于子Widget上时,其父(祖先)Widget也肯定可以收到该事件
      deferToChild,  //默认
    
      //在命中测试时,将当前Widget当成不透明处理(即使本身是透明的),最终的效果相当于当前Widget的整个区域都是点击区域
      opaque,
    
      //当点击透明区域时,可以对底部widget进行命中测试,这意味着底部widget也可以接收事件
      //translucent可以在Stack中实现"点透"的效果
      translucent,
    }
    

    GestureRecognizer 手势识别
    GestureDetector封装手势识别控件,内部使用的是多个GestureRecognizer
    使用

    Listener(
      child: Container(
        alignment: Alignment.center,
        color: Colors.blue,
        width: 300.0,
        height: 150.0,
        child: Text(_event?.toString()??"",style: TextStyle(color: Colors.white)),
      ),
      onPointerDown: (PointerDownEvent event) => setState(()=>_event=event),
      onPointerMove: (PointerMoveEvent event) => setState(()=>_event=event),
      onPointerUp: (PointerUpEvent event) => setState(()=>_event=event),
    )
    

    注:event内部使用的坐标是绝对坐标

    4.动画

    官方封装控件比较多,这里就说最基础的
    快捷键stanim
    创建的state会混合SingleTickerProviderStateMixin类,用于计时

    class ScaleAnimationWidget extends StatefulWidget {
      @override
      _ScaleAnimationWidgetState createState() => _ScaleAnimationWidgetState();
    }
    
    class _ScaleAnimationWidgetState extends State<ScaleAnimationWidget> with SingleTickerProviderStateMixin {
      AnimationController _controller;
      Animation<double> _animation;
      double _value = 255.0;
      bool _flag = true;
      _changeValue(){
        if(_flag) {
          _controller.forward();
        }else{
          _controller.reverse();
        }
        _flag = !_flag;
      }
    
      @override
      void initState() {
        _controller = AnimationController(duration: Duration(seconds: 1),vsync: this);
        //插值器
        _animation = CurvedAnimation(parent: _controller, curve: Curves.decelerate);
        _animation = Tween(begin: 255.0, end: 80.0).animate(_animation)
          ..addListener((){
            setState(() {});
          });
        super.initState();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
      
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: _changeValue,
          child: Container(
            width: _animation.value,
            height: _animation.value,
            child: FlutterLogo(),
          ),
        );
      }
    }
    

    动画一般一个AnimationController管理多个Animation,共4个AnimationStatus状态:
    a. dismissed 动画在起始点停止
    b. forward 动画正在正向执行
    c. reverse 动画正在反向执行
    d. completed 动画在终点停止
    使用步骤

    //1.创建动画控制器
    _controller = AnimationController(duration: Duration(seconds: 4),vsync: this);
    //2.添加动画,可以添加多个
    //Interval设置实现动画时间段,设置动画播放方式
    _x = Tween(begin: 0.0, end: 200.0).animate(
          CurvedAnimation(parent: _controller, curve: Interval(0.0, 0.6,curve: Curves.bounceInOut))
        );
     //执行动画
    _controller.forward();
    

    也可以设置监听

    _controller.addListener((){
          //每次值改变将调用内部
        });
    _controller.addStatusListener((AnimationStatus state){
          //可对state进行处理
        });
    

    小结

    这部分使用起来比较简单,但要深入原理需要花费一定时间。
    当时学android的时候,刚开始也是一大堆View,但其实这东西和api一样,用多了就掌握了。
    Flutter其实相对好些,所有能修改的样式其实都放在构造函数中,配合注释其实上手很快的,至于多个括号,其实你用久了感觉还是很舒服的(真香!)

    只会使用是没有意义的,接下来进一步深入控件的摆放,绘制及事件

    相关文章

      网友评论

        本文标题:Flutter笔记-控件3

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