diff --git a/examples/api/lib/painting/rounded_superellipse_border/rounded_superellipse_border.0.dart b/examples/api/lib/painting/rounded_superellipse_border/rounded_superellipse_border.0.dart new file mode 100644 index 00000000000..38dee663f98 --- /dev/null +++ b/examples/api/lib/painting/rounded_superellipse_border/rounded_superellipse_border.0.dart @@ -0,0 +1,134 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/cupertino.dart'; + +/// Flutter code sample for [RoundedSuperellipseBorder]. + +void main() { + runApp(const RoundedSuperellipseBorderExample()); +} + +class RoundedSuperellipseBorderExample extends StatefulWidget { + const RoundedSuperellipseBorderExample({super.key}); + + static final GlobalKey kBorderBoxKey = GlobalKey(); + static final GlobalKey kThicknessSliderKey = GlobalKey(); + static final GlobalKey kRadiusSliderKey = GlobalKey(); + + @override + State createState() => RoundedSuperellipseBorderExampleState(); +} + +class RoundedSuperellipseBorderExampleState extends State { + bool _toggle = true; + double _borderThickness = 4; + double _borderRadius = 69; + + @override + Widget build(BuildContext context) { + final BorderRadiusGeometry radius = BorderRadiusGeometry.circular(_borderRadius); + final BorderSide side = BorderSide(width: _borderThickness, color: const Color(0xFF111111)); + final ShapeBorder shape = _toggle + ? RoundedSuperellipseBorder(side: side, borderRadius: radius) + : RoundedRectangleBorder(side: side, borderRadius: radius); + + return CupertinoApp( + home: CupertinoPageScaffold( + child: Center( + child: Container( + padding: const EdgeInsetsGeometry.all(10), + constraints: const BoxConstraints(maxWidth: 600), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 16, + children: [ + // The border is drawn by this DecoratedBox. + DecoratedBox( + key: RoundedSuperellipseBorderExample.kBorderBoxKey, + decoration: ShapeDecoration(shape: shape, color: const Color(0xFFFFC107)), + child: const SizedBox(width: 400, height: 200), + ), + + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Shape: '), + CupertinoSwitch( + value: _toggle, + onChanged: (bool value) { + setState(() { + _toggle = value; + }); + }, + ), + ConstrainedBox( + constraints: const BoxConstraints(minWidth: 200), + child: Text(_toggle ? 'Rounded Superellipse' : 'Rounded Rect'), + ), + ], + ), + SliderRow( + label: 'Thickness', + slider: CupertinoSlider( + value: _borderThickness, + max: 14, + min: 0.0000001, + onChanged: (double value) { + setState(() { + _borderThickness = value; + }); + }, + ), + valueString: _borderThickness.toStringAsFixed(1), + key: RoundedSuperellipseBorderExample.kThicknessSliderKey, + ), + SliderRow( + label: 'Radius', + slider: CupertinoSlider( + value: _borderRadius, + max: 100, + onChanged: (double value) { + setState(() { + _borderRadius = value; + }); + }, + ), + valueString: _borderRadius.toStringAsFixed(1), + key: RoundedSuperellipseBorderExample.kRadiusSliderKey, + ), + ], + ), + ), + ), + ), + ); + } +} + +class SliderRow extends StatelessWidget { + const SliderRow({ + super.key, + required this.label, + required this.slider, + required this.valueString, + }); + + final String label; + final Widget slider; + final String valueString; + + @override + Widget build(BuildContext context) { + return Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ConstrainedBox(constraints: const BoxConstraints(minWidth: 50), child: Text(label)), + Expanded(child: slider), + ConstrainedBox(constraints: const BoxConstraints(minWidth: 50), child: Text(valueString)), + ], + ); + } +} diff --git a/examples/api/test/painting/rounded_superellipse_border/rounded_superellipse_border.0_test.dart b/examples/api/test/painting/rounded_superellipse_border/rounded_superellipse_border.0_test.dart new file mode 100644 index 00000000000..620efd2a867 --- /dev/null +++ b/examples/api/test/painting/rounded_superellipse_border/rounded_superellipse_border.0_test.dart @@ -0,0 +1,40 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/cupertino.dart'; + +import 'package:flutter_api_samples/painting/rounded_superellipse_border/rounded_superellipse_border.0.dart' + as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Smoke Test', (WidgetTester tester) async { + await tester.pumpWidget(const example.RoundedSuperellipseBorderExample()); + expect(find.byType(example.RoundedSuperellipseBorderExample), findsOneWidget); + + final RenderObject borderBox = tester.renderObject( + find.byKey(example.RoundedSuperellipseBorderExample.kBorderBoxKey), + ); + expect(borderBox, paints..rsuperellipse()); + + // Test tapping switches + await tester.tap(find.byType(CupertinoSwitch)); + await tester.pumpAndSettle(); + expect(borderBox, paints..rrect()); + + final Finder radiusSlider = find.descendant( + of: find.byKey(example.RoundedSuperellipseBorderExample.kRadiusSliderKey), + matching: find.byType(CupertinoSlider), + ); + expect(radiusSlider, findsOne); + final Finder thicknessSlider = find.descendant( + of: find.byKey(example.RoundedSuperellipseBorderExample.kThicknessSliderKey), + matching: find.byType(CupertinoSlider), + ); + expect(thicknessSlider, findsOne); + // Preferrably we should test the interaction between the sliders and the + // drawn box, but it seems very hard if the slider thumb doesn't start at + // the left-most position. + }); +} diff --git a/packages/flutter/lib/src/painting/rounded_rectangle_border.dart b/packages/flutter/lib/src/painting/rounded_rectangle_border.dart index 9fe34b9131f..4ec34fe4229 100644 --- a/packages/flutter/lib/src/painting/rounded_rectangle_border.dart +++ b/packages/flutter/lib/src/painting/rounded_rectangle_border.dart @@ -205,6 +205,20 @@ class _RoundedRectangleToCircleBorder extends _ShapeToCircleBorder