diff --git a/packages/flutter/lib/src/material/button.dart b/packages/flutter/lib/src/material/button.dart index fc53dcefed..e5f8e3f70a 100644 --- a/packages/flutter/lib/src/material/button.dart +++ b/packages/flutter/lib/src/material/button.dart @@ -184,7 +184,7 @@ class MaterialButton extends StatefulWidget { /// fill the button area if the touch is held for long enough time. If the splash /// color has transparency then the highlight and button color will show through. /// - /// Defaults to the splash color from the [Theme]. + /// Defaults to the Theme's splash color, [ThemeData.splashColor]. final Color splashColor; /// The secondary color of the button when the button is in the down (pressed) @@ -192,7 +192,7 @@ class MaterialButton extends StatefulWidget { /// button color (if any). If the highlight color has transparency, the button color /// will show through. The highlight fades in quickly as the button is held down. /// - /// Defaults to the highlight color from the [Theme]. + /// Defaults to the Theme's highlight color, [ThemeData.highlightColor]. final Color highlightColor; /// The z-coordinate at which to place this button. This controls the size of diff --git a/packages/flutter/lib/src/material/flat_button.dart b/packages/flutter/lib/src/material/flat_button.dart index 1cd8a246f5..4475cbca14 100644 --- a/packages/flutter/lib/src/material/flat_button.dart +++ b/packages/flutter/lib/src/material/flat_button.dart @@ -101,7 +101,7 @@ class FlatButton extends StatelessWidget { /// fill the button area if the touch is held for long enough time. If the splash /// color has transparency then the highlight and button color will show through. /// - /// Defaults to the splash color from the [Theme]. + /// Defaults to the Theme's splash color, [ThemeData.splashColor]. final Color splashColor; /// The secondary color of the button when the button is in the down (pressed) @@ -109,7 +109,7 @@ class FlatButton extends StatelessWidget { /// button color (if any). If the highlight color has transparency, the button color /// will show through. The highlight fades in quickly as the button is held down. /// - /// Defaults to the highlight color from the [Theme]. + /// Defaults to the Theme's highlight color, [ThemeData.highlightColor]. final Color highlightColor; /// The color of the button when the button is disabled. Buttons are disabled diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart index ee62f194a3..12161b9b4d 100644 --- a/packages/flutter/lib/src/material/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -76,6 +76,8 @@ class IconButton extends StatelessWidget { this.alignment: FractionalOffset.center, @required this.icon, this.color, + this.highlightColor, + this.splashColor, this.disabledColor, @required this.onPressed, this.tooltip @@ -136,6 +138,24 @@ class IconButton extends StatelessWidget { /// ``` final Color color; + /// The primary color of the button when the button is in the down (pressed) state. + /// The splash is represented as a circular overlay that appears above the + /// [highlightColor] overlay. The splash overlay has a center point that matches + /// the hit point of the user touch event. The splash overlay will expand to + /// fill the button area if the touch is held for long enough time. If the splash + /// color has transparency then the highlight and button color will show through. + /// + /// Defaults to the Theme's splash color, [ThemeData.splashColor]. + final Color splashColor; + + /// The secondary color of the button when the button is in the down (pressed) + /// state. The higlight color is represented as a solid color that is overlaid over the + /// button color (if any). If the highlight color has transparency, the button color + /// will show through. The highlight fades in quickly as the button is held down. + /// + /// Defaults to the Theme's highlight color, [ThemeData.highlightColor]. + final Color highlightColor; + /// The color to use for the icon inside the button, if the icon is disabled. /// Defaults to the [ThemeData.disabledColor] of the current [Theme]. /// @@ -194,6 +214,8 @@ class IconButton extends StatelessWidget { return new InkResponse( onTap: onPressed, child: result, + highlightColor: highlightColor ?? Theme.of(context).highlightColor, + splashColor: splashColor ?? Theme.of(context).splashColor, radius: math.max( Material.defaultSplashRadius, (iconSize + math.min(padding.horizontal, padding.vertical)) * 0.7, diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 8e747ca0fe..fda219e787 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -165,7 +165,7 @@ class InkResponse extends StatefulWidget { final BorderRadius borderRadius; /// The highlight color of the ink response. If this property is null then the - /// highlight color of the theme will be used. + /// highlight color of the theme, [ThemeData.highlightColor], will be used. /// /// See also: /// @@ -174,7 +174,7 @@ class InkResponse extends StatefulWidget { final Color highlightColor; /// The splash color of the ink response. If this property is null then the - /// splash color of the theme will be used. + /// splash color of the theme, [ThemeData.splashColor], will be used. /// /// See also: /// diff --git a/packages/flutter/test/material/buttons_test.dart b/packages/flutter/test/material/buttons_test.dart index 441dd64003..180116a850 100644 --- a/packages/flutter/test/material/buttons_test.dart +++ b/packages/flutter/test/material/buttons_test.dart @@ -41,7 +41,9 @@ void main() { semantics.dispose(); }); - testWidgets('Does button highlight + splash colors work if set directly', (WidgetTester tester) async { + // This test is very similar to the '...explicit splashColor and highlightColor' test + // in icon_button_test.dart. If you change this one, you may want to also change that one. + testWidgets('MaterialButton with explicit splashColor and highlightColor', (WidgetTester tester) async { final Color directSplashColor = const Color(0xFF000011); final Color directHighlightColor = const Color(0xFF000011); diff --git a/packages/flutter/test/material/icon_button_test.dart b/packages/flutter/test/material/icon_button_test.dart index 00a9152efa..1d9ed34a5b 100644 --- a/packages/flutter/test/material/icon_button_test.dart +++ b/packages/flutter/test/material/icon_button_test.dart @@ -5,6 +5,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import '../rendering/mock_canvas.dart'; + class MockOnPressedFunction implements Function { int called = 0; @@ -191,4 +193,92 @@ void main() { final RenderBox iconBox = tester.renderObject(find.byType(IconButton)); expect(iconBox.size.height, equals(barBox.size.height)); }); + + // This test is very similar to the '...explicit splashColor and highlightColor' test + // in buttons_test.dart. If you change this one, you may want to also change that one. + testWidgets('IconButton with explicit splashColor and highlightColor', (WidgetTester tester) async { + final Color directSplashColor = const Color(0xFF00000F); + final Color directHighlightColor = const Color(0xFF0000F0); + + Widget buttonWidget = new Material( + child: new Center( + child: new IconButton( + icon: const Icon(Icons.android), + splashColor: directSplashColor, + highlightColor: directHighlightColor, + onPressed: () { /* enable the button */ }, + ), + ), + ); + + await tester.pumpWidget( + new Theme( + data: new ThemeData(), + child: buttonWidget, + ), + ); + + final Offset center = tester.getCenter(find.byType(IconButton)); + final TestGesture gesture = await tester.startGesture(center); + await tester.pump(); // start gesture + await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way + + expect( + Material.of(tester.element(find.byType(IconButton))), + paints + ..circle(color: directSplashColor) + ..circle(color: directHighlightColor) + ); + + final Color themeSplashColor1 = const Color(0xFF000F00); + final Color themeHighlightColor1 = const Color(0xFF00FF00); + + buttonWidget = new Material( + child: new Center( + child: new IconButton( + icon: const Icon(Icons.android), + onPressed: () { /* enable the button */ }, + ), + ), + ); + + await tester.pumpWidget( + new Theme( + data: new ThemeData( + highlightColor: themeHighlightColor1, + splashColor: themeSplashColor1, + ), + child: buttonWidget, + ), + ); + + expect( + Material.of(tester.element(find.byType(IconButton))), + paints + ..circle(color: themeSplashColor1) + ..circle(color: themeHighlightColor1) + ); + + final Color themeSplashColor2 = const Color(0xFF002200); + final Color themeHighlightColor2 = const Color(0xFF001100); + + await tester.pumpWidget( + new Theme( + data: new ThemeData( + highlightColor: themeHighlightColor2, + splashColor: themeSplashColor2, + ), + child: buttonWidget, // same widget, so does not get updated because of us + ), + ); + + expect( + Material.of(tester.element(find.byType(IconButton))), + paints + ..circle(color: themeSplashColor2) + ..circle(color: themeHighlightColor2) + ); + + await gesture.up(); + }); }