flutter基础组件用法

张开发
2026/6/26 12:08:54 15 分钟阅读
flutter基础组件用法
边距​ // 只给 顶部 加边距 padding: EdgeInsets.only(top: 20), // 只给 左边 padding: EdgeInsets.only(left: 15), // 只给 底部 padding: EdgeInsets.only(bottom: 10), // 只给 右边 padding: EdgeInsets.only(right: 5), padding: EdgeInsets.only( top: 10, // 上 left: 20, // 左 bottom: 5, // 下 right: 0, // 右 ), // 上下10左右20 padding: EdgeInsets.symmetric( vertical: 10, // 上下 horizontal: 20, // 左右 ), // 上下左右都是 15 padding: EdgeInsets.all(15), ​圆角// 单独指定圆角 borderRadius: BorderRadius.only( topLeft: Radius.circular(10), bottomRight: Radius.circular(10), topRight: Radius.circular(12), bottomRight: Radius.circular(12), ) // 全部指定 BorderRadius.circular(12) // 没有圆角 borderRadius: BorderRadius.zero // 只有顶部两个角圆角 BorderRadius.vertical(top: Radius.circular(15)) // 只有底部两个角圆角 BorderRadius.vertical(bottom: Radius.circular(20)) // 左侧两个角圆角 BorderRadius.horizontal(left: Radius.circular(10)) // 右侧两个角圆角 BorderRadius.horizontal(right: Radius.circular(10)) // 统一设置圆角 BorderRadius.all(Radius.circular(10)) BorderRadius.all(Radius.elliptical(20, 10))边框// 统一设置 border: Border.all( color: Colors.black, // 边框颜色 width: 2, // 边框宽度 style: BorderStyle.solid, // 边框样式默认就是实线 ) // 单独设置 border: Border( top: BorderSide(color: Colors.red, width: 2), // 上边框 bottom: BorderSide(color: Colors.blue, width: 3), // 下边框 left: BorderSide(color: Colors.green, width: 1), // 左边框 right: BorderSide.none, // 右边框无边框 ) // 对称边框 左右一样 上下一样 border: Border.symmetric( horizontal: BorderSide(color: Colors.purple, width: 2), // 左、右 vertical: BorderSide(color: Colors.orange, width: 1), // 上、下 ) // 无边框 border: Border.none1、Container用于容纳单个子组件的容器组件。集成了若干个单子组件的功能如内外边距、形变、装饰、约束等...变换性约束性import dart:math; import package:flutter/material.dart; class ContainerPage extends StatelessWidget { const ContainerPage({super.key}); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Center( // 垂直水平居中 child: Container( //容器 alignment: Alignment.center, // 水平垂直居中 color: Colors.cyanAccent, width: 150, height: 150 * 0.618, transform: Matrix4.skew(-pi / 10, 0) ..translateByDouble(100.0, 0.0, 0.0, 1.0), constraints: BoxConstraints( // 约束性 minWidth: 100, maxWidth: 100, minHeight: 20, maxHeight: 100, ), child: const Text(Container, style: TextStyle(fontSize: 20)), ), ), ); } }对子组件对齐定位import dart:math; import package:flutter/material.dart; class ContainerPage extends StatelessWidget { const ContainerPage({super.key}); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Center( // 垂直水平居中 child: Container( //容器 alignment: Alignment.bottomRight, // 对子组件对齐定位 color: Colors.cyanAccent, width: 150, height: 150 * 0.618, transform: Matrix4.skew(-pi / 10, 0) ..translateByDouble(100.0, 0.0, 0.0, 1.0), constraints: BoxConstraints( // 约束性 minWidth: 100, maxWidth: 100, minHeight: 20, maxHeight: 100, ), child: const Text(Container, style: TextStyle(fontSize: 20)), ), ), ); } }控制宽高内外间距默认border-boxContainer( //容器 alignment: Alignment.bottomRight, // 对子组件对齐定位 color: Colors.cyanAccent, width: 150, height: 150 * 0.618, padding: EdgeInsets.all(10), // 内边距 margin: EdgeInsets.all(10), // 外边距 transform: Matrix4.skew(-pi / 10, 0) ..translateByDouble(100.0, 0.0, 0.0, 1.0), constraints: BoxConstraints( // 约束性 minWidth: 100, maxWidth: 100, minHeight: 20, maxHeight: 100, ), child: const Text(Container, style: TextStyle(fontSize: 20)), ),边距的用法// 只给 顶部 加边距 padding: EdgeInsets.only(top: 20), // 只给 左边 padding: EdgeInsets.only(left: 15), // 只给 底部 padding: EdgeInsets.only(bottom: 10), // 只给 右边 padding: EdgeInsets.only(right: 5), padding: EdgeInsets.only( top: 10, // 上 left: 20, // 左 bottom: 5, // 下 right: 0, // 右 ), // 上下10左右20 padding: EdgeInsets.symmetric( vertical: 10, // 上下 horizontal: 20, // 左右 ), // 上下左右都是 15 padding: EdgeInsets.all(15),装饰渐变色、圆角、阴影import dart:math; import package:flutter/material.dart; class ContainerPage extends StatelessWidget { const ContainerPage({super.key}); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Center( // 垂直水平居中 child: Container( //容器 alignment: Alignment.bottomRight, // 对子组件对齐定位 // color: Colors.cyanAccent, width: 150, height: 150 * 0.618, padding: EdgeInsets.all(10), // 内边距 margin: EdgeInsets.all(10), // 外边距 transform: Matrix4.skew(-pi / 10, 0) ..translateByDouble(100.0, 0.0, 0.0, 1.0), constraints: BoxConstraints( // 约束性 minWidth: 100, maxWidth: 100, minHeight: 20, maxHeight: 100, ), decoration: BoxDecoration( gradient: LinearGradient( stops: [0.0, 1 / 6, 2 / 6, 3 / 6, 4 / 6, 5 / 6, 1.0], colors: [ 0xffff0000, 0xffFF7F00, 0xffFFFF00, 0xff00FF00, 0xff00FFFF, 0xff0000FF, 0xff8B00FF, ].map((e) Color(e)).toList(), ), borderRadius: BorderRadius.only( topLeft: Radius.circular(10), bottomRight: Radius.circular(10), ), boxShadow: [ BoxShadow( color: Colors.red, offset: Offset(1, 1), blurRadius: 10, spreadRadius: 1, ), ], border: Border.all( color: Colors.black, // 边框颜色 width: 2, // 边框宽度 style: BorderStyle.solid, // 边框样式默认就是实线 ), ), child: const Text(Container, style: TextStyle(fontSize: 20)), ), ), ); } }2、Text基本样式child: const Text( Text, textAlign: TextAlign.left, // 文字居中 style: TextStyle( fontSize: 20, color: Colors.red, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, letterSpacing: 10, // 字距 ), ),文字方向Text( // 1. 生成 1000 个 Text 单词用空格连接成一长串文字 List.filled(1000, Text).join( ), textAlign: TextAlign.start, // 文字对齐默认靠左start开始位置 // textDirection: TextDirection.rtl, // 文字方向从右向左仅排版不反转文字 maxLines: 3, // 最大显示 3 行 overflow: TextOverflow.ellipsis, // 超出 3 行 → 末尾显示 ... style: TextStyle( fontSize: 20, // 字体大小 color: Colors.red, // 颜色红色 fontWeight: FontWeight.bold, // 加粗 fontStyle: FontStyle.italic, // 斜体 letterSpacing: 10, // 字间距非常大10逻辑像素 ), ),装饰线TextStyle( decoration: TextDecoration.underline, // 下划线 decorationThickness: 3, // 线粗 3 decorationStyle: TextDecorationStyle.wavy, // 波浪线 decorationColor: Colors.blue, // 线颜色蓝色 ),文字溢出softWrap: false, // 是否换行 设置了maxLines后会自动换行 overflow: TextOverflow.clip, // 超出部分 ellipsis 省略号 clip 裁剪 visible 显示文字阴影shadows: [ Shadow( color: Colors.cyanAccent, // 阴影颜色青色 offset: Offset(1, 1), // 阴影偏移向右 1向下 1 blurRadius: 10, // 模糊半径10越大约模糊 ), Shadow( color: Colors.blue, // 阴影颜色蓝色 offset: Offset(-0.1, 0.1),// 阴影偏移向左 0.1向下 0.1 blurRadius: 10, // 模糊半径10 ), ],文字反转List.filled(1, Text).join().split().reversed.join(), textDirection: TextDirection.rtl, // 文字方向: 从右向左 只是定位并不是文字反转显示3、GestureDetector组件手势事件的检测器,可接受点击、长按、双击按下、松开、移动等事件并可以获取触点信息。点击、长按、双击import package:flutter/material.dart; class GesturePage extends StatefulWidget { const GesturePage({super.key}); override StateGesturePage createState() _CustomGestureDetectorState(); } class _CustomGestureDetectorState extends StateGesturePage { String _info ; // 存储当前手势状态 override Widget build(BuildContext context) { return GestureDetector( // 点击事件 onTap: () setState(() _info onTap), // 双击事件 onDoubleTap: () setState(() _info onDoubleTap), // 长按事件 onLongPress: () setState(() _info onLongPress), child: Container( alignment: Alignment.center, width: 300, height: 300 * 0.4, // 120 color: Colors.grey.withAlpha(33), child: Text( _info.isEmpty ? 请进行手势操作 : _info, style: const TextStyle(fontSize: 18, color: Colors.blue), ), ), ); } }拖拽import package:flutter/material.dart; class GesturePage extends StatefulWidget { const GesturePage({super.key}); override StateGesturePage createState() _CustomGestureDetectorState(); } class _CustomGestureDetectorState extends StateGesturePage { String _info ; // 存储当前手势状态 final ListString _leftFruits [苹果, 香蕉, 橙子, 葡萄, 草莓]; final ListString _rightFruits [西瓜, 芒果, 菠萝]; void _moveFruit(String fruit, {required bool toLeft}) { setState(() { _leftFruits.remove(fruit); _rightFruits.remove(fruit); if (toLeft) { _leftFruits.add(fruit); } else { _rightFruits.add(fruit); } }); } Widget _buildFruitItem(String fruit) { return DraggableString( data: fruit, feedback: Material( // 拖拽时显示的反馈(被拖拽的物品) color: Colors.transparent, child: _FruitChip(label: fruit, color: Colors.orange), ), childWhenDragging: Opacity( opacity: 0.3, child: _FruitChip(label: fruit, color: Colors.orange), ), child: _FruitChip(label: fruit, color: Colors.orange), ); } Widget _buildDropZone({ required String title, required ListString fruits, required bool acceptToLeft, required Color color, }) { return Expanded( child: DragTargetString( onWillAcceptWithDetails: (details) true, // 是否接受拖拽 onAcceptWithDetails: (details) { // 拖拽完成 _moveFruit(details.data, toLeft: acceptToLeft); }, builder: (context, candidateData, rejectedData) { // context当前构建上下文所有 builder 都有 // candidateData当前区域有可被接受的拖拽物品 // rejectedData正在悬停但不被接受的数据列表 final isHovering candidateData.isNotEmpty; return AnimatedContainer( duration: const Duration(milliseconds: 150), margin: const EdgeInsets.all(8), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isHovering ? color.withValues(alpha: 0.2) : color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), border: Border.all( color: isHovering ? color : color.withValues(alpha: 0.6), width: isHovering ? 2 : 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 10), Expanded( child: SingleChildScrollView( child: Wrap( spacing: 8, runSpacing: 8, children: fruits.map(_buildFruitItem).toList(), ), ), ), ], ), ); }, ), ); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Gesture Drag Demo)), body: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ const Text( 拖拽水果左右两个区域可以互相拖放, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), const SizedBox(height: 8), Expanded( child: Row( children: [ _buildDropZone( title: 左侧水果区, fruits: _leftFruits, acceptToLeft: true, color: Colors.green, ), _buildDropZone( title: 右侧水果区, fruits: _rightFruits, acceptToLeft: false, color: Colors.purple, ), ], ), ), ], ), ), ); } } class _FruitChip extends StatelessWidget { const _FruitChip({required this.label, required this.color}); final String label; final Color color; override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: color.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(20), border: Border.all(color: color.withValues(alpha: 0.6)), ), child: Text(label, style: const TextStyle(fontSize: 14)), ); } }触控位置GestureDetector( onPanDown: (detail) setState( () _info onPanDown:\n相对落点:${detail.localPosition}\n绝对落点:${detail.globalPosition}, ), onPanStart: (detail) setState( () _info onPanStart:\n相对落点:${detail.localPosition}\n绝对落点:${detail.globalPosition}, ), onPanUpdate: (detail) setState( () _info onPanUpdate:\n相对落点:${detail.localPosition}\n绝对落点:${detail.globalPosition}, ), onPanEnd: (detail) setState( () _info onPanEnd:\n初速度:${detail.primaryVelocity}\n最终速度:${detail.velocity}, ), onPanCancel: () setState(() _info onPanCancel), child: Container( alignment: Alignment.center, width: 300, height: 300 * 0.618, color: Colors.grey.withAlpha(33), child: Text( _info, style: const TextStyle(fontSize: 18, color: Colors.blue), textAlign: TextAlign.center, ), ), ),4、ListView带分割线Listimport package:flutter/material.dart; class ListPage extends StatelessWidget { ListPage({super.key}); final data Color[ Colors.purple[50]!, Colors.purple[100]!, Colors.purple[200]!, Colors.purple[300]!, Colors.purple[400]!, Colors.purple[500]!, Colors.purple[600]!, Colors.purple[700]!, Colors.purple[800]!, Colors.purple[900]!, ]; override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(List)), body: Center( // 垂直水平居中 child: SizedBox( height: 200, child: ListView.separated( // 带分割线的列表 itemCount: data.length, itemBuilder: (context, index) _buildItem(data[index]), separatorBuilder: (context, index) const Divider( thickness: 2, height: 10, color: Colors.black, ), // thickness: 分割线宽度 height: 分割线高度 ), ), ), ); } String colorString(Color color) #${color.toARGB32().toRadixString(16).padLeft(8, 0).toUpperCase()}; // 颜色转16进制 Widget _buildItem(Color color) Container( alignment: Alignment.center, width: 100, height: 50, color: color, child: Text( colorString(color), style: const TextStyle( color: Colors.white, shadows: [ Shadow(color: Colors.black, offset: Offset(.5, .5), blurRadius: 2), ], ), ), ); }列表-builder方式SizedBox( // 1. 固定列表高度为 200 height: 200, child: ListView.builder( // 2. 必须指定列表有多少条数据 itemCount: data.length, // 3. 构建每一个列表项 itemBuilder: (context, index) _buildItem(data[index]), ), ),列表-水平滚动scrollDirection: Axis.horizontal, // horizontal 水平滚动 vertical 垂直滚动ListView( reverse: true, // 数据项反转 shrinkWrap: false, // 自适应内容大小 scrollDirection: Axis.horizontal, // horizontal 水平滚动 vertical 垂直滚动 children: data.map((color) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Container( alignment: Alignment.center, width: 100, height: 50, color: color, child: Text( colorString(color), style: const TextStyle( color: Colors.white, shadows: [ Shadow( color: Colors.black, offset: Offset(0.5, 0.5), blurRadius: 2, ), ], ), ), ), ); }).toList(), )5、GridView自适应行列数import package:flutter/material.dart; class GridPage extends StatelessWidget { GridPage({super.key}); final data List.generate(128, (i) Color(0xFF00FFFF - 2 * i)); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Column( children: [ SizedBox(height: 20, child: Text(自适应行列数-GridView.extent)), SizedBox( height: 200, child: GridView.extent( scrollDirection: Axis.horizontal, maxCrossAxisExtent: 100.0, // 最大交叉轴范围(单元格) // mainAxisExtent: 100.0, // 主轴长度单元格) mainAxisSpacing: 2, // 主轴间距 crossAxisSpacing: 2, // 交叉轴间距 childAspectRatio: 1, // 单元格宽高比未设置mainAxisExtent才有效 children: data.map((color) _buildItem(color)).toList(), ), ), ], ), ); } Container _buildItem(Color color) Container( alignment: Alignment.center, width: 100, height: 100, color: color, child: Text( #${color.toARGB32().toRadixString(16).padLeft(8, 0).toUpperCase()}, style: const TextStyle( color: Colors.white, shadows: [ Shadow(color: Colors.black, offset: Offset(.5, .5), blurRadius: 2), ], ), ), ); }固定行/列数import package:flutter/material.dart; class GridPage extends StatelessWidget { GridPage({super.key}); final data List.generate(128, (i) Color(0xFF00FFFF - 2 * i)); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Column( children: [ SizedBox(height: 20, child: Text(固定行列数-GridView.count)), SizedBox( height: 200, child: GridView.count( scrollDirection: Axis.vertical, crossAxisCount: 4, // 交叉轴数量 mainAxisSpacing: 2, // 主轴间距 crossAxisSpacing: 2, // 交叉轴间距 childAspectRatio: 1 / 1, // 单元格宽高比未设置mainAxisExtent才有效 shrinkWrap: true, // 关键让GridView根据内容自适应高度 children: data.map((color) _buildItem(color)).toList(), ), ), ], ), ); } Container _buildItem(Color color) Container( alignment: Alignment.center, width: 100, height: 100, color: color, child: Text( #${color.toARGB32().toRadixString(16).padLeft(8, 0).toUpperCase()}, style: const TextStyle( color: Colors.white, shadows: [ Shadow(color: Colors.black, offset: Offset(.5, .5), blurRadius: 2), ], ), ), ); }固定行和列数SizedBox( height: 20, child: const Text(固定行/列数-GridView.builder), ), SizedBox( height: 200, child: GridView.builder( itemCount: data.length, scrollDirection: Axis.vertical, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, // 交叉轴展示条目数 mainAxisSpacing: 5, // 主轴间距 crossAxisSpacing: 5, // 交叉轴间距 childAspectRatio: 1 / 1, // 宽高比 ), itemBuilder: (_, int position) _buildItem(data[position]), ), ),6、SingleChildScrollView使一个组件具有滑动的效果基本使用import package:flutter/material.dart; class SingleChildScrollViewPage extends StatelessWidget { SingleChildScrollViewPage({super.key}); final data List.generate(128, (i) Color(0xFF00FFFF - 2 * i)); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Column( children: [ SizedBox(height: 20, child: Text(基本使用)), SizedBox( height: 200, child: Column( children: data .map( (color) Container( alignment: Alignment.center, height: 50, color: color, child: Text( #${color.toARGB32().toRadixString(16).padLeft(8, 0).toUpperCase()}, style: const TextStyle( color: Colors.white, shadows: [ Shadow( color: Colors.black, offset: Offset(.5, .5), blurRadius: 2, ), ], ), ), ), ) .toList(), ), ), ], ), ); } }会产生溢出且不会滚动import package:flutter/material.dart; class SingleChildScrollViewPage extends StatelessWidget { SingleChildScrollViewPage({super.key}); final data List.generate(128, (i) Color(0xFF00FFFF - 2 * i)); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Container)), body: Column( children: [ SizedBox(height: 20, child: Text(基本使用)), SizedBox( height: 200, child: SingleChildScrollView( child: Column( children: data .map( (color) Container( alignment: Alignment.center, height: 50, color: color, child: Text( #${color.toARGB32().toRadixString(16).padLeft(8, 0).toUpperCase()}, style: const TextStyle( color: Colors.white, shadows: [ Shadow( color: Colors.black, offset: Offset(.5, .5), blurRadius: 2, ), ], ), ), ), ) .toList(), ), ), ), ], ), ); } }现在不溢出且可以滚动了

更多文章