赞
踩
Flutter 中的 ButtonStyle 和 MaterialStateProperty 是在 Flutter 2.0 发布时引入的。在 Flutter 1 中,我们可以通过设置 textColor、backgroundColor 等参数来快速配置按钮的样式。但是在 Flutter 2 中,这些参数被废弃了,取而代之的是 ButtonStyle。ButtonStyle 可以通过 MaterialStateProperty 来支持不同平台下的交互状态展示。本文将深入探讨这两个新特性。
1.MaterialStateProperty
MaterialStateProperty 的设计理念基于 Material Design 去针对全平台的交互进行兼容。在 MaterialStateProperty 体系中,有一个 MaterialState 枚举,它包含了多种不同的状态,例如 disabled、hovered、focused、selected、pressed、dragged、error 等。MaterialStateProperty 可以通过这些状态来控制控件的样式。
举个例子,假设我们需要在按钮悬停时修改按钮的背景颜色。在Flutter 1 中,我们可以这样写:
- FlatButton(
- onPressed: () {},
- color: Colors.blue,
- hoverColor: Colors.green,
- child: Text('Button'),
- )
但是在Flutter 2 中,我们需要使用 ButtonStyle 和 MaterialStateProperty 来实现相同的效果。代码如下:
- TextButton(
- onPressed: () {},
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.resolveWith((states) {
- if (states.contains(MaterialState.hovered)) {
- return Colors.green;
- }
- return Colors.blue;
- }),
- ),
- child: Text('Button'),
- )
在上述代码中,我们使用MaterialStateProperty.resolveWith 方法来处理按钮的背景颜色,这样就可以轻松地实现不同状态下的样式切换。在这个例子中,我们使用 MaterialState.hovered 来处理按钮悬停时的样式。
需要注意的是,MaterialStateProperty 不仅适用于按钮,还适用于其他控件,例如 Checkbox、Radio、Slider 等。
2.ButtonStyle
ButtonStyle 是 Flutter 中一种全新的样式定义方式,它用于定义控件的样式。ButtonStyle 的设计目的是为了在不同平台下提供一致的外观和行为。例如,当用户在不同的操作系统上运行应用程序时,ButtonStyle 可以确保按钮的样式和行为都是一致的。
ButtonStyle 由多个 MaterialStateProperty 组成,每个 MaterialStateProperty 对应一个控件状态。我们可以使用 MaterialStateProperty 来定义控件不同状态下的样式。例如,我们可以通过定义 MaterialStateProperty 来修改按钮在不同状态下的背景颜色、前景色、字体大小等。
举个例子,假设我们需要创建一个带有自定义样式的按钮。在Flutter 1 中,我们可以这样写:
- FlatButton(
- onPressed: () {},
- color: Colors.blue,
- textColor: Colors.white,
- child: Text('Button'),
- )
但是在Flutter 2 中,我们需要使用 ButtonStyle 和 MaterialStateProperty 来实现相同的效果。代码如下:
- TextButton(
- onPressed: () {},
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.all(Colors.blue),
- foregroundColor: MaterialStateProperty.all(Colors.white),
- textStyle: MaterialStateProperty.all(TextStyle(fontSize: 20)),
- ),
- child: Text('Button'),
- )
在上述代码中,我们使用MaterialStateProperty.all 方法来设置按钮的背景颜色、前景色和字体大小。MaterialStateProperty.all 方法可以将一个值应用到所有的状态中。
需要注意的是,ButtonStyle 的属性有很多,例如 elevation、padding、shape 等等。我们可以使用 MaterialStateProperty 来设置每个属性在不同状态下的值。例如,我们可以通过定义 MaterialStateProperty 来修改按钮在悬停状态下的阴影。
- TextButton(
- onPressed: () {},
- style: ButtonStyle(
- elevation: MaterialStateProperty.resolveWith((states) {
- if (states.contains(MaterialState.hovered)) {
- return 10.0;
- }
- return 5.0;
- }),
- ),
- child: Text('Button'),
- )
在上述代码中,我们使用MaterialStateProperty.resolveWith 方法来处理按钮的阴影。当按钮处于悬停状态时,我们将阴影的值设置为 10.0,否则设置为 5.0。
3.Theme
如果你希望在全局范围内应用某个样式,可以使用Flutter 中的 Theme。Theme 可以用来定义全局主题,包括文本样式、颜色、字体、按钮样式等等。在 ButtonStyle 中,我们也可以使用 Theme 来定义全局按钮样式。
举个例子,假设我们需要在全局范围内应用自定义按钮样式。我们可以这样写:
- Theme(
- data: ThemeData(
- textButtonTheme: TextButtonThemeData(
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.all(Colors.blue),
- foregroundColor: MaterialStateProperty.all(Colors.white),
- textStyle: MaterialStateProperty.all(TextStyle(fontSize: 20)),
- ),
- ),
- ),
- child: TextButton(
- onPressed: () {},
- child: Text('Button'),
- ),
- )
在上述代码中,我们使用Theme 来定义全局的按钮样式。我们将 ButtonStyle 定义在 textButtonTheme 中,并将其应用到 TextButton 中。
4.在Flutter 中,ButtonStyle 和 MaterialStateProperty 为我们提供了一种更加灵活、可定制的方式来定义控件样式。ButtonStyle 和 MaterialStateProperty 可以帮助我们实现不同状态下的样式切换,并支持不同平台下的交互状态展示。我们可以使用 ButtonStyle 和 MaterialStateProperty 来定义按钮样式、文本样式、颜色、字体、阴影等等。如果你需要在全局范围内应用某个样式,可以使用 Theme 来定义全局主题。
除了以上介绍的基本用法,ButtonStyle 还有一些高级用法,可以让我们更好地定制控件样式。下面我们将一一介绍。
5.Stateful Button
如果你需要自定义一些不同状态下的样式,可以使用 StatefulButton。StatefulButton 继承自 StatefulWidget,它包含了一个 ValueNotifier<bool>,用来表示按钮的选中状态。在按钮选中时,我们可以自定义按钮的样式。
举个例子,我们可以创建一个带有自定义选中状态的按钮:
- class MyStatefulButton extends StatefulWidget {
- const MyStatefulButton({Key? key}) : super(key: key);
-
- @override
- _MyStatefulButtonState createState() => _MyStatefulButtonState();
- }
-
- class _MyStatefulButtonState extends State<MyStatefulButton> {
- final ValueNotifier<bool> _selected = ValueNotifier(false);
-
- @override
- Widget build(BuildContext context) {
- return ValueListenableBuilder(
- valueListenable: _selected,
- builder: (BuildContext context, bool isSelected, Widget? child) {
- return TextButton(
- onPressed: () {
- setState(() {
- _selected.value = !_selected.value;
- });
- },
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.all(
- isSelected ? Colors.blue : Colors.grey,
- ),
- foregroundColor: MaterialStateProperty.all(Colors.white),
- textStyle: MaterialStateProperty.all(TextStyle(fontSize: 20)),
- ),
- child: Text('Button'),
- );
- },
- );
- }
- }
在上述代码中,我们定义了一个 MyStatefulButton,它包含了一个 ValueNotifier<bool>,用来表示按钮的选中状态。在按钮选中时,我们可以自定义按钮的样式。在 build 方法中,我们使用 ValueListenableBuilder 来监听选中状态的变化,并根据选中状态来更新按钮的样式。
6.Button Bar
如果你需要创建一个按钮组,可以使用 ButtonBar。ButtonBar 是一个将多个按钮组合在一起的控件,它支持垂直或水平排列按钮,并且可以根据需要自动对齐按钮。
举个例子,我们可以创建一个带有多个按钮的 ButtonBar:
- ButtonBar(
- alignment: MainAxisAlignment.center,
- children: [
- ElevatedButton(
- onPressed: () {},
- child: Text('Button 1'),
- ),
- ElevatedButton(
- onPressed: () {},
- child: Text('Button 2'),
- ),
- ElevatedButton(
- onPressed: () {},
- child: Text('Button 3'),
- ),
- ],
- )
在上述代码中,我们使用 ButtonBar 创建了一个带有三个 ElevatedButton 的按钮组。我们将 alignment 属性设置为 MainAxisAlignment.center,使按钮水平居中对齐。
自定义按钮形状
如果你需要创建一个自定义形状的按钮,可以使用 ShapeBorder。ShapeBorder 是一个抽象类,它定义了一个形状。我们可以继承 ShapeBorder 来创建自定义形状。
举个例子,我们可以创建一个圆形按钮:
- class CircleBorder extends ShapeBorder {
- const CircleBorder();
-
- @override
- EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
-
- @override
- Path
- getInnerPath(Rect rect, {TextDirection? textDirection}) {
- return getOuterPath(rect, textDirection: textDirection);
- }
-
- @override
- Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
- return Path()
- ..addOval(rect);
- }
-
- @override
- void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {}
-
- @override
- ShapeBorder scale(double t) {
- return CircleBorder();
- }
- }
在上述代码中,我们定义了一个 CircleBorder 类,它继承自 ShapeBorder。在 getOuterPath 方法中,我们使用 Path.addOval 方法创建了一个圆形的 Path。在 paint 方法中,我们什么都不做,因为我们只是想创建一个圆形形状的按钮。
接下来,我们可以使用 CircleBorder 创建一个圆形的按钮:
- ElevatedButton(
- onPressed: () {},
- child: Text('Button'),
- style: ButtonStyle(
- shape: MaterialStateProperty.all(CircleBorder()),
- ),
- )
在上述代码中,我们使用 CircleBorder 创建了一个圆形的按钮。我们将 shape 属性设置为 MaterialStateProperty.all(CircleBorder()),表示按钮的形状是一个 CircleBorder。
7.自定义按钮效果
如果你需要创建一个自定义效果的按钮,可以使用 InkResponse。InkResponse 是一个将水波纹效果添加到任何 Widget 的控件,它支持自定义水波纹颜色、形状等属性。
举个例子,我们可以创建一个带有自定义水波纹效果的按钮:
- InkResponse(
- onTap: () {},
- child: Container(
- padding: EdgeInsets.all(16),
- child: Text('Button'),
- decoration: BoxDecoration(
- color: Colors.grey,
- borderRadius: BorderRadius.circular(8),
- ),
- ),
- splashColor: Colors.red,
- highlightColor: Colors.yellow,
- borderRadius: BorderRadius.circular(8),
- )
在上述代码中,我们使用 InkResponse 创建了一个带有自定义水波纹效果的按钮。在 onTap 回调中,我们处理按钮的点击事件。我们将 child 属性设置为一个 Container,用来包含按钮的文本。我们将 decoration 属性设置为 BoxDecoration,用来定义按钮的背景颜色和圆角。我们将 splashColor 和 highlightColor 属性分别设置为 Colors.red 和 Colors.yellow,用来定义水波纹的颜色。最后,我们将 borderRadius 属性设置为 BorderRadius.circular(8),用来定义按钮的圆角半径。
总结
通过本文的介绍,我们学习了 ButtonStyle 的基本用法和高级用法,包括使用 MaterialStateProperty、StatefulButton、ButtonBar、自定义按钮形状和自定义按钮效果。通过这些技巧,我们可以更好地定制 Flutter 控件的样式,从而创建更好的用户体验。
写作不易,留个关注,收藏哦!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。