快速开始Flutter

创建Flutter工程

flutter工程名文件夹文件命名规则: 不要用驼峰不要用大写不要用中文
类名可以用驼峰命名

创建工程方式
  • 命令创建
// -i objc指定 OC语言,hello_flutter为工程名
flutter create -i objc hello_flutter
  • 工具栏创建
image.png
  • Android Studio启动页创建入口
image.png
配置Flutter SDK路径
image.png
Flutter工程配置
  • 配置androidios语言类型,选择平台类型
image.png
  • 选择工程Project
image.png
  • 选择模拟器,运行flutter工程
image.png
成功运行
Flutter能运行在iOS与Android平台的原因是什么?

原因是在iOS与Android平台都安装了渲染引擎

Flutter与RN的本质区别?
  • RN:对原生UIUIKit的包装,一旦原生UI产生更新,那么RN也需要进行更新,对原生的依赖性很强,RN有热更新
  • Flutter:把不同平台的渲染引擎安装在手机上,渲染引擎负责解析Dart代码进行页面展示,Flutter有热重载
    优点:效率高,不依赖于UI,安卓iOS高度统一
    缺点:引入渲染引擎会导致安装包体积增大

hello_flutter

更新Flutter版本
// 检查flutter环境配置
$ flutter doctor
// 更新flutter版本
$ flutter upgrade
解决Android Studio快捷键Cmd + Q的bug

Android Studio如果使用快捷键Cmd + Q强退,有可能会锁住当前的运行环境。一旦锁住运行环境,再次打开工程就有可能出现问题,原因是Android Studio中为了保护数据,里面有一个缓存机制

解决方案
强退Android Studio导致flutter卡住了,就需要删除缓存文件,lockfile文件目录~/flutter/bin/cache/lockfile

删除flutter SDK目录下的lockfile文件
开始Flutter编写
  • 实现基层组件都需要导入头文件material.dart导入常用的素材类似于iOS中的UIKit
// 导入flutter的UI库,类似于iOS的UIKit
import 'package:flutter/material.dart';
  • 在 iOS中运行APP 是在window中,在Flutter中使用runApp,在这个里面添加组件,我们先来看看Text组件
// flutter入口函数
void main() {
  runApp(const Center(
    child: Text(
      'helloFlutter',
      textDirection: TextDirection.ltr,
    ),
  ));
}
  1. 当前运行页面里面有两个小部件CenterText,都是继承于Widget
  2. Center相当于OC中的viewchild相当于subView的意思
  3. Text相当于UILabel
运行效果

flutter是增量渲染,不会改变组件内容,会直接用新的组件替换旧的组件,直接修改控件本身,以此改变值,所以效率很高;flutter没有页面层级它只有一层页面

Dart中的var、final 和 const介绍
  • var声明变量
void main() {
  var a;//变量
  print(a); // 打印结果为null

  var b;//变量
  b = "this is b !";
  print(b); // 打印结果为 this is b !
}
  1. var声明的变量,没有指定值,也没有指定类型,是一个动态类型,鼠标放上去会提示类型!
  2. dart中使用var声明变量,可以赋值不同类型的值,会自动推断变量的类型和Swift中是一样的效果。
  3. var声明的变量如果没有初始化,那么它的值是null
  • final声明变量
void main(){
  final a = 10;
  a = "hello"; // 运行报错

  final b;
  b = "hello";
  print(b); // 打印结果为 hello

  final c;
  print(c); // 运行报错
}
  1. final修饰的是一个最终的变量,不能再次赋值,否则会报错。也可以先声明再次赋值,但是只能赋值一次。
  2. final适用声明以后不会改变的变量,也就类似一个常量的意思,它只能赋值一次。
  3. final声明的变量,不赋值是不可以使用的
  • const声明常量
void main(){
  const a;
  a = 8; // 运行报错
  
  const b = 8;
  print(b); // 打印结果为 8
}
  1. const修饰常量,声明的时候就得赋值,这也是和变量最大的区别!
  2. const常量也是不可以修改的,不可以再次赋值,这点和 final 一样

自定义Widget

Widget分为两大类有状态stateful无状态stateless,其实flutter小组件本质上都是无状态的,有状态只是定义了一些功能方便开发

  • 无状态stateless表示不可变,如果要想改变,用新的组件替换当前组件
  • 有状态stateful表示在当前树中,内部小组件可以更改状态。影响页面渲染的数据保存起来就是有状态的
自定义Widget
  • 继承于无状态小部件
  • 要想让小部件显示在页面上,必须实现build方法返回Widget
import 'package:flutter/material.dart';

void main() {
  runApp(MyWidget());
}
// 如果main()里面只有一行代码,可以使用箭头函数进行缩写
//void main() => runApp(MyWidget());

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'helloFlutter',
        textDirection: TextDirection.ltr,
        style: TextStyle(fontSize: 14,color: Colors.orange,backgroundColor: Colors.white),
      ),
    );
  }
}
image.png
flutter热重载

如果iOS项目过大,编译时间会很长,虽然我们只改了一行代码,想要查看效果,也需要编译很长时间。而flutter开发中有一个好处,不需要重新启动flutter工程。比如我们改了Text文字大小,flutter会增量渲染我们修改的内容,不会重复渲染其他内容,即flutter热重载增量渲染就是用新的小部件直接替换旧的小部件,将内容展示出来。

如果flutter项目是有状态的,那么数据发生了更改,就需要重新启动flutter项目。即渲染树发生了变化需要重新启动flutter项目

如果是有状态的小部件,而且状态发生了变化,热重载状态是不会清零的。如果要想把状态清零,需要重新启动项目

文字样式

flutter中创建模型对象是不会渲染的。这样的对象成员属性是可以更改的,一旦模型对象的属性发生变化,通过这个模型对象取到新的数据,用来创建新的小部件

import 'package:flutter/material.dart';

void main() => runApp(MyWidget());

// 继承于无状态小部件
// 要想让小部件显示在页面上,必须实现build方法,返回Widget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'helloFlutter123123',
        textDirection: TextDirection.rtl,
        style: TextStyle(
            fontSize: 40,
            fontWeight: FontWeight.bold,
            color: Colors.orange,
        )
      ),
    );
  }
}
image.png
Text组件
  • 创建Text
    Text()构造方法创建
  • Text属性
textDirection 文本对齐  (必须要写的属性,否则内容不显示)
TextAlign.center 将文本对齐容器的中心。
TextAlign.end 对齐容器后缘上的文本。
TextAlign.justify 拉伸以结束的文本行以填充容器的宽度。即使用了decorationStyle才起效
TextAlign.left 对齐容器左边缘的文本。
TextAlign.right 对齐容器右边缘的文本。
TextAlign.start 对齐容器前缘上的文本。
maxLines 最大行数
overflow 处理字数溢出
TextOverflow.clip 剪切溢出的文本以修复其容器。
TextOverflow.ellipsis 使用省略号表示文本已溢出。
TextOverflow.fade 将溢出的文本淡化为透明。
textScaleFactor 字号系数
  • TextStyle style属性
color 文本颜色。
decoration 绘制文本装饰:
下划线(TextDecoration.underline)
上划线(TextDecoration.overline)
删除线(TextDecoration.lineThrough)
无(TextDecoration.none)

decorationStyle 绘制文本装饰的样式:
画一条虚线 TextDecorationStyle.dashed
画一条虚线 TextDecorationStyle.dotted
画两条线 TextDecorationStyle.double
画一条实线 TextDecorationStyle.solid
画一条正弦线(波浪线) TextDecorationStyle.wavy

fontWeight 绘制文本时使用的字体粗细:
FontWeight.bold 常用的字体重量比正常重。即w700
FontWeight.normal 默认字体粗细。即w400
FontWeight.w100 薄,最薄
FontWeight.w200 特轻
FontWeight.w300 轻

fontStyle 字体变体:
FontStyle.italic 使用斜体
FontStyle.normal 使用直立

textBaseline 对齐文本的水平线:
TextBaseline.alphabetic:文本基线是标准的字母基线
TextBaseline.ideographic:文字基线是表意字基线;

fontSize 字体大小

letterSpacing 水平字母之间的空间间隔(逻辑像素为单位)。可以使用负值来让字母更接近。
wordSpacing 单词之间添加的空间间隔(逻辑像素为单位)。可以使用负值来使单词更接近。
height 文本行与行的高度,作为字体大小的倍数
locale 用于选择区域特定字形的语言环境
background 文本背景色
foreground 文本的前景色
shadows 实现一些特殊效果

MaterialApp

  • 素材App
  • home属性,主页面
  • debugShowCheckedModeBanner属性,便于我们在调试版本中做操作
import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyWidget(),
    );
  }
}

// 继承于无状态小部件
// 要想让小部件显示在页面上,必须实现build方法,返回Widget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'helloFlutter123123',
        textDirection: TextDirection.rtl,
        style: TextStyle(
            fontSize: 40,
            fontWeight: FontWeight.bold,
            color: Colors.orange,
        )
      ),
    );
  }
}
运行效果
Scaffold小部件
  • ScaffoldMaterial Design布局结构的基本实现,此类提供了用于显示drawersnackbar底部sheet的API,是带有导航栏的小部件。
  • body属性,显示在导航栏下面的区域,需要传递一个Widget
import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('FlutterDemo'),
        ),
      ),
    );
  }
}

// Scaffold主要属性
appBar:显示在界面顶部的一个 AppBar
body:当前界面所显示的主要内容
floatingActionButton: 在 Material 中定义的一个功能按钮。
persistentFooterButtons:固定在下方显示的按钮。
drawer:侧边栏控件
bottomNavigationBar:显示在底部的导航栏按钮栏。
backgroundColor:背景颜色
resizeToAvoidBottomPadding: 控制界面内容 body
是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容。默认值为 true。
image.png

自定义小部件MyWidget嵌入home

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('FlutterDemo'),
        ),
        body: MyWidget(),
      ),
    );
  }
}

// 继承于无状态小部件
// 要想让小部件显示在页面上,必须实现build方法,返回Widget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'helloFlutter123123',
        textDirection: TextDirection.rtl,
        style: TextStyle(
            fontSize: 40,
            fontWeight: FontWeight.bold,
            color: Colors.orange,
        )
      ),
    );
  }
}
image.png

这个时候Center是相对于body居中的,Center小部件是相对于父视图居中的。

初探ListView

下面实现一个类似UITableView的页面

  • 新建model目录,里面创建Car.dart模型
// 
class Car {
  // {} 表示可选,可以给Car赋值,也可以不赋值
  const Car({this.name, this.imageUrl});
  final String? name;
  final String? imageUrl;
}
  • main.dart文件中导入Car.dart
import 'model/Car.dart';
  • ListView最终代码
import 'package:flutter/material.dart';
import 'model/car.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      // 去掉debug标识
      debugShowCheckedModeBanner: false,
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  //_是指文件内部!!!只在main.dart文件内部可以访问
  Widget _itemForRow(BuildContext context, int index) {
    return Container(
        color: Colors.white,
        margin: const EdgeInsets.all(10),
        // 组件的排列有三种,横着 竖着 叠着
        child: Column(
          children: [
            // 命名构造函数,图片是异步加载
            Image.network(datas[index].imageUrl!),
            // SizedBox用于设置图片与文字的间隔,也可以用Container设置间隔
            const SizedBox(
              height: 10,
            ),
            Text(
              datas[index].name!,
              style: const TextStyle(
                fontWeight: FontWeight.w800,
                fontSize: 18.0,
                // italic表示斜体
                fontStyle: FontStyle.italic,
              ),
            ),
          ],
        ));
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        title: const Text('FlutterDemo'),
      ),
      // listview构造函数
      body: ListView.builder(
        // 获取_itemForRow,上面定义的Widget
        itemBuilder: _itemForRow,
        itemCount: datas.length,
      ),
    );
  }
}

//引入`Car`模型数据
final List datas = [
  const Car(
    name: '保时捷918 Spyder',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '兰博基尼Aventador',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '法拉利Enzo',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: 'Zenvo ST1',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '迈凯伦F1',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '萨林S7',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '科尼赛克CCR',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '布加迪Chiron',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '轩尼诗Venom GT',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '西贝尔Tuatara',
    imageUrl:
        'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  )
];
ListView运行效果
Container小部件

Container是一个容器类,一个拥有绘制定位调整大小widget,在Flutter中万物皆widgetwidget是小部件的意思。类似于iOS中的UIView

  • Container组成
  1. Container的最里层的是child元素,child元素首先会被padding包着,然后添加额外的constraints限制,最后添加margin
  2. Container自身尺寸的调节分两种情况:
    Container在没有子节点(children)的时候,会试图去变得足够大。除非constraintsunbounded限制,在这种情况下,Container会试图去变得足够小。
    带子节点的Container,会根据子节点尺寸调节自身尺寸,但是Container构造器中如果包含了widthheight以及constraints,则会按照构造器中的参数来进行尺寸的调节。
  • Container属性
  1. keyContainer唯一标识符,用于查找更新。
  2. alignment:控制child的对齐方式,如果container或者container父节点尺寸大于child的尺寸,这个属性设置会起作用,有很多种对齐方式。
  3. paddingdecoration内部的空白区域,如果有child的话,child位于padding内部。padding与margin的不同之处在于,padding是包含在content内,而margin则是外部边界,设置点击事件的话,padding区域会响应,而margin区域不会响应。
  4. color:用来设置container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果。
import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      margin: EdgeInsets.all(10),
      color: Colors.red,
      alignment: Alignment(0,0),
      child: Container(
        margin: EdgeInsets.all(10),
        color: Colors.brown,
        width: 250,
        height: 250,
        child: Text(
          'Hello World',
          textDirection: TextDirection.ltr,
          style: TextStyle(fontSize: 26,color: Colors.blue,backgroundColor: Colors.white),
        ),
      ),
    );
  }
}
运行效果

Flutter中文网 - 文档学习
Dart - 文档学习
Dart包获取地址

你可能感兴趣的:(快速开始Flutter)