1 Star 1 Fork 1

不会打字的程序猿 / Flutter入门案例

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

Dart

Dart变量

dart是一个强大的脚本类语言,可以不预先定义变量类型,会自动推导

var str='hello';
String str='this is var';
  1. 使用var的时候,如果只声明,不赋值,它所能识别的数据类型是dynamic
  2. 声明加赋值,那么会自动对赋值的数据进行数据类型的识别
  var a;
  a = 'afas';
  a = {};
  a = 1;
  //这样不会报错
  var a=1;
  a = 'afas';
  a = {};
//报错

变量命名规则

  1. 变量名称必须是数字,字母,下划线和美元符号组成
  2. 不能以数字开头
  3. 不能是保留字和关键字
  4. 变量名称区分大小写

常量(final和const)

  1. const和final都必须初始就赋值
  2. final是运行时常量的特性,可以是运行后的结果,例如函数返回值
  3. const是编译期常量,不能是运行后的结果
  4. final是惰性初始化,即在运行时第一次使用前才初始化
  5. final如果是数组等类型(除去基本数据类型)是可以修改某项的,const完全不行
// main(){
//   print('你好dart')
// }

//表示main方法没有返回值
// void main(){

// }

main(List<String> args) {
  var str='hello dart';
  String str1='hello dart';
  int num=129;
  var num1=129;
  print(str);

  final t=new DateTime.now();//正确,final具有惰性初始化的特性
  // const t1=new DateTime.now();//错误
}
main(List<String> args) {
  //可以正常修改
  final a = [1, 2];
  a[0] = 20;
  print(a[0]);//20
  //下面修改const的值报错
  const a1 = [1, 2];
  a1[0] = 20;
}

数据类型

  • Number(数值): int double
  • Strings(字符串):String
  • Booleans(布尔):bool
  • List(数组):Dart中数组其实是列表对象
  • Maps(字典):Map
  • Set:Set 无序去重,所以不能通过索引取出
main(List<String> args) {
  //多行定义:三引号(单或者双都行)
  String s1='''
    this is 
    hello 
    world
  ''';
  //原样输出:能正常输出\n而不换行
  String s11=r"hello \n dart";
  
  
  print(s1);
  //字符串拼接
  String s2='dart';
  print("$s1 $s2");
  print(s1+s2);

  //数值类型
  int n1=123;
  double n2=3.14;

  //布尔类型
  bool b=true;

  //数组类型
  //方式一
  List l1=['a',1];
  print(l1.length);
  print(l1[0]);
  //方式二
  List l2=new List();
  l2.add('1');
  l2.add(123);

  List l3=new List<String>();
  // l3.add(1); 不行,如果约定了类型,则必须类型符合

  //字典
  //方式一
  Map m1={
    'name':'zq',
    'age':20,
    'work':['1',20],
  };
  print(m1); //{name: zq, age: 20}
  print(m1['name']); //zq   只能通过该种方式访问,不能通过点方式

  //方式二
  var p=new Map();
  p['age']=20;
  print(p);

  //判断数据类型: is

  var b2=m1['work'][0] is String;
  print(b2); //true
}

不常用数据类型

  • Runes:Rune是UTF-32编码的字符串,可以通过文字转换成符号表情或者特定的文字
main(List<String> args) {
  var c1='\u{1f44f}';
  Runes c2=new Runes('\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
  print(c1);
  print(c1.codeUnits);
  print(c1.runes.toList());
  print(new String.fromCharCodes(c2));
}
  • Symbols: Symbol对象表示在Dart程序中声明的运算符或标识符。您可能永远不需要使用符号, 但它们对于按名称引用标识符的API非常有用,因为缩小会更改标识符名称而不会更改标识符符号。 要获取标识符的符号,请使用符号文字,它只是#后跟标识符:
#radix
#bar

运算符

  • 算术运算符: + - * / ~/(取整) %
  • 关系运算符: == != > < >= <=
  • 逻辑运算符: ! || &&
  • 赋值运算符 := ??= += -= *= /= %= ~/=
main(List<String> args) {
  int a=13;
  int b=5;
  print(a~/b);//2
  print(a%b);//3

  int b1; //如果b1在初始化时候赋值,则下面的??=无效
  b1??=23; //表示如果b为空的话把23赋值给b
  print(b1);//23
}

条件表达式

  • if else switch case
  • 三目运算符
  • ??运算符
main(List<String> args) {
  bool flag=true;
  if(flag){

  }else{

  }

  int a=flag?10:20;
  print(a);

  var a1=22;
  var b=a1??10;
  print(b);//22
}

类型转换

  • Number转换成String toString()
  • String转换成Number parse()
  • isEmpty:判断字符串是否为空,是属性不是函数
main(List<String> args) {
    String s1 = '1213.2';
  try {
    int i1 = int.parse(s1);
    double i2=double.parse(s1);
  } catch (e) {
    print(e);
  }
  print(s1.isEmpty); //false
  print(s1==null);//判断是否为空
}

循环语句

main(List<String> args) {
   for (var i = 0; i < 10; i++) {
     print(i);
   }
  while (true) {
    //break只能跳出一层循环
    break;
  }

  do {
    break;
  } while (true);
}

switch(sex){
  case 0
  break;
  default:
  break;
}

集合类型

List属性


常用属性:

  • length:长度
  • reversed:翻转
  • isEmpty:是否为空
  • isNotEmpty:是否不为空

常用方法:

  • add 增加
  • addAll 拼接数组
  • indexof 查找 传入具体值
  • remove 删除 传入具体值
  • removeAt 删除 传入具体值
  • fillRange 修改
  • insert(index,value) 指定位置插入
  • insertAll(index,list) 指定位置插入list
  • toList 其他类型转换成list
  • join list转换成字符串
  • split 字符串转换成list

main(List<String> args) {
  List l1 = [1, 2, 3, "hello"];
  List l2 = const [1, 2, 3];
  // l2[0] = 5;//不能修改
  List l3 = <int>[1, 2, 3];
  // l3[0] = 'a';赋值不能修改类型
  List l4 = new List();//输出[]
}

Map属性


常用属性:

  • keys 获取所有key值
  • values 获取所有value值
  • isEmpty 是否为空
  • isNotEmpty 是否不为空

常用方法:

  • remove({key}) 删除指定key的数据
  • addAll({...}) 合并映射 给映射内增加属性
  • containsValue 查看映射内的值 返回true/false

main(List<String> args) {
  var b = 12;
  Map m1 = {"a": 1, b: 12};
  //不可变Map
  Map m2 = const {"f1": "a"};
  //构造创建
  Map m3 = new Map();
}

set map list通用方法

  • forEach 遍历
  • map 遍历修改,病返回新数组
  • where 类似js的filter
  • any 只要有一个满足条件就返回true
  • every 必须每个数据都满足条件才返回true
main(List<String> args) {
  var s = new Set();
  s.add(1);
  s.add(11);
  s.add(1);
  print(s.toList()); //[1, 11]

  List l = ['测试', 1];
  s.addAll(l);
  print(s.toList()); //[1, 11, 测试]

  var m = {'age': 12, 'name': 'zs'};
  print(m.keys.toList()); //[age, name]

  //遍历list可以用for in
  for (var item in l) {}
  //通用方法
  l.forEach((value){
    print(value);
  });
  var nl=l.map((value){
    return value*2;
  });
  print(nl); //(测试测试, 2)
  print(nl.toList()); //[测试测试, 2]


  var t1=[1,2,3,4,5,6];
  var b=t1.any((value){
    return value>3;
  });

  print(b); //true
}

函数相关

  • 命令参数
  • 默认参数
  • 函数作为参数
  • 可选参数
main(List<String> args) {
  var i=test(10);
  print(i);
  //命名函数要这样传值
  test1('zq',age:30);

  test2(hello);
}
/**
 * 【】内部是可选参数,可不传入
 * 可选参数内部可以默认赋值
    可选参数可以是被[]包裹或者{}也是等效
 */
int test(int num,[int sex=30,String name]){
  if(name==null||sex==null){
    return -1;
  }
  print('自定义方法');
  return num;
}
/**
 * 命名参数
 */
void test1(String name,{int age,String sex='男'}){
  print(sex);
}

/**
 * 把方法当作参数
 */

void test2(fn){
  fn();
}

void hello(){
  print('hello');
}
  • 箭头函数
  • 匿名函数
  • 闭包:全局变量常驻内存但是污染全局,局部变量不常驻内存但是会被回收;闭包实现常驻内存且不污染全局
main(List<String> args) {
  List l = ['平', '香蕉'];
  l.forEach((value)=>{
    //箭头函数
  });

  //匿名方法
  var prin=(){
    print('123');
  };
  prin();


  //自执行
  ((){
    print('这里是自执行方法');
  })();

  //闭包
  fn(){
    var a=1;
    return(){
      a++;
      print(a);
    };
  }
  var b=fn();
  b();//2
  b();//3
  b();//4
}

回调函数

main(List<String> args) {
  List l1 = ["a", "b", "c"];
  l1.forEach(print); //输出 a  b  c  print是系统内置的输出函数
  print(strPepeat("lll")); //lllllllll

  List l11 = ["h", "e", "l"];
  print(listTimes(l11, strPepeat)); //[hhh, eee, lll]
}

String strPepeat(str) => str * 3;
//传递回到函数,依然可以为传递的回调函数返回值定义类型

//可以添加String s也可以var也可以不写类型
//List listTimes(List list, String fn(String s)) 
List listTimes(List list, String fn(s)) {
  for (var i = 0; i < list.length; i++) {
    list[i] = fn(list[i]);
  }
  return list;
}

类与对象

Dart是以们使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类。

基本案例

//引入
import 'person.dart';
main(List<String> args) {
  //调用默认构造函数
  var p = new Person('男');
  print(p);
  p.getInfo(); //zq--30

  //调用命名构造函数:这种方式不会触发默认构造函数的sex初始化
  var p1 = new Person.test();
  p1.getInfo(); //打印的sex为null;
}


class Person {
  String sex;
  //构造函数-也被称为类的重写
  // Person(String sex){
  //   this.sex=sex;
  // }
  //构造函数简写
  Person(this.sex);

  //命名构造函数可以有多个
  Person.test() {
    print('命名构造函数');
  }

  String name = 'zq';
  int age = 30;
  void getInfo() {
    print("${this.name}--${this.age}--${this.sex}");
    //如果是单个字符,省略{}大括号
    print("a$a");
  }
}
main(List<String> args) {
  var p = new Person();
  print(p.sum(1, 2)); //3
}

class Person {
//主要:可以这么定义类中的方法
  Function sum = (a, b) {
    return a + b;
  };
}
  • 私有属性/方法:前面加_
class Person {
  //加上下划线就是私有属性,但是必须定义私有属性
  //和使用私有属性不在同一个文件,例如此时如果main
  //方法和当前类再一个文件,则私有属性其实还是公有
  String _sex;
  Person(this._sex);
  void _getInfo() {
    print("${this._sex}");
  }
}

import 'person.dart';
main(List<String> args) {
  var p = new Person('男');
  // print(p._sex); 私有属性无法使用
  // p. _getInfo();私有方法无法使用
}
  • set get

java中一般都是定义方法,使用get/set,dart中有内置属性,直接在前面添加set/get 即可

import 'person.dart';
main(List<String> args) {
  var p = new Person(1);
 print( p.chengyi);//20
 //注意set虽然有()但是还是赋值
 p.haha=20;
 print(p.chengyi);//400
}

class Person {
  //注意此时,可以是num类型
  num age;
  Person(this.age);
  set haha(value){
    this.age=value;
  }
  get chengyi{
    return this.age*20;
  }
}
  • 构造前初始化
class Person {
  num age;
  //Dart中我们也可以再构造函数运行之前初始化实例,如下
  Person():age=20{

  }
  // Person():age=20;这样也行
}
  • 静态成员
class Person {
  static  num age=30;
  static void show(){
    print(age);
  }
}

import 'person.dart';
main(List<String> args) {
  //静态属性
  print(Person.age);
  //静态方法
  Person.show();
}
  • 操作符

? 条件运算符

as 类型转换

is 类型判断

.. 级联操作


import 'person.dart';
main(List<String> args) {
 Person p;
 //正常情况下,此时p没有初始化调用方法肯定报错加上?
 //代表p不为Null才执行,否则不执行
  p?.show();

  var p1=new Person(30);
  //判断p对象是否属于person类
  if(p1 is Person){}


  // var p2='';这种会直接定义类型,下面赋值person报错
  var p2;//但是这种不会报错
  p2='';
  p2=new Person(30);
  p2.show();//老版本这样调用报错,新版本直接使用即可
  (p2 as Person).show();//老版本这样调用,相当于强转


  //级联操作,省略代码
  var p3=new Person(30);
  p1..age=50
    ..show();
}

class Person {
  num age=30;
  Person(this.age);
  show(){
    print(this.age);
  }
}
  • 类的继承

  1. 子类使用extends关键词来继承父类
  2. 子类会继承父类的公有的属性和方法,但不会继承构造函数
  3. 子类能复写父类的方法 getter和setter

main(List<String> args) {
  var s = new Student('asd',20);
  s.show();
}

class Person {
  String name;
  Person(this.name);
  show() {
    print(this.name);
  }
  Person.now(this.name);
}

class Student extends Person {
  int age;
  // Student(String name) : super(name);
  //也可以继承父类的命名构造
  // Student(String name) : super.now(name);
  Student(String name,int age) : super(name){
    this.age=age;
  }

  @override //可写可不写但是建议加上
  show(){
    //super.show(); 子类可以通过这种方式调用父类的方法
    print('子类重写父类的方法');
  }
}

抽象类 多态和接口

  • 抽象类:使用abstract关键字定义,抽象类不可实例化
  • 多态: 父类引用指向不同的子类
main(List<String> args) {
  //多态
  Person p = new Student();
  Person p1 = new Teacher();
  p.show();
  p1.show();
}

abstract class Person {
  show();//抽象方法
  printInfo(){
    print('抽象类可以有非抽象方法');
  }
}

class Student extends Person {
  @override
  show() {
   print('子类实现父类的抽象方法');
  }
}
class Teacher extends Person {
  @override
  show() {
   print('haha');
  }
}
  • 接口

dart中的接口没有interface关键字定义接口,都是普通类或者抽象类,同样使用implements关键字实现。dart接口如果实现的类是普通类,会将普通类和抽象中的属性的方法全部重写一遍。因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现java接口那样的方法,一般都是使用抽象类。

main(List<String> args) {
  var  s= new Student('zq');
  s.show();
}

abstract class Person {
  String name;
  show();
  printInfo() {
    print('抽象类可以有非抽象方法');
  }
}

class Student implements Person {
  @override
  String name;

  Student(this.name);

  @override
  show() {
    print('子类实现父类的抽象方法');
  }

  @override
  printInfo() {
    print('hehe');
  }
}
  • 一个类可以实现多个接口
main(List<String> args) {
  var  s= new Student();
  s.show();
  s.run();
}

abstract class Person {
  show();
}
abstract class Boy {
  run();
}

class Student implements Person,Boy {
  @override
  show() {
    print('show');
  }

  @override
  run() {
    print('run');
  }
}
  • mixins实现类似多继承的功能

使用with关键字


  1. 作为mixins的类只能继承自Object,不能继承其他类
  2. 作为mixins的类不能有构造函数
  3. 一个类可以minix多个mixins类
  4. mixins绝不是继承也不是接口,是一个新特性

main(List<String> args) {
  var  c= new C();
  c.show();
  c.run();
  c.eat();

  print(c is C); //true
  print(c is B); //true
  print(c is D); //true
}
 class A {
  show(){
    print('show');
  }
}
 class B {
  run(){
    print('eun');
  }
}
class D {
  eat(){
    print('eat');
  }
}

class C extends A with B,D {
  @override
  show() {
    print('showc');
  }

  @override
  run() {
    print('runc');
  }
}
> A不是minix类可以有构造函数,B,D不能有构造函数是minix类。
而且不论是继承还是minix都不见得需要重写父级的方法。
如果A,B,D出现同名属性或者方法,使用D,所以是有顺序优先级的。

范型

  • 范型方法
main(List<String> args) {
  var p = new Person();
  p.getData<String>('asda');
  p.getData<num>(123);
}

class Person {
  //范型方法
  T getData<T>(T data) {
    return data;
  }
}
  • 范型类
main(List<String> args) {
  var p = new Person<String>();
  p.add('asdas');
}

class Person<T>{
  List list=new List<T>();
  add(T value){
    this.list.add(value);
  }
}
  • 范型接口
main(List<String> args) {
  var f=new FileCache<String>();
  f.getByKey('asd');
}

class FileCache<T> implements Cache<T> {
  @override
  getByKey(String key) {}

  @override
  void setByKey(String key, T value) {}
}

abstract class Cache<T> {
  getByKey(String key);
  void setByKey(String key, T value);
}

async和await

main(List<String> args) async{
  var r=await test();
  print(r);
}

test() async{
  return 'Hello';
}

使用第三方包

https://pub.dev/

  • 新建pubspec.yaml文件
name: test
description: A new test
dependencies: 
  • 去pub官网查询http
dependencies:
  http: ^0.12.0+2

粘贴到pubspec.yaml文件中

  • 在vscode中保存该文件会自动下载
  • 也可以进入对应文件夹然后执行pub get
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;

main(List<String> arguments) async {
  var url = "https://api.douban.com/v2/movie/imdb/tt0111161?apikey=0df993c66c0c636e29ecbb5344252a4a";
  var response = await http.get(url);
  if (response.statusCode == 200) {
    var jsonResponse = convert.jsonDecode(response.body);
    print("请求成功---$jsonResponse");
  } else {
    print("请求失败: ${response.statusCode}.");
  }
}

包别名,局部导入和隐藏导入

import 'lib/Persion1' as P1;
import 'lib/Persion2' as P2;

在两个文件中都是Person对象,则下面使用的时候
直接new Person就不知道用的是那个,所以通过别名导入

var pp1=new P1();
var pp2=new P2();


import 'lib/Methods' show f1,f2;
只导入f1  f2两个函数


import 'lib/Methods' hide f1;
除了f1其他函数都导入

Flutter

  • 首先安装dart,然后安装Flutter环境
  • 一定要配置镜像,否则后续步骤会很慢甚至卡死
  • JDK以及AS环境(AS需要安装flutter插件,创建项目时候使用)
  • 主要如果机器上面有IDEA的话,可能flutter doctor会提示flutter没有安装,最好也安装(虽然没啥用处)
  • flutter -h: flutter的帮助
  • flutter doctor:检查flutter环境是否配置好
  • 可能需要:这行指令也是执行flutter doctor的时候提示的,其实就是更新licenses。 flutter doctor --android-licenses
  • AS创建项目:new flutter project
  • vscode打开AS创建的项目,并执行flutter run或直接使用vscode-运行- 启动调试-热重载(推荐)
flutter run  需要按r/R 很麻烦

热重载不是全能的:(替代方式是flutter  run)
1. 全局变量初始化器
2. 静态字段初始化器
3. app的main()方法

所以一般调试界面UI才使用热重载

但是可以通过vscode调试的时候的restart按钮实现R同样效果,所以flutter run可以直接放弃

入门案例

//引入material组件库,里面规定了很多组件,还规定了移动端UI渲染的一些规范
import 'package:flutter/material.dart';

//定义入口函数
//runApp是系统函数,用来执行组件渲染
void main() => runApp(
    //MyApp是一个组件,命令是系统规定好的,修改起来比较麻烦,所以按照约定来即可
    MyApp());

//所有组件都是一个类,类型是Widget
//StatefulWidget:有状态组件/动态组件
//StatelessWidget:无状态组件/静态组件
class MyApp extends StatelessWidget {
  //每一个静态组件都需要传递一个build函数
  //build是系统规定好的渲染函数,返回值一个组件
  @override
  Widget build(BuildContext context) {
    //引入了material.dart那么此处必须是MaterialApp开始
    return MaterialApp(
      //不会显示在app上面,页面收起来时候可以看到
      title: 'Flutter Demo',
      //规定当前组件的默认颜色
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      //传递自定义组件
      home: MyHomePage(title: '这是一个测试'),
    );
  }
}

//每个组件类,首字母必须大写
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    //Scaffold:脚手架工具,可以调用很多的组件
    return Scaffold(
      //导航
      appBar: AppBar(
        title: Text(widget.title),
      ),
      //Center也是一个组件,相当于内容居中
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display2,
            ),
          ],
        ),
      ),
      //右侧悬浮按钮
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
  • 脚手架

Scaffold,没有这个界面一片漆黑,当然也可以一点点排列但是不方便,而且不适宜复用

import 'package:flutter/material.dart';

class SelfText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //不用脚手架黑色一片
    // return Container(
    //   child: Text('Hello'),
    // );
    return Scaffold(
      appBar: AppBar(
        title: Text("Hello"),
      ),
      body: Center(
        child: Text(
          "Hello Flutter",
          style: TextStyle(
              fontSize: 20.0, color: Colors.pink, fontWeight: FontWeight.w700),
          overflow: TextOverflow.ellipsis, //溢出点点点
          maxLines: 1,
        ),
      ),
    );
  }
}
  • Image
import 'package:flutter/material.dart';

class SelfImage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        // child: Image(
        //     image: NetworkImage(
        //         "https://www.freesion.com/images/13/6cae05cf64b85fca7a5f207b7a4159cd.png")),

        //对宽高不满意使用Container
        child: Container(
          width: 200,
          height: 100,
          child: Image(
              //图片伸展方式
              fit: BoxFit.cover, //图片完全伸展开,不拉伸,但是可能会裁切
              // image: NetworkImage(
              //     "https://www.freesion.com/images/13/6cae05cf64b85fca7a5f207b7a4159cd.png")),

              //引入本地图片
              //1. 在项目根目录建立文件夹 images
              //2. 在项目yaml这个文件里面进行一些配置,本地图片都需要在yml文件里面一个个添加
              //  assets:
              // - images/1.png
              image: AssetImage("images/1.png")), //必须和配置文件里面路径一致
        ),
      ),
    );
  }
}
  • Container

当组件需要修改的属性没法直接在组件内部提示修改的时候,则外层包裹一层Container,例如边距,背景色什么的。

import 'package:flutter/material.dart';

class TextSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
      child: Text(
        'Abroad: Thought and ability is the key, the domestic: relationship and can run.The teacher said to hear and fine, I know hes salary.The man called the romantic love rich, rich in the coquettish woman.',
        textAlign: TextAlign.justify, //左右对齐
        //height: 1.1 类似于行高
        style: TextStyle(height: 1.1),
      ),
    );
  }
}
import 'package:flutter/material.dart';

class SelfContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      //盒子容器-一般是添加内容
      body: Container(
        // child: ,
        //装饰器:可以传递背景色/图,边框等等
        decoration: BoxDecoration(color: Colors.pink),
        width: 100,
        height: 100,
        margin: EdgeInsets.all(30),
        padding: EdgeInsets.all(20),
      ),
      //Container的child可以传递任何组件,一般自定义组件的时候,系统组件不支持传值,我们就在外层套上Container盒子
    );
  }
}
  • Dio
import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class SelfHttpRequest extends StatefulWidget {
  @override
  _SelfHttpRequestState createState() => _SelfHttpRequestState();
}

class _SelfHttpRequestState extends State<SelfHttpRequest> {
  List _list = [];

//重点:该函数其实相当于页面还未加载时候自动执行,类似于vue中的create
  @override
  void initState() {
    getMovieList();
    super.initState();
  }

  void getMovieList() async {
    try {
      // Dio d = Dio();  在flutter中new对象可以省略new直接使用,Dio库也可以这样
      Response response =
          await Dio().get("http://www.liulongbin.top:3005/api/getlunbo");

      //相当于json序列化为对象,接收值根据情况而定,如果是数组则是List
      Map responseData = jsonDecode(response.toString());
      _list = responseData['message']; //取对象里面的某个属性
      // print(responseData['message']);
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
          itemCount: _list.length,
          itemBuilder: (BuildContext context, int i) {
            // Map _item = _list[i];
            return Text(
              '${_list[i]["url"]}',
              style: TextStyle(fontSize: 30),
            );
          }),
    );
  }
}
  • 动态组件(statefulWidget)

动态组件一般针对渲染之后还需要修改的组件,例如点击操作逻辑或者网络请求渲染

//调用的时候传参如此: home: Increase(title: 'flutter')


import 'package:flutter/material.dart';

//动态组件  statefulWidget

class Increase extends StatefulWidget {
  //动态组件传参   @required使成为必传项
  Increase({Key key, @required this.title}) : super(key: key);
  final String title;

  //每一个动态组件里面都需要一个createState函数:生成状态
  @override
  _IncreaseState createState() => _IncreaseState();
}

//每一个动态组件都需要一个控制器,用来对组件内部的状态进行控制,并且渲染被控组件的UI结构
//控制器有命名要求,_被控制组件名State
class _IncreaseState extends State<Increase> {
  //页面当中的数字需要增加,定义一个状态值
  int _counter = 0;
  //数字自增函数
  void _increaseCounter() {
    //不使用setState虽然数据变化但是UI不会更新
    setState(() {
      _counter++;
    });
  }

  //控制器内部的build函数,用来渲染被控组件的UI结构
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        //重点: flutter中widget代表被控制的组件,widget可以获取所有Increase组件的属性
        title: Text(widget.title),
      ),
      body: Center(
        //从上到下排列的组件的盒子
        child: Column(
          //从上到下排列组件,这个是排列的方式
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('请点击按钮'),
            Text(
              '$_counter',
              style: TextStyle(fontSize: 30),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increaseCounter,
        //按住时候的提示信息
        tooltip: 'increase button',
        child: Icon(Icons.add),
      ),
    );
  }
}

//静态函数传参
/*
class Abc extends StatelessWidget {
  Abc({Key key, this.title}) : super(key: key);
  final String title;
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
*/
  • Row和Column

其实就是行和列,但是和ListView不同的是,ListView内容不会溢出会出现滚动,而行列内容超出则会报警告而且不会显示

import 'package:flutter/material.dart';
import 'package:flutter_app/lakes/IconSection.dart';
import 'package:flutter_app/lakes/TextSection.dart';
import 'package:flutter_app/lakes/TitleSection.dart';

class Lakes extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Image(image: AssetImage('images/1.png')),
          TitleSection(),
          IconSection(),
          TextSection()
        ],
      ),
    );
  }
}

//Column  纵向排版
//Row 横向排版
//给它们两个传递参数,都有一个children属性,后面跟一个数组,里面的每一项都是一个widget组件
import 'package:flutter/material.dart';

class IconSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
    
    //重点:主轴副轴排列方式一般用于对齐,主轴就是当前组件如果是列主轴就是竖向,副轴就是横向
    //其他组件也是依此类推
    
      //在主轴上均匀排列
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      // crossAxisAlignment: CrossAxisAlignment.center,  副轴排列方式
      children: <Widget>[
        _IconItem(title: 'CALL', icon: Icons.call),
        _IconItem(title: 'ROUTE', icon: Icons.near_me),
        _IconItem(title: 'SHARE', icon: Icons.share)
      ],
    );
  }
}

class _IconItem extends StatelessWidget {
  _IconItem({Key key, @required this.title, @required this.icon})
      : super(key: key);
  final IconData icon;
  final String title;

  @override
  Widget build(BuildContext context) {
    return Column(children: <Widget>[
      Padding(
          padding: EdgeInsets.only(bottom: 5),
          child: Icon(
            icon,
            color: Colors.blue,
          )),
      Text(
        '$title',
        style: TextStyle(color: Colors.blue),
      )
    ]);
  }
}

如果一行里面多个text组件然后长度不确定,则可能导致溢出,这时候明显overflow是无法有效显示省略号的,因为行里面没有这个属性,此时可以通过弹性布局(Expanded)实现

  • Expanded

弹性布局-会自动占据空余部分

import 'package:flutter/material.dart';

class TitleSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
      margin: EdgeInsets.only(bottom: 15),
      child: Row(
        children: <Widget>[
          //弹性布局-会自动占据空余部分
          Expanded(
            child: Column(
              //主轴(此时是从上到下)和副轴(左右)
              //使靠左对齐
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                    padding: EdgeInsets.only(bottom: 5),
                    child: Text("Oeschinen Lake Campground",
                        style: TextStyle(fontWeight: FontWeight.w700))),
                Text(
                  "Kandersteg, Switzerland",
                  style: TextStyle(color: Colors.grey),
                )
              ],
            ),
          ),
          //星星图标
          Icon(Icons.star, color: Colors.red),
          Text("41")
        ],
      ),
    );
  }
}
  • 手势识别器(GestureDetector)
import 'package:flutter/material.dart';

class Detail extends StatelessWidget {
  Detail({Key key, this.url}) : super(key: key);
  final String url;
  @override
  Widget build(BuildContext context) {
  //特别注意,该脚手架一定要在路由跳转去的组件有,因为可能main.dart里面有根组件,根组件里面有
  //这个脚手架,但是如果是路由跳转去页面,是和之前组件无关系的,如果不加可能导致
    return Scaffold(
      appBar: AppBar(
        title: Text("电影详情"),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            Image(image: NetworkImage('$url')),
            GestureDetector(
            //手势识别器有很多种事件,此处只演示最简单的点击事件
              onTap: () {
                //返回上一级页面
                Navigator.of(context).pop('49亿');
              },
              child: Text(
                '49亿',
                style: TextStyle(fontSize: 30),
              ),
            )
          ],
        ),
      ),
    );
  }
}
  • ListView

不会溢出会,多出来的会显示滚动条;动态操作需要ListView.builder

import 'package:flutter/material.dart';

class MoveScroll extends StatelessWidget {
  final List imgLit = [
    {
      "name": '哈哈哈1',
      "url": "http://api.cms.liulongbin.top/images/lunbo1-min.jpg"
    },
    {
      "name": '哈哈哈2',
      "url": "http://api.cms.liulongbin.top/images/lunbo2-min.jpg"
    }
  ];
  final List imgLit1 = [
    "http://api.cms.liulongbin.top/images/lunbo1-min.jpg",
    "http://api.cms.liulongbin.top/images/lunbo2-min.jpg",
    "http://api.cms.liulongbin.top/images/lunbo3-min.jpg"
  ];
  @override
  Widget build(BuildContext context) {
    //一个排列的组件盒子,可以纵向排版,也可以横向排版
    return Scaffold(
      body: Center(
          child: Container(
              height: 130,
              child: ListView.builder(
                  itemCount: imgLit.length,
                  scrollDirection: Axis.horizontal,
                  itemBuilder: (BuildContext context, int i) {
                    return _ImgItem(url: imgLit[i]["url"]);
                  })
              // child: ListView(
              //   //横向排版
              //   scrollDirection: Axis.horizontal,
              //   children: <Widget>[
              //     _ImgItem(url: imgLit[0]),
              //     _ImgItem(url: imgLit[1]),
              //     _ImgItem(url: imgLit[2])
              //   ],
              // ),
              )),
    );
  }
}

class _ImgItem extends StatelessWidget {
  _ImgItem({Key key, @required this.url}) : super(key: key);
  final String url;
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 350,
      child: Image(
        image: NetworkImage('$url'),
        fit: BoxFit.cover, //展开图片
      ),
    );
  }
}

//Column和Row的排版上的简单区别
//会溢出,类似于一个盒子,横着放或者是竖着放,放多了溢出

//ListView和ListView.Builder  不会溢出,会有滚动条滑动
import 'package:flutter/material.dart';
import 'package:flutter_app/moviesscroll/Detail.dart';

class MoveScroll2 extends StatelessWidget {
  final List imgLit = [
    "http://api.cms.liulongbin.top/images/lunbo1-min.jpg",
    "http://api.cms.liulongbin.top/images/lunbo2-min.jpg",
    "http://api.cms.liulongbin.top/images/lunbo3-min.jpg"
  ];
  @override
  Widget build(BuildContext context) {
    //一个排列的组件盒子,可以纵向排版,也可以横向排版
    return Scaffold(
      body: Center(
          child: Container(
        height: 130,
        child: ListView.builder(
          scrollDirection: Axis.horizontal,
          //遍历数组渲染
          itemBuilder: (BuildContext context, int i) {
            return _ImgItem(url: imgLit[i]);
          },
          //遍历次数
          itemCount: imgLit.length,
        ),
      )),
    );
  }
}

class _ImgItem extends StatelessWidget {
  _ImgItem({Key key, @required this.url}) : super(key: key);
  final String url;
  @override
  Widget build(BuildContext context) {
    //如果需要在组件上添加事件,那么就要调用一个组件GestureDetector
    return GestureDetector(
      //点击事件
      onTap: () {
        //跳转路由
        //MaterialPageRoute 路由组件
        // Navigator.of(context).push 是我们路由跳转的方法
        Navigator.of(context)
            .push(MaterialPageRoute(builder: (BuildContext context) {
          return Detail(url: url);
        })).then((val) {
          //接收子页面返回的时候传递回来的数据
          print(val);
        });
      },
      child: Container(
        width: 350,
        child: Image(
          image: NetworkImage('$url'),
          fit: BoxFit.cover, //展开图片
        ),
      ),
    );
  }
}

//Column和Row的排版上的简单区别
//会溢出,类似于一个盒子,横着放或者是竖着放,放多了溢出

//ListView和ListView.Builder  不会溢出,会有滚动条滑动

电影小案例

空文件

简介

Flutter入门案例 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Dart
1
https://gitee.com/zengqiang_455/introduction-to-fluent.git
git@gitee.com:zengqiang_455/introduction-to-fluent.git
zengqiang_455
introduction-to-fluent
Flutter入门案例
master

搜索帮助