Plugin & Package

Package: Dart中的第三方框架,里面只有Dart的代码
Plugin: 包含安卓和iOS原生的代码

Flutter & RN

Flutter:有一套自己的渲染引擎,不依赖原生UI,效率高,高度统一。
RN:基于原生的UI进行的包装,一旦原生的更新,马上也需要更新。

Widget

material.dar类似于iOS中的UIKit,在Flutter中有一个组件的概念(widget),下面的代码中Center
Text都继承于widgetflutter中没有图层的概念,只有一层。

  1. import 'package:flutter/material.dart';
  2. void main() {
  3. runApp(
  4. Center(
  5. child: Text(
  6. 'hello world',
  7. textDirection: TextDirection.ltr, // 阅读方向,不写则不显示
  8. ), // Text的构造
  9. ) // Center的构造
  10. );
  11. }

image.png

自定义Widget

有状态的stateful:可以更改
无状态的stateless:不能更改
继承StatelessWidget必须要实现一个方法:Widget build(BuildContext context)

  1. void main() {
  2. runApp(
  3. MyWidget());
  4. }
  5. //上面的可以写成箭头函数
  6. void main() => runApp(MyWidget());
  7. class MyWidget extends StatelessWidget {
  8. @override
  9. Widget build(BuildContext context) {
  10. return Center(
  11. child: Text(
  12. 'hello world',
  13. textDirection: TextDirection.ltr,
  14. ),
  15. );
  16. }
  17. }

�在Flutter中创建的对象没有说再赋值给某一个指针变量,一般都是直接构造使用。

  1. class MyWidget extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Center(
  5. child: Text(
  6. 'hello world',
  7. textDirection: TextDirection.ltr,
  8. style: TextStyle(
  9. color: Colors.yellow,
  10. fontWeight: FontWeight.bold,
  11. ),
  12. ),
  13. );
  14. }
  15. }

image.png

MaterialApp

Flutter里面提供了一个封装的比较好的MaterialApp

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(App());
  3. class App extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: MyWidget(),
  8. );
  9. }
  10. }
  11. class MyWidget extends StatelessWidget {
  12. @override
  13. Widget build(BuildContext context) {
  14. return Center(
  15. child: Text(
  16. 'hello world',
  17. textDirection: TextDirection.ltr,
  18. style: TextStyle(
  19. color: Colors.yellow,
  20. fontWeight: FontWeight.bold,
  21. ),
  22. ),
  23. );
  24. }
  25. }

image.png
运行之后发现出现了一个debug的标识符,打开MaterialApp的构造说明,发现里面有一个默认值this.debugShowCheckedModeBanner = true我们把它修改为false这个标识就没有了。

Scaffold

一般的开发中MaterialApp会搭配Scaffold来使用

  1. class App extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return MaterialApp(
  5. home: Scaffold(
  6. appBar: AppBar(
  7. title: Text(
  8. 'flutterDemo'
  9. ),
  10. ),
  11. body: MyWidget(),
  12. )
  13. );
  14. }
  15. }

此时MyWidget中的文字居中是相对于Body居中的。
image.png

模型对象

构造函数的参数使用{}修饰表示的是可选参数,可以参考下文档中的widget的构造

  1. class Car {
  2. Car({this.name, this.imageUrl});
  3. final String? name;
  4. final String? imageUrl;
  5. }
  6. // 测试数据
  7. final List<Car> datas = [
  8. const Car(
  9. name: '保时捷918 Spyder',
  10. imageUrl:
  11. 'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  12. ),
  13. const Car(
  14. name: '兰博基尼Aventador',
  15. imageUrl:
  16. 'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  17. ),
  18. const Car(
  19. name: '法拉利Enzo',
  20. imageUrl:
  21. 'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  22. ),
  23. const Car(
  24. name: 'Zenvo ST1',
  25. imageUrl:
  26. 'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  27. ),
  28. const Car(
  29. name: '迈凯伦F1',
  30. imageUrl:
  31. 'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  32. ),
  33. const Car(
  34. name: '萨林S7',
  35. imageUrl:
  36. 'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  37. ),
  38. const Car(
  39. name: '科尼赛克CCR',
  40. imageUrl:
  41. 'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  42. ),
  43. const Car(
  44. name: '布加迪Chiron',
  45. imageUrl:
  46. 'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  47. ),
  48. const Car(
  49. name: '轩尼诗Venom GT',
  50. imageUrl:
  51. 'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  52. ),
  53. const Car(
  54. name: '西贝尔Tuatara',
  55. imageUrl:
  56. 'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  57. )
  58. ];

ListView

scaffold抽取出来,同时body使用ListView()

  1. class App extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return MaterialApp(
  5. home: Home(),
  6. );
  7. }
  8. }
  9. class Home extends StatelessWidget {
  10. @override
  11. Widget build(BuildContext context) {
  12. return Scaffold(
  13. appBar: AppBar(
  14. title: Text(
  15. 'flutterDemo'
  16. ),
  17. ),
  18. );
  19. }
  20. }

listView的构造函数�ListView.builder(itemBuilder: itemBuilder)点击进去发现是一个回调required IndexedWidgetBuilder itemBuilder,继续点击IndexedWidgetBuilder发现这个
typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index)这个跟iOS中指定每一个indexPath的cell一样。所以我们来实现一个这样的方法

  1. class Home extends StatelessWidget {
  2. Widget _itemForRow(BuildContext context, int index) {
  3. return Text(datas[index].name!);
  4. }
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: AppBar(
  9. title: Text(
  10. 'flutterDemo'
  11. ),
  12. ),
  13. body: ListView.builder(
  14. itemBuilder: _itemForRow,
  15. itemCount: datas.length,
  16. ),
  17. );
  18. }
  19. }

image.png
这里介绍一个Container组件

  1. Widget _itemForRow(BuildContext context, int index) {
  2. return Container(
  3. color: Colors.white,
  4. margin: EdgeInsets.all(10),
  5. child: Image.network(datas[index].imageUrl!),
  6. );
  7. }

image.png
组件的排列只有三种:横着、竖着和叠着。
但是Container内部只能装有一个child,我们可以使用组件的排列的样式来布局

  1. Widget _itemForRow(BuildContext context, int index) {
  2. return Container(
  3. color: Colors.white,
  4. margin: EdgeInsets.all(10),
  5. child: Column(
  6. children: [
  7. Image.network(datas[index].imageUrl!),
  8. Text(datas[index].name!)
  9. ],
  10. )
  11. );
  12. }

image.png
加载的时候是异步加载的,因为首先显示的是文字等到图片资源回来之后更新排版。

TIPS

如果AS强退会锁死。当我们再次打开的时候会有点问题,所以一旦锁死的时候,我们可以来到这里/flutter/bin/cache/lockfile把这个删掉就行
Flutter中文网:中文网
Dart package: pub