Flutter列表ListView学习

学习ing

1. 热重载

1.1 什么是热重载

  • Flutter热重载:在我们调试布局的时候,更改代码,模拟器上可以立即看到代码改动的效果;而不是iOS和Android单独开发需要重新编译,启动,耗时极长。

  • 开发效率:Flutter的热重载可帮助开发者快速地进行测试、构建UI、添加功能并更快地修复错误。在iOS和Android模拟器或真机上可以实现毫秒级热重载,并且不会丢失状态。这真的很棒,相信我,如果你是一名原生开发者,体验了Flutter开发流后,很可能就不想重新回去做原生了,毕竟很少有人不吐槽原生开发的编译速度。

1.2 热重载的使用

热重载快捷键:

command + \

或者直接点击热重载按钮,闪电标识:
热重载按钮

如果使用终端直接run,热重载直接输入小写的 r,即可;热重启直输入大写的 R,即可

终端热重载指令,输入r,R

2. 常用快捷键的使用

  1. Dart语言命名规则:
    文件名:小写 + _ (组合使用,不需要驼峰规则)
    类名 :首字母大写 + 驼峰规则

  2. 格式化: 按照Dart的语法规则将代码格式优化
    command + option + l

  3. function折叠: 将{}之间的方法折叠为{…}或展开
    command -
    command +

  4. 代码块的使用:
    stl (无状态stateless widget)
    stf (有状态stateful widget)

  5. import快捷键: 当使用一个没有import的类时报错,可以使用如下快捷键
    option + enter两次

  6. 切换文件: 在两个.dart文件之间来回切换
    command + [
    command + ]

  7. 打开一个文件:
    command + shift + o

  8. 当一个function里面只有一句执行代码的时候,可以用=>简写,如下:

    void main() {
    runApp(App(); //只有一句执行代码
    }

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

3. 简单ListView的搭建

Flutter中的ListView类似于iOS中的UITableView,使用之处和iOS的UITableView类似也有区别;

3.1 Widget控件

  • 在Flutter中几乎所有的对象都是一个Widget。与原生开发中“控件”不同的是,Flutter中的Widget的概念更广泛,它不仅可以表示UI元素,也可以表示一些功能性的组件如:用于手势检测的 GestureDetector widget、用于APP主题数据传递的Theme等等,而原生开发中的控件通常只是指UI元素。在后面的内容中,我们在描述UI元素时可能会用到“控件”、“组件”这样的概念,读者心里需要知道他们就是widget,只是在不同场景的不同表述而已。由于Flutter主要就是用于构建用户界面的,所以,在大多数时候,读者可以认为widget就是一个控件,不必纠结于概念。

Widget主要接口:

@immutable
abstract class Widget extends DiagnosticableTree {
 const Widget({ this.key });
 final Key key;

 @protected
 Element createElement();

 @override
 String toStringShort() {
   return key == null ? '$runtimeType' : '$runtimeType-$key';
 }

 @override
 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
   super.debugFillProperties(properties);
   properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
 }

 static bool canUpdate(Widget oldWidget, Widget newWidget) {
   return oldWidget.runtimeType == newWidget.runtimeType
       && oldWidget.key == newWidget.key;
 }
}
  • Widget类继承自DiagnosticableTree,DiagnosticableTree即“诊断树”,主要作用是提供调试信息。
  • Key: 这个key属性类似于React/Vue中的key,主要的作用是决定是否在下一次build时复用旧的
  • widget,决定的条件在canUpdate()方法中。
  • createElement():正如前文所述“一个Widget可以对应多个Element”;Flutter Framework在构建UI树时,会先调用此方法生成对应节点的Element对象。此方法是Flutter Framework隐式调用的,在我们开发过程中基本不会调用到。
  • debugFillProperties(…) 复写父类的方法,主要是设置诊断树的一些特性。
  • canUpdate(…)是一个静态方法,它主要用于在Widget树重新build时复用旧的widget,其实具体来说,应该是:是否用新的Widget对象去更新旧UI树上所对应的Element对象的配置;通过其源码我们可以看到,只要newWidget与oldWidget的runtimeType和key同时相等时就会用newWidget去更新Element对象的配置,否则就会创建新的Element。

以上摘自Flutter官方文档Widget概述:Flutter中文网Widget概述

简单来说Widget就相当于iOS中的UIView

3.2 主要代码

代码主要分为3部分:

  1. main.dat:主界面,导航栏等;
  2. listview_demo.dart 列表listview对象控件;
  3. car.dart 单个widget模型(name,imageUrl);
  • main.dart中的代码:
//material.dart相当于iOS中的UIKit
import 'package:flutter/material.dart';
import 'package:flutter_001/model/listview_demo.dart';

//Widget 控件 相当于UIView
//Stateful 有状态的控件  Stateless 无状态的控件

//void main (){
//  
//  runApp(
//     App(),
//  );
//}

//当一个function里面只有一句执行代码的时候,可以用=>简写
//如下:

void main() => runApp(App());
//runApp相当于iOS中的UIApplication

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: true,
      home: Home(),//首页
      theme: ThemeData(
        primaryColor: Colors.yellow,//导航栏颜色
      ),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      //appBar 导航栏
      appBar: AppBar(title: Text(
        "ListView",
        style: TextStyle(
        color: Colors.deepOrange[300],
     fontSize: 22,
        ),
      ),
      ),
      body: ListViewDemo(),  //ListView控件
    );

  }
}

  • 列表listview_demo的代码:
import 'package:flutter/material.dart';

import 'car.dart'; //option +enter两次

class ListViewDemo extends StatelessWidget {
  Widget _cellForRow (BuildContext context, int index){ 
  //自定义返回cell的函数
  //context:上下文
  //index:第几个widget(第几个cell)

    return Container(
      margin: EdgeInsets.all(10),
      color: Colors.white,
      child: Column(
        children: <Widget>[
          Image.network(datas[index].imageUrl),
          SizedBox(height:20),
          Text(datas[index].name,style:
          TextStyle(color:Colors.blue,
            fontSize:22,
            fontWeight: FontWeight.w800,
            fontStyle: FontStyle.values[1],
          )),
          SizedBox(height: 20),
        ],
      ),
    );
  }

  //Column 上下布局
  //Row    左右布局
  //Stack  层级布局

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: datas.length,
        itemBuilder: _cellForRow);
  }
  // ListView.builder创建listView,需要传入的参数有
  // itemCount: 简单理解UITableView中的cell的个数;
  // itemBuilder: 简单理解UITableView中的cellforRowsAtIndex;
  // Dart中带_的方法为私有方法,外部不能访问,例如_cellForRow;
}
  • 模型car.dart文件中的代码:
class Car {

  const Car ({ //构造函数
    this.name,
    this.imageUrl,

  });
  final String name;
  final String imageUrl;
}

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

];

运行效果

原文链接:链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值