Unverified Commit 6a8c393f authored by jslavitz's avatar jslavitz Committed by GitHub

Allows for the CupertinoPicker to have a non white background color (#24085)

* fixes wheel gradient and adds test
parent 26a6fd92
...@@ -39,7 +39,8 @@ class CupertinoPicker extends StatefulWidget { ...@@ -39,7 +39,8 @@ class CupertinoPicker extends StatefulWidget {
/// ///
/// The [backgroundColor] defaults to light gray. It can be set to null to /// The [backgroundColor] defaults to light gray. It can be set to null to
/// disable the background painting entirely; this is mildly more efficient /// disable the background painting entirely; this is mildly more efficient
/// than using [Colors.transparent]. /// than using [Colors.transparent]. Also, if it has transparency, no gradient
/// effect will be rendered.
/// ///
/// The [looping] argument decides whether the child list loops and can be /// The [looping] argument decides whether the child list loops and can be
/// scrolled infinitely. If set to true, scrolling past the end of the list /// scrolled infinitely. If set to true, scrolling past the end of the list
...@@ -121,6 +122,9 @@ class CupertinoPicker extends StatefulWidget { ...@@ -121,6 +122,9 @@ class CupertinoPicker extends StatefulWidget {
/// ///
/// This can be set to null to disable the background painting entirely; this /// This can be set to null to disable the background painting entirely; this
/// is mildly more efficient than using [Colors.transparent]. /// is mildly more efficient than using [Colors.transparent].
///
/// Any alpha value less 255 (fully opaque) will cause the removal of the
/// wheel list edge fade gradient from rendering of the widget.
final Color backgroundColor; final Color backgroundColor;
/// {@macro flutter.rendering.wheelList.offAxisFraction} /// {@macro flutter.rendering.wheelList.offAxisFraction}
...@@ -202,24 +206,32 @@ class _CupertinoPickerState extends State<CupertinoPicker> { ...@@ -202,24 +206,32 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
} }
} }
/// Makes the fade to white edge gradients. /// Makes the fade to [CupertinoPicker.backgroundColor] edge gradients.
Widget _buildGradientScreen() { Widget _buildGradientScreen() {
// Because BlendMode.dstOut doesn't work correctly with BoxDecoration we
// have to just do a color blend. And a due to the way we are layering
// the magnifier and the gradient on the background, using a transparent
// background color makes the picker look odd.
if (widget.backgroundColor != null && widget.backgroundColor.alpha < 255)
return Container();
final Color widgetBackgroundColor = widget.backgroundColor;
return Positioned.fill( return Positioned.fill(
child: IgnorePointer( child: IgnorePointer(
child: Container( child: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
colors: <Color>[ colors: <Color>[
Color(0xFFFFFFFF), widgetBackgroundColor,
Color(0xF2FFFFFF), widgetBackgroundColor.withAlpha(0xF2),
Color(0xDDFFFFFF), widgetBackgroundColor.withAlpha(0xDD),
Color(0x00FFFFFF), widgetBackgroundColor.withAlpha(0),
Color(0x00FFFFFF), widgetBackgroundColor.withAlpha(0),
Color(0xDDFFFFFF), widgetBackgroundColor.withAlpha(0xDD),
Color(0xF2FFFFFF), widgetBackgroundColor.withAlpha(0xF2),
Color(0xFFFFFFFF), widgetBackgroundColor,
], ],
stops: <double>[ stops: const <double>[
0.0, 0.05, 0.09, 0.22, 0.78, 0.91, 0.95, 1.0, 0.0, 0.05, 0.09, 0.22, 0.78, 0.91, 0.95, 1.0,
], ],
begin: Alignment.topCenter, begin: Alignment.topCenter,
...@@ -267,6 +279,34 @@ class _CupertinoPickerState extends State<CupertinoPicker> { ...@@ -267,6 +279,34 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
); );
} }
Widget _buildUnderMagnifierScreen() {
final Color foreground = widget.backgroundColor?.withAlpha(
(widget.backgroundColor.alpha * _kForegroundScreenOpacityFraction).toInt()
);
return Column(
children: <Widget>[
Expanded(child: Container()),
Container(
color: foreground,
constraints: BoxConstraints.expand(
height: widget.itemExtent * widget.magnification,
),
),
Expanded(child: Container()),
],
);
}
Widget _addBackgroundToChild(Widget child) {
return DecoratedBox(
decoration: BoxDecoration(
color: widget.backgroundColor,
),
child: child,
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget result = Stack( Widget result = Stack(
...@@ -292,13 +332,17 @@ class _CupertinoPickerState extends State<CupertinoPicker> { ...@@ -292,13 +332,17 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
_buildMagnifierScreen(), _buildMagnifierScreen(),
], ],
); );
if (widget.backgroundColor != null) { // Adds the appropriate opacity under the magnifier if the background
result = DecoratedBox( // color is transparent.
decoration: BoxDecoration( if (widget.backgroundColor != null && widget.backgroundColor.alpha < 255) {
color: widget.backgroundColor, result = Stack(
), children: <Widget> [
child: result, _buildUnderMagnifierScreen(),
_addBackgroundToChild(result),
]
); );
} else {
result = _addBackgroundToChild(result);
} }
return result; return result;
} }
......
...@@ -56,6 +56,84 @@ void main() { ...@@ -56,6 +56,84 @@ void main() {
}); });
}); });
group('gradient', () {
testWidgets('gradient displays correctly with background color', (WidgetTester tester) async {
const Color backgroundColor = Color.fromRGBO(255, 0, 0, 1.0);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: 300.0,
width: 300.0,
child: CupertinoPicker(
backgroundColor: backgroundColor,
itemExtent: 15.0,
children: const <Widget>[
Text('1'),
Text('1'),
Text('1'),
Text('1'),
Text('1'),
Text('1'),
Text('1'),
],
onSelectedItemChanged: (int i) {},
),
),
),
),
);
final Container container = tester.firstWidget(find.byType(Container));
final BoxDecoration boxDecoration = container.decoration;
expect(boxDecoration.gradient.colors, <Color>[
backgroundColor,
backgroundColor.withAlpha(0xF2),
backgroundColor.withAlpha(0xDD),
backgroundColor.withAlpha(0x00),
backgroundColor.withAlpha(0x00),
backgroundColor.withAlpha(0xDD),
backgroundColor.withAlpha(0xF2),
backgroundColor,
]);
});
testWidgets('No gradient displays with transparent background color', (WidgetTester tester) async {
const Color backgroundColor = Color.fromRGBO(255, 0, 0, 0.5);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: 300.0,
width: 300.0,
child: CupertinoPicker(
backgroundColor: backgroundColor,
itemExtent: 15.0,
children: const <Widget>[
Text('1'),
Text('1'),
Text('1'),
Text('1'),
Text('1'),
Text('1'),
Text('1'),
],
onSelectedItemChanged: (int i) {},
),
),
),
),
);
final DecoratedBox decoratedBox = tester.firstWidget(find.byType(DecoratedBox));
final BoxDecoration boxDecoration = decoratedBox.decoration;
expect(boxDecoration.gradient, isNull);
expect(boxDecoration.color, isNotNull);
});
});
group('scroll', () { group('scroll', () {
testWidgets( testWidgets(
'scrolling calls onSelectedItemChanged and triggers haptic feedback', 'scrolling calls onSelectedItemChanged and triggers haptic feedback',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment