From f1c2d784550c331dc5d67859d94b20f5aea31763 Mon Sep 17 00:00:00 2001 From: David Yang Date: Sun, 19 Mar 2017 05:19:40 -0700 Subject: [PATCH] Updating Cupertino Button MinSize to comply with iOS guidelines (#8881) The recommended minimum tappable area is actually 44.0pt according to the [iOS Human Interface Guidline](https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/). > Provide ample spacing for interactive elements. Try to maintain a minimum tappable area of 44pt x 44pt for all controls. I've also added an override to allow for flexibility in situations where designers get naughty and have a desire to make everything super small. --- .../flutter/lib/src/cupertino/button.dart | 17 ++++++++++++-- .../flutter/test/cupertino/button_test.dart | 23 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/flutter/lib/src/cupertino/button.dart b/packages/flutter/lib/src/cupertino/button.dart index 7a52af5a80..b48e9c044c 100644 --- a/packages/flutter/lib/src/cupertino/button.dart +++ b/packages/flutter/lib/src/cupertino/button.dart @@ -46,6 +46,7 @@ class CupertinoButton extends StatefulWidget { @required this.child, this.padding, this.color, + this.minSize: 44.0, @required this.onPressed, }); @@ -69,6 +70,16 @@ class CupertinoButton extends StatefulWidget { /// If this is set to null, the button will be disabled. final VoidCallback onPressed; + /// Minimum size of the button. + /// + /// Defaults to 44.0 which the iOS Human Interface Guideline recommends as the + /// minimum tappable area + /// + /// See also: + /// + /// * + final double minSize; + /// Whether the button is enabled or disabled. Buttons are disabled by default. To /// enable a button, set its [onPressed] property to a non-null value. bool get enabled => onPressed != null; @@ -129,11 +140,13 @@ class _CupertinoButtonState extends State with SingleTickerProv onPointerDown: enabled ? _handleTapDown : null, onPointerUp: enabled ? _handleTapUp : null, onPointerCancel: enabled ? _handleTapCancel : null, - child: new GestureDetector( onTap: config.onPressed, child: new ConstrainedBox( - constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0), + constraints: new BoxConstraints( + minWidth: config.minSize, + minHeight: config.minSize, + ), child: new FadeTransition( opacity: new CurvedAnimation( parent: _animationController, diff --git a/packages/flutter/test/cupertino/button_test.dart b/packages/flutter/test/cupertino/button_test.dart index 6ee157d790..cb21fc6182 100644 --- a/packages/flutter/test/cupertino/button_test.dart +++ b/packages/flutter/test/cupertino/button_test.dart @@ -13,7 +13,7 @@ const TextStyle testStyle = const TextStyle( ); void main() { - testWidgets('Layout minimum size', (WidgetTester tester) async { + testWidgets('Default layout minimum size', (WidgetTester tester) async { await tester.pumpWidget( new Center(child: new CupertinoButton( child: new Text('X', style: testStyle), @@ -23,8 +23,25 @@ void main() { final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton)); expect( buttonBox.size, - // 1 10px character + 16px * 2 is smaller than the 48px minimum. - const Size.square(48.0), + // 1 10px character + 16px * 2 is smaller than the default 44px minimum. + const Size.square(44.0), + ); + }); + + testWidgets('Minimum size parameter', (WidgetTester tester) async { + final double minSize = 60.0; + await tester.pumpWidget( + new Center(child: new CupertinoButton( + child: new Text('X', style: testStyle), + onPressed: null, + minSize: minSize, + )) + ); + final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton)); + expect( + buttonBox.size, + // 1 10px character + 16px * 2 is smaller than defined 60.0px minimum + new Size.square(minSize), ); });