Padding 组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. // Padding 组件
    24. return Padding(
    25. padding: EdgeInsets.all(10),
    26. child: GridView(
    27. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    28. crossAxisCount: 2,
    29. crossAxisSpacing: 10,
    30. mainAxisSpacing: 10,
    31. ),
    32. children: [
    33. Image.network(
    34. 'https://images.pexels.com/photos/6569318/pexels-photo-6569318.jpeg?cs=srgb&dl=pexels-david-underland-6569318.jpg&fm=jpg',
    35. fit: BoxFit.cover,
    36. ),
    37. Image.network(
    38. 'https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg',
    39. fit: BoxFit.cover,
    40. ),
    41. Image.network(
    42. 'https://images.pexels.com/photos/5994821/pexels-photo-5994821.jpeg?cs=srgb&dl=pexels-matteus-silva-de-oliveira-5994821.jpg&fm=jpg',
    43. fit: BoxFit.cover,
    44. ),
    45. Image.network(
    46. 'https://images.pexels.com/photos/7173820/pexels-photo-7173820.jpeg?cs=srgb&dl=pexels-lisa-fotios-7173820.jpg&fm=jpg',
    47. fit: BoxFit.cover,
    48. ),
    49. Image.network(
    50. 'https://images.pexels.com/photos/7042988/pexels-photo-7042988.jpeg?cs=srgb&dl=pexels-jc-siller-7042988.jpg&fm=jpg',
    51. fit: BoxFit.cover,
    52. ),
    53. Image.network(
    54. 'https://images.pexels.com/photos/7137430/pexels-photo-7137430.jpeg?cs=srgb&dl=pexels-monica-turlui-7137430.jpg&fm=jpg',
    55. fit: BoxFit.cover,
    56. ),
    57. ],
    58. ),
    59. );
    60. }
    61. }

    Row组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return Row(
    24. mainAxisAlignment: MainAxisAlignment.spaceAround,
    25. crossAxisAlignment: CrossAxisAlignment.start,
    26. children: [
    27. IconWidget(Icons.home_filled, color: Colors.pink, size: 30),
    28. IconWidget(Icons.search_off, color: Colors.blue, size: 30),
    29. IconWidget(Icons.access_alarm, color: Colors.redAccent, size: 30),
    30. ],
    31. );
    32. }
    33. }
    34. class IconWidget extends StatelessWidget {
    35. IconWidget(this.icon, {this.color = Colors.white70, this.size = 32});
    36. final double size;
    37. final IconData icon;
    38. final Color color;
    39. @override
    40. Widget build(BuildContext context) {
    41. return Container(
    42. color: this.color,
    43. width: 100,
    44. height: 100,
    45. child: Center(
    46. child: Icon(this.icon, size: this.size, color: Colors.black),
    47. ),
    48. );
    49. }
    50. }
    属性 说明
    mainAxisAlignment 主轴的排序方式
    crossAxisAlignment 次轴的排序方式
    children 组件的子元素

    Column组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return Column(
    24. mainAxisAlignment: MainAxisAlignment.spaceAround,
    25. children: [
    26. IconWidget(Icons.home_filled, color: Colors.pink, size: 30),
    27. IconWidget(Icons.search_off, color: Colors.blue, size: 30),
    28. IconWidget(Icons.access_alarm, color: Colors.redAccent, size: 30),
    29. ],
    30. );
    31. }
    32. }
    33. class IconWidget extends StatelessWidget {
    34. IconWidget(this.icon, {this.color = Colors.white70, this.size = 32});
    35. final double size;
    36. final IconData icon;
    37. final Color color;
    38. @override
    39. Widget build(BuildContext context) {
    40. return Container(
    41. color: this.color,
    42. width: 100,
    43. height: 100,
    44. child: Center(
    45. child: Icon(this.icon, size: this.size, color: Colors.black),
    46. ),
    47. );
    48. }
    49. }

    Column 组件跟 Row 组件是差不多的。

    Expanded 组件:

    属性 说明
    flex 元素占整个父 Row / Column 的比例
    child 子元素
    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return Row(
    24. children: [
    25. Expanded(
    26. flex: 1,
    27. child: IconWidget(Icons.home_filled, color: Colors.pink, size: 30)),
    28. Expanded(
    29. flex: 2,
    30. child: IconWidget(Icons.search_off, color: Colors.blue, size: 30)),
    31. Expanded(
    32. flex: 1,
    33. child: IconWidget(Icons.access_alarm,
    34. color: Colors.redAccent, size: 30)),
    35. ],
    36. );
    37. }
    38. }
    39. class IconWidget extends StatelessWidget {
    40. IconWidget(this.icon, {this.color = Colors.white70, this.size = 32});
    41. final double size;
    42. final IconData icon;
    43. final Color color;
    44. @override
    45. Widget build(BuildContext context) {
    46. return Container(
    47. color: this.color,
    48. width: 100,
    49. height: 100,
    50. child: Center(
    51. child: Icon(this.icon, size: this.size, color: Colors.black),
    52. ),
    53. );
    54. }
    55. }

    Expanded组件跟 web 中的 flex 布局相似。

    一个布局demo:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return Container(
    24. padding: EdgeInsets.all(10),
    25. // decoration: BoxDecoration(color: Colors.pink),
    26. child: Column(
    27. children: [
    28. BannerWidget(),
    29. BannerListWidget(),
    30. ],
    31. ),
    32. );
    33. }
    34. }
    35. class BannerWidget extends StatelessWidget {
    36. @override
    37. Widget build(BuildContext context) {
    38. return Container(
    39. height: 100,
    40. decoration: BoxDecoration(
    41. color: Colors.pink,
    42. borderRadius: BorderRadius.circular(10),
    43. ),
    44. );
    45. }
    46. }
    47. class BannerListWidget extends StatelessWidget {
    48. @override
    49. Widget build(BuildContext context) {
    50. return Container(
    51. padding: EdgeInsets.only(top: 10),
    52. child: Row(
    53. children: [
    54. Expanded(
    55. flex: 2,
    56. child: Padding(
    57. padding: EdgeInsets.only(right: 10),
    58. child: Image.network(
    59. 'https://cdn.pixabay.com/photo/2021/03/16/15/30/beach-6100209_960_720.jpg',
    60. fit: BoxFit.cover,
    61. height: 180,
    62. ),
    63. ),
    64. ),
    65. Expanded(
    66. flex: 1,
    67. child: Container(
    68. height: 180,
    69. child: layoutImage(),
    70. ),
    71. ),
    72. ],
    73. ),
    74. );
    75. }
    76. }
    77. class layoutImage extends StatelessWidget {
    78. @override
    79. Widget build(BuildContext context) {
    80. return Column(
    81. children: [
    82. Expanded(
    83. child: Container(
    84. width: double.infinity,
    85. padding: EdgeInsets.only(bottom: 10),
    86. child: Image.network(
    87. 'https://cdn.pixabay.com/photo/2015/09/09/16/40/girl-931776_960_720.jpg',
    88. fit: BoxFit.cover),
    89. )),
    90. Expanded(
    91. child: Container(
    92. width: double.infinity,
    93. child: Image.network(
    94. 'https://cdn.pixabay.com/photo/2014/12/16/22/25/woman-570883_960_720.jpg',
    95. fit: BoxFit.cover),
    96. )),
    97. ],
    98. );
    99. }
    100. }

    在这个 布局demo 中,你需要体会, 布局约束的重要性,否则你将有很多无法理解的东西。

    建议查看文档: https://flutter.cn/docs/development/ui/layout/constraints

    Stack 组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return Center(
    24. child: Container(
    25. padding: EdgeInsets.all(10),
    26. // decoration: BoxDecoration(color: Colors.pink),
    27. child: Container(
    28. width: 200,
    29. height: 500,
    30. decoration: BoxDecoration(
    31. color: Colors.pink,
    32. ),
    33. child: Stack(
    34. children: [
    35. Align(
    36. alignment: Alignment.bottomCenter,
    37. child: Icon(Icons.home),
    38. ),
    39. Align(
    40. alignment: Alignment.bottomLeft,
    41. child: Icon(Icons.search_off),
    42. ),
    43. ],
    44. ),
    45. ),
    46. ),
    47. );
    48. }
    49. }

    AspectRatio 的作用是设置调整子元素的宽高比:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return AspectRatio(
    24. aspectRatio: 2 / 1,
    25. child: Image.network(
    26. 'https://cdn.pixabay.com/photo/2021/01/29/09/29/bridge-5960361_960_720.jpg',
    27. fit: BoxFit.cover,
    28. ),
    29. );
    30. }
    31. }

    Card 组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return CardListWidget();
    24. }
    25. }
    26. class CardListWidget extends StatelessWidget {
    27. Widget _imageList(context, index) {
    28. return Card(
    29. margin: EdgeInsets.all(10),
    30. child: Column(
    31. children: [
    32. Expanded(child: Image.network(listData[index]['imageUrl'])),
    33. ListTile(
    34. title: Text(
    35. listData[index]['title'],
    36. textAlign: TextAlign.center,
    37. ),
    38. subtitle: Text(
    39. listData[index]['author'],
    40. textAlign: TextAlign.center,
    41. ),
    42. ),
    43. ],
    44. ),
    45. );
    46. }
    47. @override
    48. Widget build(BuildContext context) {
    49. return GridView.builder(
    50. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    51. crossAxisCount: 2,
    52. mainAxisSpacing: 1,
    53. crossAxisSpacing: 2,
    54. ),
    55. itemCount: listData.length,
    56. itemBuilder: this._imageList);
    57. }
    58. }

    CircleAvatar 圆形头像组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return CardListWidget();
    24. }
    25. }
    26. class CardListWidget extends StatelessWidget {
    27. Widget _imageList(context, index) {
    28. return Card(
    29. margin: EdgeInsets.all(10),
    30. child: Column(
    31. children: [
    32. AspectRatio(
    33. aspectRatio: 20 / 9,
    34. child:
    35. Image.network(listData[index]['imageUrl'], fit: BoxFit.cover),
    36. ),
    37. ListTile(
    38. // CircleAvatar 处理头像
    39. leading: CircleAvatar(
    40. backgroundImage: NetworkImage(listData[index]['imageUrl']),
    41. ),
    42. title: Text(listData[index]['title']),
    43. subtitle: Text(listData[index]['author']),
    44. ),
    45. ],
    46. ),
    47. );
    48. }
    49. @override
    50. Widget build(BuildContext context) {
    51. return ListView.builder(
    52. itemCount: listData.length, itemBuilder: this._imageList);
    53. }
    54. }

    Warp 自动换行组件:

    1. import 'package:flutter/material.dart';
    2. import 'data/newList.dart';
    3. void main() => runApp(MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. home: Scaffold(
    9. appBar: AppBar(
    10. title: Text('Welcome to Flutter'),
    11. ),
    12. body: HomeContent(),
    13. ),
    14. theme: ThemeData(
    15. primaryColor: Colors.pink,
    16. ),
    17. );
    18. }
    19. }
    20. class HomeContent extends StatelessWidget {
    21. @override
    22. Widget build(BuildContext context) {
    23. return Container(
    24. width: double.infinity,
    25. height: 180,
    26. padding: EdgeInsets.all(20),
    27. child: Center(
    28. child: Wrap(
    29. spacing: 5,
    30. runSpacing: 10,
    31. runAlignment: WrapAlignment.spaceAround,
    32. children: [
    33. Container(
    34. width: 70,
    35. height: 70,
    36. child: Column(
    37. children: [
    38. Expanded(
    39. child: CircleAvatar(
    40. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    41. ),
    42. ),
    43. Text('首页'),
    44. ],
    45. ),
    46. ),
    47. Container(
    48. width: 70,
    49. height: 70,
    50. child: Column(
    51. children: [
    52. Expanded(
    53. child: CircleAvatar(
    54. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    55. ),
    56. ),
    57. Text('首页'),
    58. ],
    59. ),
    60. ),
    61. Container(
    62. width: 70,
    63. height: 70,
    64. child: Column(
    65. children: [
    66. Expanded(
    67. child: CircleAvatar(
    68. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    69. ),
    70. ),
    71. Text('首页'),
    72. ],
    73. ),
    74. ),
    75. Container(
    76. width: 70,
    77. height: 70,
    78. child: Column(
    79. children: [
    80. Expanded(
    81. child: CircleAvatar(
    82. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    83. ),
    84. ),
    85. Text('首页'),
    86. ],
    87. ),
    88. ),
    89. Container(
    90. width: 70,
    91. height: 70,
    92. child: Column(
    93. children: [
    94. Expanded(
    95. child: CircleAvatar(
    96. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    97. ),
    98. ),
    99. Text('首页'),
    100. ],
    101. ),
    102. ),
    103. Container(
    104. width: 70,
    105. height: 70,
    106. child: Column(
    107. children: [
    108. Expanded(
    109. child: CircleAvatar(
    110. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    111. ),
    112. ),
    113. Text('首页'),
    114. ],
    115. ),
    116. ),
    117. Container(
    118. width: 70,
    119. height: 70,
    120. child: Column(
    121. children: [
    122. Expanded(
    123. child: CircleAvatar(
    124. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    125. ),
    126. ),
    127. Text('首页'),
    128. ],
    129. ),
    130. ),
    131. Container(
    132. width: 70,
    133. height: 70,
    134. child: Column(
    135. children: [
    136. Expanded(
    137. child: CircleAvatar(
    138. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    139. ),
    140. ),
    141. Text('首页'),
    142. ],
    143. ),
    144. ),
    145. Container(
    146. width: 70,
    147. height: 70,
    148. child: Column(
    149. children: [
    150. Expanded(
    151. child: CircleAvatar(
    152. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    153. ),
    154. ),
    155. Text('首页'),
    156. ],
    157. ),
    158. ),
    159. Container(
    160. width: 70,
    161. height: 70,
    162. child: Column(
    163. children: [
    164. Expanded(
    165. child: CircleAvatar(
    166. backgroundImage: NetworkImage('https://images.pexels.com/photos/6922718/pexels-photo-6922718.jpeg?cs=srgb&dl=pexels-kira-schwarz-6922718.jpg&fm=jpg'),
    167. ),
    168. ),
    169. Text('首页'),
    170. ],
    171. ),
    172. ),
    173. ],
    174. ),
    175. ),
    176. );
    177. }
    178. }