Flutter 目前拥有400多个组件,其中常用的也就那么几个。大家学习 Flutter 一般都是看的其他人的教程,或者官网的文档教程,这些教程里用到的组件只有那些常用的,更多的组件需要我们自己去看 api 文档。这里列出一些不太常使用的组件,或许可以在你需要的时候帮助你。
AboutDialog
这是一个对话框,其中包含应用程序的图标、名称、版本号和版权,以及一个自定生成的显示应用程序使用的软件许可的按钮和界面。
要想使用AboutDialog
我们只需调用showAboutDialog
方法就行:
Scaffold(
appBar: AppBar(title: const Text("AboutDialog")),
body: Center(
child: ElevatedButton(
onPressed: () {
showAboutDialog(context: context);
},
child: const Text("显示AboutDialog"),
),
),
);
showAboutDialog
一共有以下几个参数:
BuildContext context
:BuildContext 对象String? applicationName
:程序名称String? applicationVersion
:程序版本Widget? applicationIcon
:程序图标String? applicationLegalese
:程序版权声明List<Widget>? children
:子组件bool useRootNavigator = true
:是否使用根导航RouteSettings? routeSettings
:路由设置Offset? anchorPoint
:锚点位置
showAboutDialog(
context: context,
applicationName: "Flutter冷门组件",
applicationVersion: "0.0.1",
applicationIcon: const FlutterLogo(),
applicationLegalese: "没有版权声明",
children: [
Container(height: 12, color: Colors.blue),
Container(height: 12, color: Colors.red),
Container(height: 12, color: Colors.green),
],
useRootNavigator: true,
routeSettings: null,
anchorPoint: Offset.zero,
);
当我们点击VIEW LICENSES
按钮时,会自动跳转到系统生成的软件许可证界面,里面列出了程序所使用的的所有包的证书:
AboutListTile
适合用在Drawer
中显示AboutDialog
的组件。
该组件的使用很简单,直接使用不用传参就有效果:
return Scaffold(
body: SafeArea(
child: AboutListTile(),
),
);
不仅有效果,还有附带点击事件:
该组件有以下几个属性,大部分是设置AboutDialog
:
Key? key
:标识键Widget? icon
:左边显示的图标Widget? child
:子组件String? applicationName
:程序名称String? applicationVersion
:程序版本号Widget? applicationIcon
:程序图标String? applicationLegalese
:程序版权声明List<Widget>? aboutBoxChildren
:弹窗显示的子组件bool? dense
:是否是垂直密集列表的一部分
我们使用以上几个属性看一下:
return Scaffold(
body: SafeArea(
child: AboutListTile(
icon: const Icon(Icons.perm_device_info),
applicationName: "Flutter冷门组件",
applicationVersion: "0.0.1",
applicationIcon: const FlutterLogo(),
applicationLegalese: "没有版权声明",
aboutBoxChildren: [
Container(height: 12, color: Colors.blue),
Container(height: 12, color: Colors.red),
Container(height: 12, color: Colors.green),
],
dense: false,
child: const Text("这是一个AboutListTitle"),
),
),
);
再贴一个dense
不同值得情况下的对比:
当然,你也可以直接使用LicensePage
这个组件。
AbsorbPointer
使子组件不再触发命中测试/事件。
该组件有以下几个属性:
Key? key
:标识键bool absorbing
:是否会在命中测试中吸收指针。默认为trueWidget? child
:子组件bool? ignoringSemantics
:编译语义树时是否忽略此渲染对象的语义
我有以下一个组件:
Center(
child: InkWell(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("点击了")),
);
},
child: Container(width: 250, height: 250, color: Colors.blue),
),
)
每次点击时都会弹出一个 SnackBar:
现在在外面套个AbsorbPointer
:
AbsorbPointer(
child: Center(
child: InkWell(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("点击了")),
);
},
child: Container(width: 250, height: 250, color: Colors.blue),
),
),
)
若想重新使子组件能接受点击事件,只要把absorbing
属性设置为false
就行。
Accumulator
整数的可变包装器,可以通过引用传递来在递归堆栈中跟踪值。
准确来说这不是组件,就是 Flutter 中的一个类。它只有一个int
类型的属性value
,默认值是0。有两个比较重要的实例方法:value
和increment
。
下面通过一个简单的例子来使用以下:
// 先实例化一下
Accumulator accumulator = Accumulator();
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("${accumulator.value}", style: const TextStyle(fontSize: 24)),
ElevatedButton(
onPressed: () {
accumulator.increment(5);
setState(() {});
},
child: const Text("+5"),
),
],
),
)
AnnotatedRegion
在某个页面中单独修改状态栏和导航栏主题
Key? key
:标识键Widget child
:子组件- SystemUiOverlayStyle value`:SystemUiOverlayStyle属性
bool sized
:推入树中的层是否提供大小。默认为true
AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: Colors.white,
statusBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
),
child: Scaffold(
// ...
)
)
有两点需要注意:
-
该组件最好是在没有使用官方
AppBar
时使用,因为AppBar
的systemOverlayStyle
属性会覆盖状态栏的样式(AppBar
的systemOverlayStyle
无法修改系统导航栏的样式)。当然,可以两个混合使用:AnnotatedRegion( value: SystemUiOverlayStyle( systemNavigationBarColor: _colors[_index], systemNavigationBarIconBrightness: _flag ? Brightness.light : Brightness.dark, ), child: Scaffold( appBar: AppBar( title: Text( "AnnotatedRegion", style: TextStyle(color: _flag ? Colors.white : Colors.black), ), leading: BackButton(color: _flag ? Colors.white : Colors.black), backgroundColor: _colors[_index], systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: _colors[_index], statusBarIconBrightness: _flag ? Brightness.light : Brightness.dark, ), ), body: ... ), )
- 使用该组件修改的样式会运用到全局,最好的方法是在返回或进入的另一个界面也对
SystemUiOverlayStyle
进行设置
ButtonBar
用来对齐一系列按钮
Key? key
:标识键MainAxisAlignment? alignment
:主轴对齐方式。默认为MainAxisAlignment.endMainAxisSize? mainAxisSize
:水平空间的宽度。默认为MainAxisSize.maxButtonTextTheme? buttonTextTheme
:按钮文本主题double? buttonMinWidth
:按钮最小宽度double? buttonHeight
:按钮高度EdgeInsetsGeometry? buttonPadding
:按钮内边距bool? buttonAlignedDropdown
:定义DropdownButton
菜单的宽度是否与按钮的宽度匹配。默认值为 falseButtonBarLayoutBehavior? layoutBehavior
:定义ButtonBar
是否应使用最小尺寸约束或填充来调整自身大小。默认值为 ButtonBarLayoutBehavior.paddedVerticalDirection? overflowDirection
:定义子项(如果溢出)的垂直方向。默认为VerticalDirection.downdouble? overflowButtonSpacing
:按钮栏溢出时按钮之间的间距List children = const []
:子按钮
Center(
child: ButtonBar(
mainAxisSize: MainAxisSize.max,
alignment: MainAxisAlignment.center,
buttonPadding: const EdgeInsets.symmetric(horizontal: 12),
overflowDirection: VerticalDirection.up,
children: [
const BackButton(),
const CloseButton(),
DropdownButton(
value: "语文",
items: const [
DropdownMenuItem(value: "语文", child: Text("语文")),
DropdownMenuItem(value: "数学", child: Text("数学")),
DropdownMenuItem(value: "英语", child: Text("英语")),
],
onChanged: (value) {},
),
TextButton(onPressed: () {}, child: const Text("按钮")),
ElevatedButton(onPressed: () {}, child: const Text("按钮")),
OutlinedButton(onPressed: () {}, child: const Text("按钮")),
MaterialButton(onPressed: () {}, child: const Text("按钮")),
],
),
),
这样看起来这个组件是不是很鸡肋。其实这种用法是错误的,官方推荐在弹窗中使用该组件:
TextButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: const Text("弹窗"),
children: [
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text("ButtonBar的使用"),
),
ButtonBar(
children: [
OutlinedButton(onPressed: () {}, child: const Text("确认")),
OutlinedButton(onPressed: () {}, child: const Text("取消")),
],
),
],
);
},
);
},
child: const Text("按钮"),
)
BackdropFilter
对子元素应用滤镜。
Key? key
:标识键ImageFilter filter
:在绘制子项之前应用于现有绘制内容的图像过滤器Widget? child
:子组件BlendMode blendMode
:用于将过滤的背景内容应用到背景表面的混合模式。默认值为BlendMode.srcOver
Stack(
children: [
Image.asset("assets/images/sxt.jpg", fit: BoxFit.cover),
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
child: ColoredBox(color: Colors.white.withOpacity(.2)),
),
],
),