Fix: Update CupertinoSheetRoute transition rounded corner (#163700)

Fix: Update CupertinoSheetRoute transition rounded corner
fixes: #163334 

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
This commit is contained in:
Kishan Rathore 2025-03-06 02:19:55 +05:30 committed by GitHub
parent 1cd6cb0cdc
commit b44f717d57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 96 additions and 3 deletions

View File

@ -11,6 +11,19 @@ import 'interface_level.dart';
import 'route.dart';
import 'theme.dart';
// Smoothing factor applied to the device's top padding (which approximates the corner radius)
// to achieve a smoother end to the corner radius animation. A value of 1.0 would use
// the full top padding. Values less than 1.0 reduce the effective corner radius, improving
// the animation's appearance. Determined through empirical testing.
const double _kDeviceCornerRadiusSmoothingFactor = 0.9;
// Threshold in logical pixels. If the calculated device corner radius (after applying
// the smoothing factor) is below this value, the corner radius transition animation will
// start from zero. This prevents abrupt transitions for devices with small or negligible
// corner radii. This value, combined with the smoothing factor, corresponds roughly
// to double the targeted radius of 12. Determined through testing and visual inspection.
const double _kRoundedDeviceCornersThreshold = 20.0;
// The distance from the top of the open sheet to the top of the screen, as a ratio
// of the total height of the screen. Found from eyeballing a simulator running
// iOS 18.0.
@ -221,10 +234,15 @@ class CupertinoSheetTransition extends StatefulWidget {
reverseCurve: reverseCurve,
parent: secondaryAnimation,
);
final double deviceCornerRadius = MediaQuery.maybeViewPaddingOf(context)?.top ?? 0;
final double deviceCornerRadius =
(MediaQuery.maybeViewPaddingOf(context)?.top ?? 0) * _kDeviceCornerRadiusSmoothingFactor;
final bool roundedDeviceCorners = deviceCornerRadius > _kRoundedDeviceCornersThreshold;
final Animatable<BorderRadiusGeometry> decorationTween = Tween<BorderRadiusGeometry>(
begin: BorderRadius.circular(deviceCornerRadius),
begin: BorderRadius.vertical(
top: Radius.circular(roundedDeviceCorners ? deviceCornerRadius : 0),
),
end: BorderRadius.circular(12),
);
@ -262,7 +280,13 @@ class CupertinoSheetTransition extends StatefulWidget {
animation: radiusAnimation,
child: child,
builder: (BuildContext context, Widget? child) {
return ClipRRect(borderRadius: radiusAnimation.value, child: contrastedChild);
return ClipRRect(
borderRadius:
!secondaryAnimation.isDismissed
? radiusAnimation.value
: BorderRadius.circular(0),
child: contrastedChild,
);
},
),
),

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../widgets/navigator_utils.dart';
@ -745,6 +746,74 @@ void main() {
expect(sheetNavBarHeight, lessThan(homeNavBardHeight));
});
testWidgets('Previous route corner radius goes to same when sheet route is popped', (
WidgetTester tester,
) async {
final GlobalKey scaffoldKey = GlobalKey();
await tester.pumpWidget(
CupertinoApp(
home: CupertinoPageScaffold(
key: scaffoldKey,
child: Column(
children: <Widget>[
const Text('Page 1'),
CupertinoButton(
onPressed: () {
Navigator.push<void>(
scaffoldKey.currentContext!,
CupertinoSheetRoute<void>(
builder: (BuildContext context) {
return CupertinoPageScaffold(
child: GestureDetector(
onTap: () => Navigator.pop(context),
child: const Icon(Icons.arrow_back_ios),
),
);
},
),
);
},
child: const Text('Push Page 2'),
),
],
),
),
),
);
expect(find.text('Page 1'), findsOneWidget);
expect(
tester
.getTopLeft(
find.ancestor(of: find.text('Page 1'), matching: find.byType(CupertinoPageScaffold)),
)
.dy,
equals(0.0),
);
expect(find.byType(Icon), findsNothing);
await tester.tap(find.text('Push Page 2'));
await tester.pumpAndSettle();
// Previous page is still visible behind the new sheet.
expect(find.text('Page 1'), findsOneWidget);
final Offset pageOneOffset = tester.getTopLeft(
find.ancestor(of: find.text('Page 1'), matching: find.byType(CupertinoPageScaffold)),
);
expect(pageOneOffset.dy, greaterThan(0.0));
expect(pageOneOffset.dx, greaterThan(0.0));
expect(find.byType(Icon), findsOneWidget);
// Pop Sheet Route
await tester.tap(find.byType(Icon));
await tester.pumpAndSettle();
final Finder clipRRectFinder = find.byType(ClipRRect);
final Rect clipRect = tester.getRect(clipRRectFinder);
expect(clipRect.center, equals(const Offset(400, 300)));
});
group('drag dismiss gesture', () {
Widget dragGestureApp(GlobalKey homeScaffoldKey, GlobalKey sheetScaffoldKey) {
return CupertinoApp(