From 47689616a9fcb33536b40da64f7d0e23d97d4b02 Mon Sep 17 00:00:00 2001 From: Huy <104349824+huycozy@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:20:34 +0700 Subject: [PATCH] Add an example for CupertinoPopupSurface (#150357) ### Demo https://github.com/flutter/flutter/assets/104349824/61cd4c96-e01e-4fad-b270-acd7bb55d995 ### Related issue Fixes https://github.com/flutter/flutter/issues/150353 --- .../dialog/cupertino_popup_surface.0.dart | 105 ++++++++++++++++++ .../cupertino_popup_surface.0_test.dart | 70 ++++++++++++ .../flutter/lib/src/cupertino/dialog.dart | 8 ++ 3 files changed, 183 insertions(+) create mode 100644 examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart create mode 100644 examples/api/test/cupertino/dialog/cupertino_popup_surface.0_test.dart diff --git a/examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart b/examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart new file mode 100644 index 00000000000..76a807d7719 --- /dev/null +++ b/examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart @@ -0,0 +1,105 @@ +// 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 [CupertinoPopupSurface]. + +void main() => runApp(const PopupSurfaceApp()); + +class PopupSurfaceApp extends StatelessWidget { + const PopupSurfaceApp({super.key}); + + @override + Widget build(BuildContext context) { + return const CupertinoApp( + home: PopupSurfaceExample(), + ); + } +} + +class PopupSurfaceExample extends StatefulWidget { + const PopupSurfaceExample({super.key}); + + @override + State createState() => _PopupSurfaceExampleState(); +} + +class _PopupSurfaceExampleState extends State { + bool _shouldPaintSurface = true; + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('Paint surface'), + const SizedBox(width: 16.0), + CupertinoSwitch( + value: _shouldPaintSurface, + onChanged: (bool value) => setState(() => _shouldPaintSurface = value), + ), + ], + ), + CupertinoButton( + onPressed: () => _showPopupSurface(context), + child: const Text('Show popup'), + ), + ], + ), + ), + ); + } + + void _showPopupSurface(BuildContext context) { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return CupertinoPopupSurface( + isSurfacePainted: _shouldPaintSurface, + child: Container( + height: 240, + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + decoration: _shouldPaintSurface + ? null + : BoxDecoration( + color: CupertinoTheme.of(context).scaffoldBackgroundColor, + borderRadius: BorderRadius.circular(8.0), + ), + child: const Text('This is a popup surface.'), + ), + ), + const SizedBox(height: 8.0), + SizedBox( + width: double.infinity, + child: CupertinoButton( + color: _shouldPaintSurface + ? null + : CupertinoTheme.of(context).scaffoldBackgroundColor, + onPressed: () => Navigator.pop(context), + child: const Text( + 'Close', + style: TextStyle(color: CupertinoColors.systemBlue), + ), + ), + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/examples/api/test/cupertino/dialog/cupertino_popup_surface.0_test.dart b/examples/api/test/cupertino/dialog/cupertino_popup_surface.0_test.dart new file mode 100644 index 00000000000..37b30f796ab --- /dev/null +++ b/examples/api/test/cupertino/dialog/cupertino_popup_surface.0_test.dart @@ -0,0 +1,70 @@ +// 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/cupertino/dialog/cupertino_popup_surface.0.dart' + as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('CupertinoPopupSurface displays expected widgets in init state', + (WidgetTester tester) async { + await tester.pumpWidget(const example.PopupSurfaceApp()); + + final Finder cupertinoButton = find.byType(CupertinoButton); + expect(cupertinoButton, findsOneWidget); + + final Finder cupertinoSwitch = find.byType(CupertinoSwitch); + expect(cupertinoSwitch, findsOneWidget); + }); + + testWidgets('CupertinoPopupSurface is displayed with painted surface', + (WidgetTester tester) async { + await tester.pumpWidget(const example.PopupSurfaceApp()); + + // CupertinoSwitch is toggled on by default. + expect(tester.widget(find.byType(CupertinoSwitch)).value, isTrue); + + // Tap on the CupertinoButton to show the CupertinoPopupSurface. + await tester.tap(find.byType(CupertinoButton)); + await tester.pumpAndSettle(); + + // Make sure CupertinoPopupSurface is showing. + final Finder cupertinoPopupSurface = find.byType(CupertinoPopupSurface); + expect(cupertinoPopupSurface, findsOneWidget); + + // Confirm that CupertinoPopupSurface is painted with a ColoredBox. + final Finder coloredBox = find.descendant( + of: cupertinoPopupSurface, + matching: find.byType(ColoredBox), + ); + expect(coloredBox, findsOneWidget); + }); + + testWidgets('CupertinoPopupSurface is displayed without painted surface', + (WidgetTester tester) async { + await tester.pumpWidget(const example.PopupSurfaceApp()); + + // Toggling off CupertinoSwitch and confirm its state. + final Finder cupertinoSwitch = find.byType(CupertinoSwitch); + await tester.tap(cupertinoSwitch); + await tester.pumpAndSettle(); + expect(tester.widget(cupertinoSwitch).value, isFalse); + + // Tap on the CupertinoButton to show the CupertinoPopupSurface. + await tester.tap(find.byType(CupertinoButton)); + await tester.pumpAndSettle(); + + // Make sure CupertinoPopupSurface is showing. + final Finder cupertinoPopupSurface = find.byType(CupertinoPopupSurface); + expect(cupertinoPopupSurface, findsOneWidget); + + // Confirm that CupertinoPopupSurface is not painted with a ColoredBox. + final Finder coloredBox = find.descendant( + of: cupertinoPopupSurface, + matching: find.byType(ColoredBox), + ); + expect(coloredBox, findsNothing); + }); +} diff --git a/packages/flutter/lib/src/cupertino/dialog.dart b/packages/flutter/lib/src/cupertino/dialog.dart index c5671479425..2ce5a24a833 100644 --- a/packages/flutter/lib/src/cupertino/dialog.dart +++ b/packages/flutter/lib/src/cupertino/dialog.dart @@ -419,6 +419,14 @@ class _CupertinoAlertDialogState extends State { /// Additionally, the white paint can be disabled to render a blurred rounded /// rectangle without any color (similar to iOS's volume control popup). /// +/// {@tool dartpad} +/// This sample shows how to use a [CupertinoPopupSurface]. The [CupertinoPopupSurface] +/// shows a model popup from the bottom of the screen. +/// Toggling the switch to configure its surface color. +/// +/// ** See code in examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart ** +/// {@end-tool} +/// /// See also: /// /// * [CupertinoAlertDialog], which is a dialog with a title, content, and