Plugin
& Package
Package
: Dart中的第三方框架,里面只有Dart的代码Plugin
: 包含安卓和iOS原生的代码
Flutter
& RN
Flutter
:有一套自己的渲染引擎,不依赖原生UI,效率高,高度统一。RN
:基于原生的UI进行的包装,一旦原生的更新,马上也需要更新。
Widget
material.dar
类似于iOS中的UIKit
,在Flutter中有一个组件的概念(widget),下面的代码中Center
Text
都继承于widget
,flutter
中没有图层的概念,只有一层。
import 'package:flutter/material.dart';
void main() {
runApp(
Center(
child: Text(
'hello world',
textDirection: TextDirection.ltr, // 阅读方向,不写则不显示
), // Text的构造
) // Center的构造
);
}
自定义Widget
有状态的stateful
:可以更改
无状态的stateless
:不能更改
继承StatelessWidget
必须要实现一个方法:Widget build(BuildContext context)
void main() {
runApp(
MyWidget());
}
//上面的可以写成箭头函数
void main() => runApp(MyWidget());
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'hello world',
textDirection: TextDirection.ltr,
),
);
}
}
�在Flutter中创建的对象没有说再赋值给某一个指针变量,一般都是直接构造使用。
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'hello world',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.yellow,
fontWeight: FontWeight.bold,
),
),
);
}
}
MaterialApp
Flutter里面提供了一个封装的比较好的MaterialApp
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyWidget(),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'hello world',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.yellow,
fontWeight: FontWeight.bold,
),
),
);
}
}
运行之后发现出现了一个debug
的标识符,打开MaterialApp
的构造说明,发现里面有一个默认值this.debugShowCheckedModeBanner = true
我们把它修改为false这个标识就没有了。
Scaffold
一般的开发中MaterialApp
会搭配Scaffold
来使用
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(
'flutterDemo'
),
),
body: MyWidget(),
)
);
}
}
此时MyWidget
中的文字居中是相对于Body居中的。
�
模型对象
构造函数的参数使用{}修饰表示的是可选参数,可以参考下文档中的widget
的构造
class Car {
Car({this.name, this.imageUrl});
final String? name;
final String? imageUrl;
}
// 测试数据
final List<Car> 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
把scaffold
抽取出来,同时body使用ListView()
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'flutterDemo'
),
),
);
}
}
listView
的构造函数�ListView.builder(itemBuilder: itemBuilder)
点击进去发现是一个回调required IndexedWidgetBuilder itemBuilder
,继续点击IndexedWidgetBuilder
发现这个typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index)
这个跟iOS中指定每一个indexPath
的cell一样。所以我们来实现一个这样的方法
class Home extends StatelessWidget {
Widget _itemForRow(BuildContext context, int index) {
return Text(datas[index].name!);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'flutterDemo'
),
),
body: ListView.builder(
itemBuilder: _itemForRow,
itemCount: datas.length,
),
);
}
}
这里介绍一个Container
组件
Widget _itemForRow(BuildContext context, int index) {
return Container(
color: Colors.white,
margin: EdgeInsets.all(10),
child: Image.network(datas[index].imageUrl!),
);
}
组件的排列只有三种:横着、竖着和叠着。
但是Container
内部只能装有一个child
,我们可以使用组件的排列的样式来布局
Widget _itemForRow(BuildContext context, int index) {
return Container(
color: Colors.white,
margin: EdgeInsets.all(10),
child: Column(
children: [
Image.network(datas[index].imageUrl!),
Text(datas[index].name!)
],
)
);
}
加载的时候是异步加载的,因为首先显示的是文字等到图片资源回来之后更新排版。
TIPS
如果AS强退会锁死。当我们再次打开的时候会有点问题,所以一旦锁死的时候,我们可以来到这里/flutter/bin/cache/lockfile
把这个删掉就行Flutter
中文网:中文网Dart package
: pub