• Flutter仿照airbnb创建app


    github地址:https://github.com/GainLoss/flutter-app

    一、基础

    flutter是谷歌公司开发的开源免费的UI框架,用dart语言实现的,可以实现跨平台,一套代码可以在Android Ios Windows Max Linux系统运行;使用120fps,基于GPU渲染;

    1.Widget

    在flutter中一切都是Widget(和react里面一切都是组件好像),文字 图片 甚至路由都是Widget;

    flutter的底层架构(在flutter官网上有)

    1.主题风格:

    我们的主题风格可以分为Material和Cupertino是两种风格的主题包(前者是android后者是ios),风格是可以选择的,你也可以直接用基础的组件也是可以的;

    基础组件:https://flutterchina.club/widgets/

    Material:https://flutterchina.club/widgets/material/

    Cupertino:https://flutterchina.club/widgets/cupertino/

    Text 文本

    Text(
      '文本',
      style:TextStyle(fontSize:10.0,color:Colors.red,fontWeight:FontWeight[500],fontFamily:'字体类型'),//文本类型颜色之类的
      textAlign:TextAlign.center,//文本居中
      maxLines:2,//最多显示几行
        textDirection:TextDirection.rtl,//文本方向
        overflow:TextOverflow.ellipsis,//用省略号结尾
        softWrap:false,//是否自动换行
        textScaleFactor:20.0,//字体显示倍率
        locale//区域设置
    ) 

    Image 图片

    方法释义
    Image() ImageProvider中获取图片,从本质上看,下面的几个方法都是他的具体实现。
    Image.asset(String name) AssetBundler中获取图片
    Image.network(String src) 显示网络图片
    Image.file(File file) File中获取图片
    Image.memory(Uint8List bytes) Uint8List中显示图片

      可以有这几种获取图片的方法,那么里面数据主要有哪几个呢

     Image(
          10.0,
          height:10.0,
          color: Colors.greenAccent,
          colorBlendMode: BlendMode.colorBurn,//和color混合使
          alignment: Alignment.center, //居中
          repeat: ImageRepeat.noRepeat//重复
     )

    Icon 图标 官方图标:https://material.io/tools/icons/?icon=favorite_border&style=baseline

    Icon(
      Icons.ac_unit,
      color:Colors.red,
      size:10.0,
    )

    TextField 输入框

    TextField(
     TextEditingController controller, //控制正在编辑的文本
     FocusNode focusNode, //是否具有键盘焦点
     InputDecoration decoration: const InputDecoration(), //样式
     TextInputType keyboardType,//键盘类型
     TextInputAction textInputAction, //控制键盘的功能键 指enter键,比如此处设置为next时,enter键 显示的文字内容为 下一步
     TextStyle style, //文字样式
     TextAlign textAlign: TextAlign.start, //文字位置
     TextDirection textDirection, //文字下划线
     bool autofocus: false, //是否自动获取焦点
     bool obscureText: false, //隐藏文本输入内容 用 圆点 符号代替
     bool autocorrect: true, //是否自动更正
     int maxLines: 1,//显示行数 
     int maxLength, //限制长度
     bool maxLengthEnforced: true, //如果这个为false那么maxLength设置了也没有用
     onChanged:(){},//改变事件 
     onEditingComplete,//编辑完成事件
     onSubmitted, //提交事件
     inputFormatters, //限制输入的文字的格式
     bool enabled, //是否可编辑
     double cursorWidth: 2.0,//光标宽度 
     Radius cursorRadius, //光标圆角
     Color cursorColor,//光标颜色
     Brightness keyboardAppearance, 
     EdgeInsets scrollPadding: const EdgeInsets.all(20.0), 
     DragStartBehavior dragStartBehavior: DragStartBehavior.down, 
     bool enableInteractiveSelection, 
     onTap:(){},//点击事件 
    )

    Row:行 Column:列(如果你的内容超出了Row或者column的宽度或者高度,那么会报错页面会显示黄黑条纹,证明溢出了)

     Row(
        Key key, 
        MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, //主轴的对齐方向 水平是主轴
        MainAxisSize mainAxisSize: MainAxisSize.max, //布局的宽高值
        CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, //非主轴的对齐方式
        TextDirection textDirection, //Row 子级的排列顺序
        VerticalDirection verticalDirection: VerticalDirection.down,//Column 子级的排列顺序 
        TextBaseline textBaseline, //子组件对齐的,只不过对齐的是字符的基线
        List<Widget> children: const <Widget> []//放置自己
    )

    Flex:弹性布局允许子widget按照一定比例来分配父容器空间(和Row、Column类似)

     Flex(
      Key key, 
      Axis direction, //样式 边框之类的
      MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, 
      MainAxisSize mainAxisSize: MainAxisSize.max, 
      CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, 
      TextDirection textDirection, 
      VerticalDirection verticalDirection: VerticalDirection.down, 
      TextBaseline textBaseline, 
      List<Widget> children: const <Widget> []//子级
    )

    Expand:可以按比例“扩伸”Row、Column和Flex子widget所占用的空间。

    Expanded(
      Key key, 
      int flex: 1, 
      Widget child
    )

    Wrap和Flow:支持流式布局,可以在要溢出的时候自动换行(Wrap对比Row Flow对比Column Flow尽量少用,因为太过复杂了)

    Wrap(
     Key key, 
     Axis direction: Axis.horizontal, 
     WrapAlignment alignment: WrapAlignment.start,
     double spacing: 0.0, //主轴方向子widget的间距
     WrapAlignment runAlignment: WrapAlignment.start, 
     double runSpacing: 0.0, //纵轴方向的间距
     WrapCrossAlignment crossAxisAlignment: WrapCrossAlignment.start, 
     TextDirection textDirection, 
     VerticalDirection verticalDirection: VerticalDirection.down, 
     List<Widget> children: const <Widget> []//子级
    )

    Stack Positioned :层叠(经常一块使用)

    Stack(
       Key key, 
       AlignmentGeometry alignment: AlignmentDirectional.topStart, //如何去对齐没有定位
       TextDirection textDirection, 
       StackFit fit: StackFit.loose, //用于决定没有定位的子widget如何去适应Stack的大小
       Overflow overflow: Overflow.clip, //决定如何显示超出Stack显示空间的子widget
       List<Widget> children:[
         Image('src'),
         Positioned(
           Key key, 
           double left, 
           double top, 
           double right, 
           double bottom, 
           double width, 
           double height, 
           Widget child
         )
      ]
    )

    Container:容器

              Container(
                Key key, 
                AlignmentGeometry alignment,//子级对齐 
                EdgeInsetsGeometry padding, 
                Color color, //颜色
                Decoration decoration,// 背景装饰
                Decoration foregroundDecoration, //前景装饰
                double width, 
                double height, 
                BoxConstraints constraints, //容器大小的限制条件
                EdgeInsetsGeometry margin, 
                Matrix4 transform, //变换
                Widget child
              )

    ConstrainedBox:限制容器

    ConstrainedBox(
      Key key, 
      constraints: BoxConstraints(
        minWidth: double.infinity, //宽度尽可能大
        minHeight: 50.0 //最小高度为50像素
      ),
      Widget child
    )

    BoxDecoration:装饰容器

    BoxDecoration(
      Color color, //颜色
      DecorationImage image, //图片
      BoxBorder border, //边框
      BorderRadiusGeometry borderRadius, //圆角
      List<BoxShadow> boxShadow, //阴影
      Gradient gradient, 
      BlendMode backgroundBlendMode, 
      BoxShape shape: BoxShape.rectangle
    )
    

    ListView:水平列表

    ListView(
      Key key, 
      Axis scrollDirection: Axis.vertical, //水平列表还是垂直列表
      bool reverse: false, //翻转
      ScrollController controller, 
      bool primary, 
      ScrollPhysics physics, 
      bool shrinkWrap: false, //是否根据子widget的总长度来设置ListView的长度
      EdgeInsetsGeometry padding, 
      double itemExtent, //控制子控件在滚动方向上的长度,所以它跟scrollDirection是密切相关的
      bool addAutomaticKeepAlives: true, 
      bool addRepaintBoundaries: true, 
      bool addSemanticIndexes: true, 
      double cacheExtent, 
      List<Widget> children: const <Widget> [], 
      int semanticChildCount, 
      DragStartBehavior dragStartBehavior: DragStartBehavior.down
    )

    GridView:类似表格的那种布局

    GridView(
      Key key, 
     gridDelegate:SliverDelegateWithFixedCrossAxiaCount(
      crossAxisCount:2,//横轴两个子级
      childAspextRatio:1.0//宽高比为1
      mainAxisSpacing:0.0,//主轴间隔
      crossAxisSpacing:0.0,//横轴间隔
    ), Axis
    scrollDirection: Axis.vertical, //水平还是垂直 bool reverse: false, //翻转 ScrollController controller, bool primary, ScrollPhysics physics, bool shrinkWrap: false, EdgeInsetsGeometry padding, SliverGridDelegate gridDelegate, bool addAutomaticKeepAlives: true, bool addRepaintBoundaries: true, bool addSemanticIndexes: true, double cacheExtent, List<Widget> children: const <Widget> [], int semanticChildCount )

    GestureDetector:手势(交互事件在这里面都有)

    GestureDetector(
      Key key, 
     Widget child, (TapDownDetails) → void onTapDown, (TapUpDetails) → void onTapUp, () → void onTap, () → void onTapCancel, () → void onDoubleTap, () → void onLongPress, () → void onLongPressUp, (GestureLongPressDragStartDetails) → void onLongPressDragStart, (GestureLongPressDragUpdateDetails) → void onLongPressDragUpdate, (GestureLongPressDragUpDetails) → void onLongPressDragUp, (DragDownDetails) → void onVerticalDragDown, (DragStartDetails) → void onVerticalDragStart, (DragUpdateDetails) → void onVerticalDragUpdate, (DragEndDetails) → void onVerticalDragEnd, () → void onVerticalDragCancel, (DragDownDetails) → void onHorizontalDragDown, (DragStartDetails) → void onHorizontalDragStart, (DragUpdateDetails) → void onHorizontalDragUpdate, (DragEndDetails) → void onHorizontalDragEnd, () → void onHorizontalDragCancel, (ForcePressDetails) → void onForcePressStart, (ForcePressDetails) → void onForcePressPeak, (ForcePressDetails) → void onForcePressUpdate, (ForcePressDetails) → void onForcePressEnd, (DragDownDetails) → void onPanDown, (DragStartDetails) → void onPanStart, (DragUpdateDetails) → void onPanUpdate, (DragEndDetails) → void onPanEnd, () → void onPanCancel, (ScaleStartDetails) → void onScaleStart, (ScaleUpdateDetails) → void onScaleUpdate, (ScaleEndDetails) → void onScaleEnd, HitTestBehavior behavior, bool
    excludeFromSemantics: false, DragStartBehavior dragStartBehavior: DragStartBehavior.down )

    StatelessWidget和StatefulWidget

    1.StatelessWidget:无中间状态变化的widget,需要更新展示内容就得通过重新new,flutter推荐尽量使用StatelessWidget

    2.StatefullWidget:存在中间状态变化,那么问题来了,widget不是都immutable的,状态变化存储在哪里?flutter 引入state的类用于存放中间态,通过调用state.setState()进行此节点及以下的整个子树更新

    二、注意

    1.在dart中如果需要将变量变成私有的可以在变量名字前面加下划线 _name 就可以了;

    2.有的组件具有点击效果比如LnkWall 有一个onTap表示点击,但是有的并没有点击函数。所以我们可以把这个组件放到手势里面;

    三、理解

    1.几种移动端开发的技术对比

      React Native   是接近原生;               需要些适配代码;         60fps(帧)

      Html5    就是嵌入页面;           需要适配代码;   

      Flutter    可以和原生开发一致甚至超过原生;    不需要直接一套代码就可以了;  120fps (帧) 基于C++开发 原生的是基于Java开发的

    2.引入dart文件或者包

    <1>.import 组件路径 show 需要导入的组件名称;//本地组件 只引入组件名字的,如果没有写名字那么就是全部引入

    <2>.import 'package:包名称';//要引入的dart文件

      在pubspec.yaml文件中将包的版本写上,就可以了

    1 dependencies:
    2   flutter:
    3     sdk: flutter
    4   cupertino_icons: ^0.1.2
    5   http : ^0.12.0
    6   dio: ^2.1.0
    7   date_range_picker: ^1.0.5

    <3>.一个dart文件作为另一个文件的一部分

    在父中:part './book/Featured.dart';

    在子中:part of '../book.dart';

    3.数据交互

    第一种方法

    import 'package:http/http.dart' as http;//包
    import 'dart:convert';//包
    class GetData extends StatefulWidget{
      _StateGetData createstate()=>_StateGetData() 
    }
    class _StateGetData extends State<GetData>{
        Future _getDataInfo() async{
        final url=Uri.http('10.0.2.2:8081','/home',{'mark':'春季特惠房间','address':widget.mark});
        final result=await http.get(url);
        setState((){
          data=json.decode(result.body).toList();
        });
      }
      @override
      void initState(){
        super.initState();
        _getDataInfo();
      }
      Widget build(BuildContext context){
         return Container()    
      }    
    }

    第二种方法

    import 'package:http/http.dart' as http;//包
    import 'dart:convert';//包
    class GetData extends StatefulWidget{
      _StateGetData createstate()=>_StateGetData() 
    }
    class _StateGetData extends State<GetData>{
        _getDataInfo(){
        final url=Uri.http('10.0.2.2:8081','/home',{'mark':'春季特惠房间','address':widget.mark});
        final result=http.get(url);
        return result
      }
      @override
      Widget build(BuildContext context){
        FutureBuilder(
          future:_getDataInfo(),
          builder:(BuildContext context,snap){
            return snap.data
          }
        )
         return Container()    
      }    
    }

    4.路由

    main.dart

    return new MaterialApp(
          title: 'Flutter Demo',
          home: new MyHomePage(title: '应用程序首页'),
          routes: <String, WidgetBuilder> {
            '/a': (BuildContext context) => new MyPage(title: 'A 页面'),
            '/b': (BuildContext context) => new MyPage(title: 'B 页面'),
            '/c': (BuildContext context) => new MyPage(title: 'C 页面')
          },
    );

    1.page1-page2

    page1

    Navigator.pushNamed(context,'/page2')

    2.page1-page2带参数

    page1

    Navigator.of((context).push(MaterialPageRoute(
    builder: (context) {
    return new Page2("传入跳转参数");
    }
    ));

    3.page2-page1带参数

    page2

    Navigator.of(context).pop("我是来自dymamic 关闭的返回值");

     5.flutter底层渲染

    我们在开发android或者ios的时候用的语言是不一样,但是最终的图形计算和绘制都是由相应的硬件来完成,而直接操作硬件的指令通常都会有操作系统屏蔽,应用开发者通常不会直接面对硬件,操作系统屏蔽了这些底层硬件操作后会提供一些封装后的API供操作系统之上的应用调用,但是对于应用开发者来说,直接调用这些操作系统提供的API是比较复杂和低效的,因为操作系统提供的API往往比较基础。

    Flutter的原理正是如此,它提供了一套Dart API,然后在底层通过OpenGL这种跨平台的绘制库(内部会调用操作系统API)实现了一套代码跨多端。由于Dart API也是调用操作系统API,所以它的性能接近原生。

    6.Element和BuildContext的区别

    根据Widget生成Element,然后创建相应的RenderObject并关联到Element.renderObject属性上,最后再通过RenderObject来完成布局排列和绘制。

    四、资料

    1.官网:https://flutter.dev/

    2.中文网站:https://flutterchina.club/

    3.dart package:https://pub.dartlang.org/

    4.Icon:https://material.io/tools/icons/?icon=favorite_border&style=baseline

    5.数据可以放在firebase

  • 相关阅读:
    转:Web Service介绍
    CodeIgniter网页缓存
    CodeIgniter管理你的应用程序
    CodeIgniter自动装载资源
    python feedparser 使用
    HTC文件的使用
    动态执行javascript代码
    jQuery获取文本节点之text()/val()/html() 方法区别
    style,runtimeStyle与currentStyle的定义及用法
    File,FileStream,byte[]3者互相转换总结(转)
  • 原文地址:https://www.cnblogs.com/GainLoss/p/10637491.html
Copyright © 2020-2023  润新知