1、基础组件
文本,Text
按钮,TextButton等
图片图标,Image、Icon
输入框 和 表单,TextField、Form
进度指示器,LinearProgressIndicator、CircularProgressIndicator
单选框和复选框,Switch、Checkbox
2、布局之容器组件
装饰,DecoratedBox、BoxDecoration等,如颜色、背景、边框、渐变、阴影等
复合容器,Container,它是结合align、padding、margin、box、变换等多种功能。
尺寸,主要是设置页面的宽高大小 或 宽高比例。
宽高SizedBox、AspectRatio、LimitedBox、FractionallySizedBox等;
限制类ConstrainedBox、BoxConstraints、UnconstrainedBox等
对齐,Align
居中,Center
填充,Padding
剪裁,ClipOval、ClipPath、ClipRect、ClipRRect等
变换(如旋转等),Transform
适配(如换行,即超出父组件边界约束),FittedBox
3、布局组件
线性布局,Row、Column
弹性布局,Flex、Expanded
流式布局(子元素自动换行),Wrap、Flow
层叠布局,Stack、Positioned
4、复合组件(滚动、列表等)
简单滚动列表(类似iOS的ScrollView),SingleChildScrollView
列表,ListView、AnimatedList
二维列表(类似iOS的CollectionView),GridView
自定义滚动列表,CustomScrollView、NestedScrollView
TabBar,TabBarView
5、交互组件
手势,GestureDetector、GestureRecognizer等相关类
动画,Animation、Curve、AnimationController、Tween、Ticker等相关类
一、组件基类
abstract class DiagnosticableTree with Diagnosticable
abstract class Widget extends DiagnosticableTree
二、普通组件
abstract class StatelessWidget extends Widget
abstract class StatefulWidget extends Widget
// 状态
abstract class State<T extends StatefulWidget> with Diagnosticable
三、布局组件
// 布局类基类
abstract class RenderObjectWidget extends Widget
// 包含一个子Widget,如:ConstrainedBox、DecoratedBox等
abstract class SingleChildRenderObjectWidget extends RenderObjectWidget
通过属性child关联单个widget
// 包含多个子Widget,一般都有一个children参数,接受一个Widget数组。如Row、Column、Stack等
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget
通过属性children关联多个widget。
// Widget树的叶子节点,用于没有子节点的widget,通常基础组件都属于这一类,如Image。
abstract class LeafRenderObjectWidget extends RenderObjectWidget
// Widget代理
abstract class ProxyWidget extends Widget
abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget
// 弹性布局,flex
class Flex extends MultiChildRenderObjectWidget
class Flexible extends ParentDataWidget<FlexParentData>
class Expanded extends Flexible
// 线性布局
class Column extends Flex
class Row extends Flex
// 设置padding
class Padding extends SingleChildRenderObjectWidget
// SizedBox 设置宽高
class SizedBox extends SingleChildRenderObjectWidget
// Spacer 基于flex的空白,内部基于Expanded实现的,它只是Expanded的一个包装类
class Spacer extends StatelessWidget
// 流式布局
class Wrap extends MultiChildRenderObjectWidget
class Flow extends MultiChildRenderObjectWidget
// 层叠布局
class Stack extends MultiChildRenderObjectWidget
class Positioned extends ParentDataWidget<StackParentData>
// 对齐与相对定位
class Align extends SingleChildRenderObjectWidget
class Center extends Align
/* 容器类组件*/
// 填充
class Padding extends SingleChildRenderObjectWidget
// 尺寸大小限制
class ConstrainedBox extends SingleChildRenderObjectWidget
class SizedBox extends SingleChildRenderObjectWidget
class AspectRatio extends SingleChildRenderObjectWidget
class FractionallySizedBox extends SingleChildRenderObjectWidget
class LimitedBox extends SingleChildRenderObjectWidget
class UnconstrainedBox extends StatelessWidget
// 装饰类组件
class DecoratedBox extends SingleChildRenderObjectWidget
class BoxDecoration extends Decoration
// 组合类容器
class Container extends StatelessWidget
/* Material常用组件类 */
class Scaffold extends StatefulWidget
abstract class PreferredSizeWidget implements Widget
class AppBar extends StatefulWidget implements PreferredSizeWidget
class Drawer extends StatelessWidget
class FloatingActionButton extends StatelessWidget
class BottomNavigationBar extends StatefulWidget
class BottomNavigationBarItem
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
//使用字符串插值($或者${name}) 来打印包含变量的字符串
void main() {
String name = "Alice";
int age = 25;
print("My name is $name and I am $age years old.");
}
Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型
var t = "hi world";
// 下面代码在dart中会报错,因为变量t的类型已经确定为String,
// 类型一旦确定后则不能再更改其类型。
t = 1000;
dynamic与Object声明的变量都可以赋值任意对象,且后期可以改变赋值的类型,不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错
dynamic a;
Object b = "";
main() {
a = "";
printLengths();
}
printLengths() {
// 正常
print(a.length);
// 报错 The getter 'length' is not defined for the class 'Object'
print(b.length);
}
不可更改变量,使用 final 或 const,两者区别在于:const 变量是一个编译时常量(编译时直接替换为常量值),final变量在第一次使用时被初始化。被final或者const修饰的变量,变量类型可以省略
//可以省略String这个类型声明
final str = "hi world";
//final String str = "hi world";
const str1 = "hi world";
//const String str1 = "hi world";
int i = 8; //默认为不可空,必须在定义时初始化。
int? j; // 定义为可空类型,对于可空变量,我们在使用前必须判空。
// 如果我们预期变量不能为空,但在定义时不能确定其初始值,则可以加上late关键字,
// 表示会稍后初始化,但是在正式使用它之前必须得保证初始化过了,否则会报错
late int k;
k=9;
int age = 12;
double price = 10.0;
String name = "张飞";
String name2 = '张飞';//单双引号没区别
//多行字符串
String name3 = '''
张飞
诸葛亮
廉颇
''';
bool sex = false;
var nameList = ["张飞","关羽","刘备"];
List<String> nameList2 =["张飞","关羽","刘备"];
List<String> nameList3 = [];
var nameSet = {"张飞","关羽","刘备"};
Set<String> nameSet2 = {"张飞","关羽","刘备"};
Set<String> nameSet3 = {};
var map = {"name": "张飞", "height": 1.88};
Map<String, Object> map2 = {"name": "张飞", "height": 1.88};
Map<String, Object> map3 = {};
//无返回值
void fun1(){
}
//有返回值
int fun2(){
return 1;
}
//单行简写
int fun3()=>1;
//返回类型 void 和 int 也可以省略
注意, 只有可选参数才可以有默认值, 必须参数不能有默认值
//命名可选参数: {param1, param2, ...}
//位置可选参数: [param1, param2, ...]
//命名可选参数
optionParamsFun1(String name, {int age = 10, double height = 1.8}) {
print('$name,$age,$height');
}
//required 标识为必选参数
optionParamsFun2(String name, {int age = 10,required double height}{
print('$name,$age,$height');
}
//调用
optionParamsFun1('yh');
optionParamsFun1('yh',age: 20);
optionParamsFun1('yh',age: 20,height: 1.88);
// yh,10,1.8
// yh,20,1.8
// yh,20,1.88
//位置可选参数
optionParamsFun1(String name, [int age = 10, double height = 1.8]) {
print('$name,$age,$height');
}
optionParamsFun1('yh');
optionParamsFun1('yh', 20);
optionParamsFun1('yh', 20, 1.88);
// yh,10,1.8
// yh,20,1.8
// yh,20,1.88
//调用
test(){
getFunc();
test2(foo("张飞"));
}
//1.定义一个函数
foo(String name) {
print(name);
}
//2.将函数作为另一个函数的返回值
getFunc() {
return foo;
}
//3.将函数作为另一个函数的参数
test2(Function func) {
func("func");
}
void main3() {
var numbers = [1, 2, 3, 4, 5];
//遍历
numbers.forEach((element) {
print(element);
});
// 使用匿名函数对列表中的每个元素进行平方
var squaredNumbers = numbers.map((number) => number * number);
print(squaredNumbers.toList()); // 输出: [1, 4, 9, 16, 25]
}
var num = 7;
print(num / 3);//除 2.3333
print(num ~/ 3);//整除 2
print(num % 3);//取余 1
test1(){
//当变量不为null时使用变量,
var name = 'lucy';
name ??= 'sala';
print(name);//lucy
//当变量为null时,后面的值将被赋值给变量
var name2 = null;
name2 ??= 'Toms';
print(name2);//Toms
//如果a>10,b就等于a,否则b = 11
int a = 5;
int b = a>10?a:11;
}
//当变量不为null时使用变量,
var name = 'lucy';
print(name ?? 'sala');//lucy
//当变量为null时使用后面的值
var name2 = null;
print(name2 ?? 'Toms');//Toms
as 将对象强制转换为特定类型。
is 和 is! 判断变量是不是某种类型。
class Person {
String name = 'Tom';
void eat() {
}
void drink() {
}
void sleep() {
}
}
//..可以连续访问方法和属性(类似返回值为Person)
void test2(){
Person()..name..eat()..drink()..sleep();
}
void test2(){
List<String> names = ['Alice', 'Bob', 'Charlie'];
//普通遍历
for (int i = 0; i < names.length; i++) {
print(names[i]);
}
//forEach 遍历
names.forEach((name) {
print(name);
});
//遍历的同时转换为大写
List<String> upperCaseNames = names.map((name) => name.toUpperCase()).toList();
print(upperCaseNames);
//in 遍历
for (String name in names) {
print(name);
}
Set<String> mySet = {'A', 'B', 'C'};
for (var item in mySet) {
print(item);
}
mySet.forEach((item) {
print(item);
});
//转为list然后遍历
List<String> myList = mySet.toList();
for (var item in myList) {
print(item);
}
Map<String, dynamic> myMap = {'key1': 'value1', 'key2': 'value2'};
//遍历键值对
for (var entry in myMap.entries) {
print('${entry.key}: ${entry.value}');
}
//遍历键值对
myMap.forEach((key, value) => print('$key: $value'));
//遍历键
myMap.keys.forEach((key) => print(key));
//遍历值
myMap.values.forEach((value) => print(value));
}
while :先检查条件,再执行
int i = 0;
while (i < 5) {
print(i);
i++;
}
do-while :先执行,再检查
int i = 0;
do {
print(i);
i++;
} while (i < 5);
for循环中,我们可以使用"break"关键字来提前结束循环
for (int i = 0; i < 10; i++) {
if (i == 5) {
break;
}
print(i);
}
使用"continue"时,会跳过当前迭代的剩余代码,直接进入下一次迭代
for (int i = 0; i < 10; i++) {
if (i % 2 != 0) {
continue;
}
print(i);
}
void main(List<String> args) {
//实例化
var p1 = Person();
p1.eat();
}
class Person {
String name = 'Tom';
void eat() {
String name = 'lucy';
print(name);//lucy
print(this.name);//Tom
}
}
Dart为类提供了默认的构造函数,当有了自己的构造函数,默认的构造方法将会失效,
在Flutter中,构造方法有几种方式:默认、命名、工厂、常量
默认构造方法:这是最常见的构造方法,它没有任何参数。例如:
复制代码
class MyClass {
MyClass() {
// 构造方法的逻辑
}
}
命名构造方法:使用命名构造方法可以为类提供多个不同的构造方法,每个构造方法可以有不同的参数。例如:
class MyClass {
MyClass() {
// 默认构造方法
}
MyClass.namedConstructor() {
// 命名构造方法
}
}
在使用命名构造方法时,可以通过指定构造方法的名字来调用它。
带参数的构造方法
class MyClass {
int value;
MyClass(int value) {
this.value = value;
}
}
工厂构造方法:可以返回一个已经存在的实例,或者返回一个子类的实例。例如:
class MyClass {
factory MyClass() {
return _singleton;
}
MyClass._internal();
static final MyClass _singleton = MyClass._internal();
}
在这个例子中,工厂构造方法返回一个单例实例。
常量构造方法,成员变量必须是final修饰,使用const关键字实例化
class Person {
final String name;
final int age;
const Person(this.name,this.age);
}
void main(List<String> args) {
print(Colors.red);
//枚举属性 index索引,从0开始;values包含所有枚举值的list
print(Colors.red.index);
print(Colors.values);
}
enum Colors {
red,
green,
blue
}
//写法一
class Singleton {
const Singleton._internal();
factory Singleton() => const Singleton._internal();
}
Singleton single = Singleton();
//写法二
class Singleton {
Singleton._privateInstance();
static final Singleton instance = Singleton._privateInstance();
factory Singleton(){
return instance;
}
}
//使用
Singleton single = Singleton();
//写法三
class Singleton {
Singleton._internal();
static final Singleton _instance = Singleton._internal();
static Singleton getInstance() {
return _instance;
}
}
//使用
var instance = Singleton.getInstance();
//写法四
class Singleton {
// 私有化构造方法
Singleton._privateConstructor();
static final Singleton _instance = Singleton._privateConstructor();
//同下 : static Singleton get instance => _instance;
static Singleton get instance { return _instance;}
}
//使用
var instance = Singleton.instance;
//写法五
class Singleton {
Singleton._privateConstructor();
static final Singleton instance = Singleton._privateConstructor();
}
//使用
void mian(){
var instance = Singleton.instance;
var instance2 = Singleton.instance;
print(instance == instance2);
}
class Person {
var name;
set setName(String nameStr){
name = nameStr;
}
String get getName{
print('getName');
return name;
}
}
Person p = Person();
p.name = '123';
print(p.getName);//getName 123
class Person {
var name;
Person(this.name);
set setName(String nameStr){
name = nameStr;
}
String get getName{
print('getName');
return name;
}
eat() {
}
run(){
print('person run');
}
}
class Student extends Person {
int age;
Student.withAge(String name, this.age): super(name);
@override
run() {
// TODO: implement run
super.run();
print('student run');
}
}
test(){
Student s = Student.withAge('Tom', 18);
s.name = '123';
print(s.getName);//getName 123
s.run();
//person run
// student run
}
abstract class Animal {
eat();
run(){
}
}
class Dog extends Animal {
@override
eat() {
// TODO: implement eat
}
}
class SmallDog extends Dog {
@override
run() {
// TODO: implement run
}
}
Dart中的接口比较特殊, 没有一个专门的关键字来声明接口.
默认情况下,定义的每个类都相当于默认也声明了一个接口,可以由其他的类来实现(因为Dart不支持多继承)
class Eat {
eat() {
}
}
abstract class Run {
run() {
}
}
class Animal implements Eat,Run {
@override
run() {
// TODO: implement run
}
@override
eat() {
// TODO: implement eat
throw UnimplementedError();
}
}
除了通过class定义类,也可以通过mixin定义一个类。
通过mixin定义的类用于被其他类混入使用,通过with关键字来进行混入。
mixin Eat {
eat();
}
mixin Run {
run(){
}
}
class Animal with Eat,Run {
@override
eat() {
// TODO: implement eat
}
// @override
// run() {
// // TODO: implement run
// }
}
//泛型写法
// List