这篇博客主要是实现以下功能
  1. flutter中 ListView的基本使用
  2. 上拉加载刷新
  3. 加载提示
准备
//在配置文件中添加这个库我们会随机生成单词
  english_words: ^3.1.0
基础代码

下面这部分代码是死的,我就不介绍了,我们重点介绍_MyInfiniteListViewState这里面的内容

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

void main() => runApp(new InfiniteListView());

class InfiniteListView extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "InfiniteListView",
      home: Scaffold(
        appBar: AppBar(
          title: Text("InfiniteLisView"),
        ),
        body: MyInfiniteListView(),
      ),
    );
  }
}
class MyInfiniteListView extends StatefulWidget{
  @override
  _MyInfiniteListViewState createState() => _MyInfiniteListViewState();

}

主要内容

数据容器
//定义一个结尾的标志和一个初始的数组,数组里面放一个元素防止后面的异常
  static const loadingTag = "****loading****";
  var _word = <String>[loadingTag];
初始化
@override
  void initState() {
    //初始化的时候添加20个元素
    super.initState();
      _retireveData();
  }

接下来我们来看这个初始化数据的方法怎么写

/**
   * 在新的数组中添加20个单词
   */
  void _retireveData(){
    Future.delayed(new Duration(seconds: 2)).then((e)=>{
        //_word 是一个数组,因为默认有一个元素,所以这里减一没关系
        _word.insertAll(_word.length-1,generateWordPairs().take(20).map((e) => e.asPascalCase).toList()),
      //每次生成20个单词
      //这里用到了  english_words: ^3.1.0这个框架,调用生成单词的函数
        //生成完了20个单词之后就要更新界面了
        setState(() {
      //重新构建列表,这里不用做什么事,空的调用也会提示程序刷新builder
    })
    });

  }

build中的内容

//我们使用这个构造函数,是因为这个构造函数中带有分割线
ListView.separated()

我们来看一下伪代码

ListView.separated(
//这个是对每个item的构建
itemBuilder: (context,index){
	是否滑动到最后一条
		是: 是否超过100条
			是: 显示没有更多数据
			否:显示转圈圈,等待加载数据
		否:构建下一条数据
}
)

基本上就是这个思路了,我们来看下如果超过100条的写法

//超过100条,不在加载更多的数据了,提示用户
              return Container(
                alignment: Alignment.center,
                padding: EdgeInsets.all(16.0),
                child: Text("--------我也是有底线的------",
                style:TextStyle(color: Colors.grey)),
              );

没有超过100条但是滑到底了的写法

//不足100条,继续获取数据
            if(_word.length-1<100){
              //获取数据
              _retireveData();
              //加载时显示loading
              return Container(
              //设置边距
                padding: const EdgeInsets.all(16.0),
                //居中显示
                alignment: Alignment.center,
                child: SizedBox(
                  width: 24.0,
                  height: 24.0,
                  //这是一个转圈的progressBar的widget
                  child: CircularProgressIndicator(strokeWidth: 2.0,),
                ),
              );

好了 附上完整代码

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

void main() => runApp(new InfiniteListView());

class InfiniteListView extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "InfiniteListView",
      home: Scaffold(
        appBar: AppBar(
          title: Text("InfiniteLisView"),
        ),
        body: MyInfiniteListView(),
      ),
    );
  }
}
class MyInfiniteListView extends StatefulWidget{
  @override
  _MyInfiniteListViewState createState() => _MyInfiniteListViewState();

}

class _MyInfiniteListViewState extends State<MyInfiniteListView>{
  static const loadingTag = "****loading****";
  var _word = <String>[loadingTag];
  @override
  void initState() {
    //初始化的时候添加20个元素
    super.initState();
      _retireveData();
  }

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
        itemBuilder: (context,index){
          //如果到了末尾,就需要获取数据了,这里判断的依据就是是否和 ***loading***相等
          if(_word[index] == loadingTag){
            //不足100条,继续获取数据
            if(_word.length-1<100){
              //获取数据
              _retireveData();
              //加载时显示loading
              return Container(
                padding: const EdgeInsets.all(16.0),
                alignment: Alignment.center,
                child: SizedBox(
                  width: 24.0,
                  height: 24.0,
                  child: CircularProgressIndicator(strokeWidth: 2.0,),
                ),
              );
            }else{
              //超过100条,不在加载更多的数据了,提示用户
              return Container(
                alignment: Alignment.center,
                padding: EdgeInsets.all(16.0),
                child: Text("--------我也是有底线的------",
                style:TextStyle(color: Colors.grey)),
              );

            }
          }
          return ListTile(title: Text("${_word[index]} $index"),);
        },
        //这里表示的是默认的分割线
        separatorBuilder: (context, index)=>Divider(),
        itemCount: _word.length);
  }

  /**
   * 在新的数组中添加20个单词
   */
  void _retireveData(){
    Future.delayed(new Duration(seconds: 2)).then((e)=>{
        //_word 是一个数组,因为默认有一个元素,所以这里减一没关系
        _word.insertAll(_word.length-1,generateWordPairs().take(20).map((e) => e.asPascalCase).toList()),
      //每次生成20个单词
      //这里用到了  english_words: ^3.1.0这个框架,调用生成单词的函数
        //生成完了20个单词之后就要更新界面了
        setState(() {
      //重新构建列表,这里不用做什么事,空的调用也会提示程序刷新builder
    })
    });

  }
}


class MyListView3 extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    Widget divider1 = new Divider(color: Colors.red);
    Widget divider2 = new Divider(color: Colors.blue);
    // TODO: implement build
    return MaterialApp(
      title: "listView",
      home: Scaffold(
        appBar: AppBar(
          title: Text("LsitView"),
        ),
        body: ListView.separated(
            itemBuilder: (BuildContext context, int index){
              return ListTile(
                title: Text("idnex$index"),
              );
            },
            separatorBuilder:(BuildContext context, int index){
              return index%2==0?divider1:divider2;
            },
            itemCount: 100),
      ),
    );
  }

}












class MyListView extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "ListViewText",
      home: Scaffold(
        appBar: AppBar(
          title: Text("ListViewText"),
        ),
        body: ListView.builder(
            itemCount: 100,
            itemExtent: 50,
            itemBuilder: (BuildContext contxt,int index){
              return ListTile(
                title: Text("index$index"),
              );
            }
          ),
      ),
    );
  }
  
}









class SingleChildScrollViewTestRoute extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    String str =  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    // TODO: implement build
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "测试",
      home: Scaffold(
        appBar: AppBar(
          title: Text("SingleChildScrollViewTestRoute"),
        ),
        body: SingleChildScrollView(
          padding: EdgeInsets.all(16.0),
          child: Center(
            child: Column(
              //动态的创建一个List<Widget>
              children: str.split("").map((e)=>Text(e,textScaleFactor: 2.0,)).toList(),
            ),
          ),
        ),
      ),
    );
  }

}





















class ScaffoldRoute extends StatefulWidget {
  @override
  _ScaffoldRoute createState() {
    // TODO: implement createState
    return _ScaffoldRoute();
  }
}

class _ScaffoldRoute extends State<ScaffoldRoute>  with SingleTickerProviderStateMixin{
  List tabs = ["新闻", "历史", "图片"];
  TabController _tabController;
  int _selectedIndex = 1;
  @override
  void initState() {
    // TODO: implement initState
    // 创建Controller
    _tabController = TabController(length: tabs.length, vsync: this);
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "pro",
      home: Scaffold(
        appBar: AppBar(
          //导航栏
          title: Text("App Name"),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.share),
              onPressed: () {
                print("点击了");
              },
            ),
          ],
          bottom: TabBar(
            controller: _tabController,
            tabs: tabs.map((e)=>Tab(text: e,)).toList(),
          ),
        ),
        drawer: MyDrawer(),
        body:TabBarView(
            controller: _tabController,
            children:tabs.map((e){
      return Container(
      alignment: Alignment.center,
      child: Text(e, textScaleFactor: 5),
      );
      }).toList()

        ),
        bottomNavigationBar: BottomNavigationBar(
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
            BottomNavigationBarItem(icon: Icon(Icons.business), title: Text('Business')),
            BottomNavigationBarItem(icon: Icon(Icons.school), title: Text('School')),
          ],
          currentIndex: _selectedIndex,
          //这个属性表示的是点击后的颜色变化
          fixedColor: Colors.blue,
          onTap: _onItemTapped,
        ),

      ),
    );
  }
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
}

class MyDrawer extends StatelessWidget {
  const MyDrawer({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Drawer(
      child: MediaQuery.removePadding(context: context,
          child:Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.only(top: 28.0),
                child: Row(
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 16.0),
                      child: ClipOval(
                        child: Image.network("https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=5ce3474036adcbef15397654cdc645b8/b7fd5266d01609242759dc9fd30735fae6cd3431.jpg",
                        width: 80,
                        ),
                      ),
                    ),
                    Text("Wendux",
                    style: TextStyle(fontWeight: FontWeight.bold),
                    )
                  ],
                ),
              ),
              Expanded(
                  child: ListView(
                    children: <Widget>[
                      ListTile(
                        leading: const Icon(Icons.add),
                        title: const Text("add account"),
                      ),
                      ListTile(
                        leading: const Icon(Icons.settings),
                        title: const Text("Manage account"),
                      ),
                    ],
                  ),
              ),
            ],
          )
      )
    );
  }

}

class FlexLayoutTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "test",
      home: Scaffold(
        appBar: AppBar(
          title: Text("test"),
        ),
        body: MyLayoutTest(),
      ),
    );
  }
}

class MyLayoutTest extends StatelessWidget {
  Widget redBox = DecoratedBox(
    decoration: BoxDecoration(color: Colors.red),
  );

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "Test",
      home: Scaffold(
        appBar: AppBar(
          title: Text("布局测试"),
        ),
        body: Container(
          //容器外补白
          margin: EdgeInsets.only(top: 50.0, left: 120.0),
          //容器的大小
          constraints: BoxConstraints.tight(Size(500, 500)),
          decoration: BoxDecoration(
            //背景装饰
            gradient: RadialGradient(
                colors: [Colors.red, Colors.orange],
                center: Alignment.topLeft,
                radius: 0.98),
            boxShadow: [
              BoxShadow(
                  color: Colors.black54,
                  offset: Offset(2.0, 2.0),
                  blurRadius: 4.0),
            ],
          ),
          //卡片倾斜式变换
          transform: Matrix4.rotationZ(0.2),
          //卡片内的文字居中
          alignment: Alignment.center,
          child: Text(
            "薇薇一笑很倾城",
            style: TextStyle(color: Colors.white, fontSize: 40.0),
          ),
        ),
      ),
    );
  }
}

class PaddingTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      //上下左右各添加16像素补白
      padding: EdgeInsets.all(16.0),
      child: Column(
        //显式指定对齐方式为左对齐,排除对齐干扰
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            //左边添加8像素补白
            padding: const EdgeInsets.only(left: 28.0),
            child: Text("Hello world"),
          ),
          Padding(
            //上下各添加8像素补白
            padding: const EdgeInsets.symmetric(vertical: 8.0),
            child: Text("I am Jack"),
          ),
          Padding(
            // 分别指定四个方向的补白
            padding: const EdgeInsets.fromLTRB(20.0, .0, 20.0, 20.0),
            child: Text("Your friend"),
          )
        ],
      ),
    );
  }
}