theme: cyanosis
Continue to create, accelerate growth! This is the second day of my participation in the "Nuggets Daily New Project · October Update Challenge", Click to view event details
0. Status of the button family
With the release of Flutter 3.3, the RaisedButton component was removed from the Flutter framework, and the three button brothers who pioneered the interface are completely a thing of the past.

In addition, MaterialButton and RawMaterialButton will also be abandoned in the future, so it is not recommended that you use them again:

At present, there are three button components, TextButton, ElevatedButton, and OutlinedButton. This article will focus on how to use these three.

In addition, some simple button wrapper components can still be used:
copyCupertinoButton : iOS style button CupertinoNavigationBarBackButton : iOS Navigation bar back button BackButton : back button IconButton : icon button CloseButton : close button FloatingActionButton : floating button
There are also some multi-button integrated components, which will be described in detail in subsequent articles:
copyCupertinoSegmentedControl CupertinoSlidingSegmentedControl ButtonBar DropdownButton ToggleButtons
1. The default behavior of the three button components
The following is the default behavior of ElevatedButton: rounded corners and shadows, and water ripples when clicked. When constructing, you must pass in the click callback function onPressed and the child component child :

copyElevatedButton( onPressed: () {}, child: Text('ElevatedButton'), ),
The following is the default behavior of OutlinedButton: rounded corners and outer edges, no padding inside, and water ripples when clicked. When constructing, you must pass in the click callback function onPressed and the child component child :

copyOutlinedButton( onPressed: () {}, child: Text('OutlinedButton'), );
The following is the default behavior of TextButton: no border, no padding, and water ripples when clicked. When constructing, you must pass in the click callback function onPressed and the child component child :

copyTextButton( onPressed: () {}, child: Text('TextButton'), );
2. Button style change
If you look at the source code a little, you can see that these three buttons are essentially the same, and they are all derived classes of ButtonStyleButton. It's just that their default style ButtonStyle is different:

As shown below, queue two abstract methods in the ButtonStyleButton class, which need to be implemented by subclasses, returning the default button style:

Take the ElevatedButton component below, which needs to implement the defaultStyleOf method to return the default theme. When Material3 is not used, related properties are set according to the theme through the styleFrom static method: such as various colors, shadows, text styles, margins, shapes, etc.

Therefore, to modify the button style, you only need to provide the style property setting: the property type is ButtonStyle, and the three button components provide the styleFrom static method to create the ButtonStyle object, which is used as follows:

copyButtonStyle style = ElevatedButton.styleFrom( backgroundColor: Colors.orange, foregroundColor: Colors.white, elevation: 0, padding: const EdgeInsets.symmetric(horizontal: 40), shape: const StadiumBorder(), side: const BorderSide(color: Colors.black,), ); ElevatedButton( onPressed: () {}, child: Text('Login'), style: style );
You can shape by specifying shape, as shown below, and implement a circle component through CircleBorder:

copyButtonStyle style = ElevatedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, elevation: 2, shape: const CircleBorder(), ); ElevatedButton( onPressed: () {}, style: style, child: const Icon(Icons.add) );
The three buttons, TextButton, ElevatedButton, and OutlinedButton, have different default themes. If you provide the same configuration, OutlinedButton can achieve the following display effect.

copyButtonStyle style = OutlinedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, elevation: 0, shape: const CircleBorder(), side:BorderSide.none ); OutlinedButton( onPressed: () {}, style: style, child: const Icon(Icons.add) );
Common style properties:
property name | type | use |
---|---|---|
foregroundColor | Color? | foreground color |
backgroundColor | Color? | background color |
disabledForegroundColor | Color? | Foreground color when disabled |
disabledBackgroundColor | Color? | background color when disabled |
shadowColor | Color? | shadow color |
elevation | double? | shadow depth |
textStyle | TextStyle? | text style |
padding | EdgeInsetsGeometry? | margin |
side | BorderSide? | sideline |
shape | OutlinedBorder? | shape |
In addition, there are some less commonly used properties, just take a look at them:
property name | type | use |
---|---|---|
alignment | AlignmentGeometry? | Alignment in subcomponent area |
enableFeedback | bool? | Whether to enable feedback, such as long-press vibration |
enabledMouseCursor | MouseCursor? | Desktop mouse style |
disabledMouseCursor | MouseCursor? | Desktop mouse style when disabled |
animationDuration | Duration? | animation duration |
minimumSize | Size? | smallest size |
maximumSize | Size? | biggest size |
fixedSize | Size? | Fixed size |
padding | EdgeInsetsGeometry? | margin |
3. Button events
All three buttons need to pass in the onPressed parameter as the click callback when they are constructed. In addition, there are three callbacks onLongPress for listening for long press events; onHover for listening for mouse hover events; onFocusChange for listening for focus change events.

copyElevatedButton( onPressed: () { print('========Login=========='); }, onHover: (bool value) { print('=====onHover===$value=========='); }, onLongPress: () { print('========onLongPress=========='); }, onFocusChange: (bool focus) { print('=====onFocusChange===$focus=========='); }, child: const Text('Login'), );
When the button's onPressed and onLongPress are both null , the button will be disabled . At this time, the button will not respond to clicks, and there is no water ripple effect; in addition, the background color and foreground color of the button are respectively disabledBackgroundColor and disabledForegroundColor Attributes:


copyElevatedButton( onPressed: null, style: style, child: const Text('Login'), );
4. Button size
In the default button style, the minimum size is specified as Size(64, 36) and the maximum size is unlimited.

That is, within the allowable range of the parent's area constraints, the button's size is determined by the child component and the margin. As shown below, the text in the subcomponent is very large, and the button size will be adapted to the size of the text.

copyButtonStyle style = ElevatedButton.styleFrom( // slightly... padding: const EdgeInsets.symmetric(horizontal: 40,vertical: 10), ); ElevatedButton( onPressed: null, style: style, child: const Text('Login',style: TextStyle(fontSize: 50),), );
The parent constraint must not be violated, and under tight constraints, the size of the button will be locked. As follows, apply a tight constraint of 200*40 to the button through SizedBox:

copySizedBox( width: 200, height: 40, child: ElevatedButton( onPressed: (){}, style: style, child: const Text('Login'), ), );
As follows, the tight constraint width is set to 10, you can see that the button can only follow. Even if its minimum size is Size(64, 36), it cannot violate the parent's constraints:

Therefore, if you want to modify the size of the button, there are two ways:
- Start with the child component size margins and adjust the button size.
- Apply a tight constraint to the button, locking the button size.
5. A brief look at the source code implementation of the ButtonStyleButton component
First of all, ButtonStyleButton is an abstract class that inherits from StatefulWidget, indicating that it needs to rely on the state class to implement internal changes.

Return the _ButtonStyleState state object in the createState method, indicating that the logic of button construction is in this state class:
copy@override State<ButtonStyleButton> createState() => _ButtonStyleState();
Looking directly at the constructor in _ButtonStyleState, it will trigger the component's themeStyleOf and defaultStyleOf abstract methods to get the ButtonStyle object at first. This is the logic that TextButton, ElevatedButton, and OutlinedButton need to complete as implementation classes.

The constructed component is the final representation of the button, which uses the ConstrainedBox component to handle constraints; the Material component to handle basic presentation content; InkWell to handle water ripples and related events; Padding to handle padding; and Align to handle alignment.

Use, in general: The ButtonStyleButton component is just a combination of some common components, and the style configuration is performed through the ButtonStyle class to simplify the construction logic. Simplified use through packaging. In addition, we can unify the styles through themes without configuring them one by one, which will be introduced later. That's it for this article, thank you for watching~