This post was updated 880 days ago and some of the ideas may be out of date.

Warp组件 流式布局

(如app里的小标签)
spacing 元素间距离(X轴)
runSpacing 纵轴间距离
alignment WrapAlignment 元素对齐方式

class MyButton extends StatelessWidget{
  String text = "默认内容";
  MyButton(this.text);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ElevatedButton(
        onPressed: (){
        },
        child: Text(this.text)
    );
  }
}

class Home extends StatelessWidget {

@override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      padding: EdgeInsets.fromLTRB(8, 10, 8, 10),
      child:Wrap(
        spacing: 10,
        runSpacing: 5,
        children: [
          MyButton("女装"),
          MyButton("女装"),
          MyButton("女装"),
          MyButton("女装11"),
          MyButton("女装"),
          MyButton("女装"),
          MyButton("女装2222"),
          MyButton("女装"),
          MyButton("女装111111"),
          MyButton("女装"),
          MyButton("女装"),
        ],
      ),
    );

  }


}

aspectRatio 配置宽高比 eg:2.0/1.0

Example

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return AspectRatio(aspectRatio: 2/1,
    child:Container(
      color: Colors.red,
    ),
    );
  }
}
//占满全宽 高度为宽度的一半

Card组件

margin 外边距
child 子组件
shape 阴影效果

简单例子

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ListView(
      children: [
        Card(
          margin: EdgeInsets.all(13),
          child: Column(
          children: [
            ListTile(
              title: Text("CC米饭",style: TextStyle(fontSize: 28),),
              subtitle: Text('米饭鸭!!!'),
              leading: Icon(Icons.unarchive_sharp),
            ),
          ],
          ),
        )
      ],
    );
  }
}

图文卡片

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ListView(
      children: [
        Card(
          child: Column(
            children: [
              AspectRatio(aspectRatio: 2/1,
              child: Image.network("https://i0.hdslb.com/bfs/archive/08e9af7deb7ef87448095c2eba544c033232d061.jpg@336w_190h_1c.webp",fit: BoxFit.cover,),
              ),
              ListTile(
                title: Text('xxxxx'),
                subtitle: Text("介绍呀啊啊啊啊啊"),
                leading: ClipOval(
                  child: Image.network("https://i0.hdslb.com/bfs/archive/08e9af7deb7ef87448095c2eba544c033232d061.jpg@336w_190h_1c.webp",height: 60,width: 60,fit: BoxFit.cover,),
                ),
              )
            ],
          ),
        ),
      ],
    );
  }
}

圆图片实现2:

leading: CircleAvatar(
                  backgroundImage: NetworkImage('https://i0.hdslb.com/bfs/archive/08e9af7deb7ef87448095c2eba544c033232d061.jpg@336w_190h_1c.webp'),
),
</code></pre><p>#### 卡片加列表加动态数据 实例</p><pre><code>class Home extends StatelessWidget {



 @override
 Widget build(BuildContext context) {
   // TODO: implement build
   return ListView(
     children: listDatas.map((e){
       return Card(
         child: Column(
           children: [
             AspectRatio(aspectRatio: 2/1,
               child: Image.network(e[&quot;imageUrl&quot;],fit: BoxFit.cover,),
             ),
             ListTile(
               title: Text(e['title']),
               subtitle: Text(e['author']),
               leading: CircleAvatar(
                 backgroundImage: NetworkImage(e[&quot;imageUrl&quot;]),
               ),
             )
           ],
         ),
       );
     }).toList(),
   );
 }
}

路由

就是页面跳转

基本路由
命令路由

普通(基本)路由

eg.首页到搜索页面(Push方法)

import 'package:flutter/material.dart';
import 'res/listData.dart';

import './pages/Search.dart';
void main(){
  runApp(MainHome());
}


class MainHome extends StatelessWidget {
  const MainHome({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}


class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  State&lt;Home&gt; createState() =&gt; _HomeState();
}

class _HomeState extends State&lt;Home&gt; {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(&quot;Home&quot;),
      ),
      body: Container(
          child:
          ElevatedButton(onPressed: (){
            Navigator.of(context).push(
                MaterialPageRoute(builder: (context)=&gt;SearchPage())
            );

          }, child: Text(&quot;搜索&quot;))
      ),
    );


  }
}

基本路由跳转

ElevatedButton(onPressed: (){
            Navigator.of(context).push(
                MaterialPageRoute(builder: (context)=&gt;SearchPage())
            );
</code></pre><p>传参</p><pre><code>
MaterialPageRoute(builder: (context)=&gt;TextPage(ttt: '我的内容',))


----

  String ttt = '表单';
  TextPage({required this.ttt});

返回页面(POP方法)

eg 一个悬浮圆形按钮+返回

      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.back_hand_outlined),
        onPressed: (){
          Navigator.of(context).pop();
        },

命名路由

略 待学习

TABBAR

使用 leading在前面添加 使用action在后面添加

return Scaffold(
      appBar: AppBar(
        title: Text(&quot;AppBar&quot;),
        backgroundColor: Colors.red,
        actions: [
          IconButton(onPressed: (){
            print('Seacrh');
          }, icon: Icon(Icons.search))
        ],
      ),
      body: Text('111'),
    );
  }

centertitle 标题居中显示

顶部TabBar

一定要有DefaultTabController(length: length, child: child)

eg 仅添加TAb

 return DefaultTabController(length: 2, child:
    Scaffold(
      appBar: AppBar(
        title: Text(&quot;AppBar&quot;),
        backgroundColor: Colors.red,
        bottom: TabBar(
          tabs: [
            Tab(text: '热门'),
            Tab(text: '推荐'),
          ],
        ),
      ),
      body: Text('111'),
    ),
    );

要内容对应则这样

body: TabBarView(
        children: [
          ListView(
            children: [
              ListTile(title: Text(&quot;热门内容1!!&quot;)),
              ListTile(title: Text(&quot;热门内容1!!&quot;)),
              ListTile(title: Text(&quot;热门内容1!!&quot;)),
            ],
          ),
          ListView(
            children: [
              ListTile(title: Text(&quot;推荐内容2!!&quot;)),
              ListTile(title: Text(&quot;推荐内容2!!&quot;)),
              ListTile(title: Text(&quot;推荐内容2!!&quot;)),
            ],
          ),
        ],
      )

不显示标题栏则:把要的东西放在title里面 eg:

Scaffold(
    appBar: AppBar(
      title: Row(
        children: [
          Expanded(child: TabBar(
            tabs: [
              Tab(text: '热门'),
              Tab(text: '推荐'),
            ],
          ),)
        ],
      ),
      backgroundColor: Colors.red,
    ),
    body: TabBarView(
      children: [
        ListView(
          children: [
            ListTile(title: Text(&quot;热门内容1!!&quot;)),
            ListTile(title: Text(&quot;热门内容1!!&quot;)),
            ListTile(title: Text(&quot;热门内容1!!&quot;)),
          ],
        ),
        ListView(
          children: [
            ListTile(title: Text(&quot;推荐内容2!!&quot;)),
            ListTile(title: Text(&quot;推荐内容2!!&quot;)),
            ListTile(title: Text(&quot;推荐内容2!!&quot;)),
          ],
        ),
      ],
    )
  ),

指示器颜色 labelColor unselectedLableColor

指示器长度 indicatorSize: TabBarIndicatorSize.tab

另一种Tab切换方法

必须动态组件 还有多继承(with)

class TabBarControllerpage extends StatefulWidget {
  const TabBarControllerpage({Key? key}) : super(key: key);

  @override
  State&lt;TabBarControllerpage&gt; createState() =&gt; _TabBarControllerpageState();
}

class _TabBarControllerpageState extends State&lt;TabBarControllerpage&gt; with SingleTickerProviderStateMixin{
  //Control配置
  //1,继承类
  //2.定义
  //3.初始化触发方法
  var _tabController;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _tabController = new TabController(length: 2, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TabBarControllerpage'),
        bottom: TabBar(
          //添加control
          controller: this._tabController,
          tabs: [
            Tab(text: '热销',),
            Tab(text: '推荐',),
          ],
        ),
      ),
      body: TabBarView(
        //配置control
        controller: this._tabController,
        children: [
          Text('热销11111'),
          Text('推荐2222')
        ],
      ),
    );
  }
}

事件监听

  late TabController _tabController;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _tabController = new TabController(length: 2, vsync: this);
    //tab事件监听
    _tabController.addListener((){
      print(_tabController.index);
    });

  }

侧滑

最简单实例

Scaffold(
      appBar: AppBar(
        title: Text(&quot;Home&quot;),
      ),
      drawer: Drawer(
        child: Text('Helllo'),
      ),
      );

endDrawer 右侧侧边栏

Divider组件 一根线

DrawerHeader 头部组件(为侧滑加图片
eg:

 drawer: Drawer(
        child: Column(
          children: [
            Row(
              children: [
                Expanded(child: DrawerHeader(child:Text(&quot;头部&quot;)),)
              ],
            ),
            ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.home),
              ),
              title: Text('我'),
            ),
            ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.settings),
              ),
              title: Text('设置'),
            ),
            ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.face),
              ),
              title: Text('朋友'),
            )
          ],
        )
      ),

顶部图片例子

 DrawerHeader(
                    child:Text(&quot;头部&quot;),
                  decoration: BoxDecoration(
                    //color: Colors.pink,
                    image: DecorationImage(
                      image: NetworkImage(&quot;URL&quot;)
                    )
                  ),
                ),</code></pre><pre><code>DrawerHeader(
                    child:Text(&quot;头部&quot;),
                  decoration: BoxDecoration(
                    //color: Colors.pink,
                    image: DecorationImage(
                      image: NetworkImage(&quot;https://i0.hdslb.com/bfs/live/d7fdba9dd2eb76f1faf5a1ed998d4d8b0dc0ab9e.jpg@672w_378h_1c.webp&quot;,),
                      fit: BoxFit.cover
                    )

快速侧滑头部样式(UserAccountsDrawerHeader)

accountName 设置大标题
accountEmail 设置小标题
currentAccountPicture 小图片
otherAccountsPictures 右侧小图片·(没啥用)
完整实例

drawer: Drawer(
        child: Column(
          children: [
            Row(
              children: [
                Expanded(
                    child:UserAccountsDrawerHeader(
                      currentAccountPicture: CircleAvatar(
                        backgroundImage: NetworkImage('url'),
                      ),
                      decoration: BoxDecoration(
                        //color: Colors.pink,
                          image: DecorationImage(
                          image: NetworkImage(&quot;url&quot;)
                          )
                        ),
                      accountName: Text('CC米饭'),
                      accountEmail: Text('233333'),
                    )
                )
              ],
            ),
            ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.home),
              ),
              title: Text('我'),
            ),
            ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.settings),
              ),
              title: Text('设置'),
            ),
            ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.face),
              ),
              title: Text('朋友'),
            )
          ],
        )
      ),

侧边栏点击事件

使用ontap
eg:

ListTile(
              leading: CircleAvatar(
                child: Icon(Icons.home),
              ),
              title: Text('我'),
              onTap: (){
                print(&quot;hello&quot;);
              },
            ),

使用Navigator.of(context).pop();关闭

按钮

配置按钮颜色

backgroundColor: MaterialStateProperty.all 按钮颜色
foregroundColor: MaterialStateProperty.all文本颜色
elevation: MaterialStateProperty.all(填数字)阴影颜色

eg

ElevatedButton(
   onPressed: (){},
   child: Text(&quot;122&quot;),
   style: ButtonStyle(
           backgroundColor: MaterialStateProperty.all(Colors.blueGrey),
        foregroundColor: MaterialStateProperty.all(Colors.white),
        elevation: MaterialStateProperty.all(2),
                ),
              )

图标按钮

ElevatedButton.icon(onPressed: (){},
                  icon: Icon(Icons.abc),
                  label: Text('附带的文字')
              )

按钮宽度 高度

通过Container控制 (在Container中包含按钮)

Container(
                height: 50,
                width: 100,
                child: ElevatedButton(
                  onPressed: (){},
                  child: Text('111'),
                ),
              )

自适应按钮

Expands中加Container再加按钮

圆角按钮

              ElevatedButton(onPressed: (){},
                child: Text('111'),
                style: ButtonStyle(
                  shape: MaterialStateProperty.all(
                      RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20)
                      )
                  )
                ),
              ),

扁平按钮 TextButton

边框按钮

边框按钮设置边框颜色 宽度

OutlinedButton(onPressed: (){},
                 child: Text(&quot;1111&quot;),
               style: ButtonStyle(
                 //字体颜色
                 foregroundColor: MaterialStateProperty.all(Colors.blueGrey),
                 //边框颜色 宽度
                 side: MaterialStateProperty.all(
                     BorderSide(
                       width: 1,
                       color: Colors.red
                     )
                 ),

               ),
             )