CupertinoAlertDialog should not create ScrollController on every build, if null values are passed in constructor. (#134075)
Relanding of https://github.com/flutter/flutter/pull/134071 Verified failed tests succeeded now:
This commit is contained in:
parent
a863ad6e76
commit
cc95ace32c
@ -188,7 +188,7 @@ bool _isInAccessibilityMode(BuildContext context) {
|
||||
/// * [CupertinoDialogAction], which is an iOS-style dialog button.
|
||||
/// * [AlertDialog], a Material Design alert dialog.
|
||||
/// * <https://developer.apple.com/ios/human-interface-guidelines/views/alerts/>
|
||||
class CupertinoAlertDialog extends StatelessWidget {
|
||||
class CupertinoAlertDialog extends StatefulWidget {
|
||||
/// Creates an iOS-style alert dialog.
|
||||
///
|
||||
/// The [actions] must not be null.
|
||||
@ -233,9 +233,6 @@ class CupertinoAlertDialog extends StatelessWidget {
|
||||
/// section when there are many actions.
|
||||
final ScrollController? scrollController;
|
||||
|
||||
ScrollController get _effectiveScrollController =>
|
||||
scrollController ?? ScrollController();
|
||||
|
||||
/// A scroll controller that can be used to control the scrolling of the
|
||||
/// actions in the dialog.
|
||||
///
|
||||
@ -247,37 +244,49 @@ class CupertinoAlertDialog extends StatelessWidget {
|
||||
/// section when it is long.
|
||||
final ScrollController? actionScrollController;
|
||||
|
||||
ScrollController get _effectiveActionScrollController =>
|
||||
actionScrollController ?? ScrollController();
|
||||
|
||||
/// {@macro flutter.material.dialog.insetAnimationDuration}
|
||||
final Duration insetAnimationDuration;
|
||||
|
||||
/// {@macro flutter.material.dialog.insetAnimationCurve}
|
||||
final Curve insetAnimationCurve;
|
||||
|
||||
@override
|
||||
State<CupertinoAlertDialog> createState() => _CupertinoAlertDialogState();
|
||||
}
|
||||
|
||||
class _CupertinoAlertDialogState extends State<CupertinoAlertDialog> {
|
||||
ScrollController? _backupScrollController;
|
||||
|
||||
ScrollController? _backupActionScrollController;
|
||||
|
||||
ScrollController get _effectiveScrollController =>
|
||||
widget.scrollController ?? (_backupScrollController ??= ScrollController());
|
||||
|
||||
ScrollController get _effectiveActionScrollController =>
|
||||
widget.actionScrollController ?? (_backupActionScrollController ??= ScrollController());
|
||||
|
||||
Widget _buildContent(BuildContext context) {
|
||||
final double textScaleFactor = MediaQuery.textScalerOf(context).textScaleFactor;
|
||||
|
||||
final List<Widget> children = <Widget>[
|
||||
if (title != null || content != null)
|
||||
if (widget.title != null || widget.content != null)
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: _CupertinoAlertContentSection(
|
||||
title: title,
|
||||
message: content,
|
||||
title: widget.title,
|
||||
message: widget.content,
|
||||
scrollController: _effectiveScrollController,
|
||||
titlePadding: EdgeInsets.only(
|
||||
left: _kDialogEdgePadding,
|
||||
right: _kDialogEdgePadding,
|
||||
bottom: content == null ? _kDialogEdgePadding : 1.0,
|
||||
bottom: widget.content == null ? _kDialogEdgePadding : 1.0,
|
||||
top: _kDialogEdgePadding * textScaleFactor,
|
||||
),
|
||||
messagePadding: EdgeInsets.only(
|
||||
left: _kDialogEdgePadding,
|
||||
right: _kDialogEdgePadding,
|
||||
bottom: _kDialogEdgePadding * textScaleFactor,
|
||||
top: title == null ? _kDialogEdgePadding : 1.0,
|
||||
top: widget.title == null ? _kDialogEdgePadding : 1.0,
|
||||
),
|
||||
titleTextStyle: _kCupertinoDialogTitleStyle.copyWith(
|
||||
color: CupertinoDynamicColor.resolve(CupertinoColors.label, context),
|
||||
@ -303,10 +312,10 @@ class CupertinoAlertDialog extends StatelessWidget {
|
||||
Widget actionSection = Container(
|
||||
height: 0.0,
|
||||
);
|
||||
if (actions.isNotEmpty) {
|
||||
if (widget.actions.isNotEmpty) {
|
||||
actionSection = _CupertinoAlertActionSection(
|
||||
scrollController: _effectiveActionScrollController,
|
||||
children: actions,
|
||||
children: widget.actions,
|
||||
);
|
||||
}
|
||||
|
||||
@ -330,8 +339,8 @@ class CupertinoAlertDialog extends StatelessWidget {
|
||||
return AnimatedPadding(
|
||||
padding: MediaQuery.viewInsetsOf(context) +
|
||||
const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
|
||||
duration: insetAnimationDuration,
|
||||
curve: insetAnimationCurve,
|
||||
duration: widget.insetAnimationDuration,
|
||||
curve: widget.insetAnimationCurve,
|
||||
child: MediaQuery.removeViewInsets(
|
||||
removeLeft: true,
|
||||
removeTop: true,
|
||||
@ -368,6 +377,13 @@ class CupertinoAlertDialog extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_backupScrollController?.dispose();
|
||||
_backupActionScrollController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// Rounded rectangle surface that looks like an iOS popup surface, e.g., alert dialog
|
||||
|
@ -2664,7 +2664,7 @@ void main() {
|
||||
okNode.dispose();
|
||||
});
|
||||
|
||||
testWidgets('Adaptive AlertDialog shows correct widget on each platform', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Adaptive AlertDialog shows correct widget on each platform', (WidgetTester tester) async {
|
||||
final AlertDialog dialog = AlertDialog.adaptive(
|
||||
content: Container(
|
||||
height: 5000.0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user