flutter学习笔记

flutter与RN的异同

  • 均实现了跨平台
  • 都支持热重载,开发调试非常方便
  • RN基于React,使用js开发,受众较广,flutter则是使用Dart,受众小,对于Java开发人员来说非常友好
  • 通俗来讲,RN的UI框架是将JS转化为原生控件,所以流畅度会比webview要高,而flutter则是从更底层进行控件的绘制,直接废弃了原生UI控件,性能要比RN更高!可以将flutter的应用理解成一个跨平台的游戏引擎写的游戏APP。
  • RN发展较早,比flutter稳定,flutter的第三方库还很少

flutter界面控件

在flutter中,所有控件都是widget,页面(可以理解成Android的activity,iOS的controller)和应用程序自身都是一个widget。

flutter中存在两种widget,StatelessWidget用于定义无状态控件,适用于显示静态文字、图片等,这种控件在编译运行后无法更新内容;StatefulWidget用于定义有状态控件,后期可以通过调用setState方法来刷新内容,用途更广,更灵活。

flutter自带了Material Design的整套UI设计控件,可构建非常完整MD风格的APP,也拥有用于当前iOS设计语言的美丽和高保真widget。

详细widget控件目录可浏览flutter中文官网

flutter构建页面

在flutter中页面自身也是widget,以下示例中的MaterialApp控件提供了MD风格的整套UI模板,另外也有针对iOS风格的CupertinoApp

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // 这个widget是这个应用的根部widget
  @override
  Widget build(BuildContext context) { 
    return MyHomePage();
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  // 这是应用的主页widget,同时它是一个有状态的widget,意味着它可以动态刷新内容
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  int _counter = 0;

  void _incrementCounter() {
    setState(() { 
      //当你调用setState方法时,会通知framework触发build方法,刷新UI界面
      _counter++; 
    });
  }

  @override
  Widget build(BuildContext context) {
    //当你条用setState方法,build方法就会被触发,刷新UI
    return  MaterialApp(
    //设置路由
     routes: < String, WidgetBuilder > {

      '/a':(_) => PageA(),
      '/b':(_) => PageB()},
      title: 'Flutter Demo',
      home: Scaffold(
        backgroundColor: Colors.white70,
        appBar: AppBar(
          title: Text('hello flutter'),
        ),
        body: Center( 
          child: Text('hello flutter onclick-count = $_counter'),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

flutter学习笔记_第1张图片
Screenshot_1550475894.png

值得注意的是MyApp自身是StatelessWidget,是无状态的widget,但由于它内部存在StatefulWidget,所以它是可以通过StatefulWidget来更改UI

flutter触摸事件

flutter中,除了RaisedButton、FlatButton、IconButton等一系列按钮控件外,其余widget是不具备onPressed属性的,但是flutter提供了一个更加强大的手势监听widget:GestureDetector,支持单机、双击、长按等常见触摸事件,当你某个widget需要某些触摸事件时,可在GestureDetector嵌套该widget。

GestureDetector(
            //双击
            onDoubleTap: (){

            },
            //长按
            onLongPress: (){

            },
            //单击
            onTap: (){

              _incrementCounter();
            },
            child: Text('hello flutter onclick-count = $_counter'),
          ), 

flutter页面跳转

路由分为静态路由和动态路由

静态路由

有两种注册方式
1.修改主方法,用MaterialApp或其他WidgetsApp来包裹MyApp,设置路由

void main() => runApp(MaterialApp(home: MyApp(),
  routes: < String, WidgetBuilder > {

      '/a':(_) => PageA(),//页面A
      '/b':(_) => PageB()//页面B 
  },
)); 

2.直接在MyApp的类中设置属性,请参考flutter构建页面这一章节

然后通过

//切换到B页面
 Navigator.pushNamed(context, '/b');

动态路由

动态路由则不需要事先注册,灵活度更高,使用方式更多,方便传值以及设置转场动画

Navigator.push(context, PageRouteBuilder(pageBuilder: (BuildContext context, Animation < double > animation,
              Animation < double > secondaryAnimation) {
              //下一个页面
              return Center(
                child: GestureDetector(
                  onTap: () {
                    //返回上一个页面
                    Navigator.pop(context);
                  },
                  child: Text('haha'),
                ),
              );
            //构建转场动画
            }, transitionsBuilder: (BuildContext context,
              Animation < double > animation,
              Animation < double > secondaryAnimation,
              Widget child) {
                //自定义转场动画
              return new SlideTransition(
                position: new Tween < Offset > (
                  begin: const Offset(3.0, 0.0),
                    end: const Offset(0.0, 0.0),
                ).animate(animation),
                child: child,
              ).build(context);
            }));

如果你想使用系统默认的动画,推荐直接使用MaterialPageRoute

Navigator.push(context,MaterialPageRoute(builder: (context){
              //下一个页面
              return Center(
                child: GestureDetector(

                  onTap: () {
                    //返回上一页
                    Navigator.pop(context);
                    //返回上一页,并且返回一个200的值,可以是其他值,用于回调场景
                    //Navigator.pop(context,200);

                  },
                  child: Text('haha'),
                ),
              );
              //用于接收下一个页面返回的值
            })).then((data){


              print(data);
            });

建议通过自定义StatefulWidget来构建下一个可刷新的页面,更便于传值

Navigator.push(context,MaterialPageRoute(builder: (context){
              //Page为StatefulWidget参数即可达到传值的效果
              return Page(id:'1023');
            }));

flutter与原生交互

Android

首先,在flutter中声名如下方法

 Future _tryConnectAndroid() async {
      
          try { 
              //注册方法频道
              MethodChannel platform = MethodChannel('samples.test/test');
              //第一个参数 tryToast为Java/oc中的方法名(后面会讲),第二个参数数组为传参数组
              String result= await platform.invokeMethod('tryToast',[{'msg':"flutter connect android"}]);}
              //result 为回调的结果
              on PlatformException catch (e){ 
                  
              }
 
    }

然后在flutter项目的Android目录找到MainActivity

public class MainActivity extends FlutterActivity {
  //需要与flutter的MethodChannel名称对应
  static String CHANNEL="samples.test/test";
  private int count = 0;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
     //注册方法
    new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
      new MethodCallHandler() {
          @Override
          public void onMethodCall(MethodCall call, Result result) {
              //找到对应的方法名
              if (call.method.equals("tryToast")) {
                  //传递过来的参数列表
                  ArrayList arguments = (ArrayList)call.arguments;
                  String msg =((Map)arguments.get(0)).get("msg");
                  //回调结果
                  result.success("hello flutter");
                // start();
                Toast.makeText(MainActivity.this,msg,Toast.LENGTH_LONG).show();

              }

          }
      });
  }


  
}

iOS

iOS的请参考此链接

flutter打包apk与ipa

apk打包

apk打包相对简单,和以往的Android打包一样,在gradle文件里配置好签名信息等,运行一下指令即可

flutter build apk

IPA的请参考此链接

总结

学习flutter两三个星期,一开始被它多重嵌套的UI写法吓到了,后来习惯下来还是比较得心应手的,虽然写UI的时候不能像Android写xml一样能够即使预览,但是得益于热重载的功能,实际上你一边写UI一边在模拟器和手机上预览UI也是完全没有问题的。flutter提供了大量的UI控件,方便开发者灵活使用,像上文所说,flutter是直接抛弃了原生控件,通过图像引擎利用Android/iOS的画布将UI绘制出来,性能当然要比RN通过JavaScript转换成原生UI控件要高,通过Android手机查看基于flutter缩写APP的UI层级时,会发现APP的UI只有一个层级,它是一个整体的View,不像以往Android需要进一步优化布局层级。

flutter的定义是极速构建漂亮的原生应用,是一套移动UI框架,flutter只是能够帮助开发者更有效率地构建UI,如果APP的业务需要调用大量的手机系统特性时,开发者仍需要转移到原生开发中,所以开发者能够同时掌握Android、iOS开发就最好不过了。

更多关于flutter的文档可查阅此链接

你可能感兴趣的:(flutter学习笔记)