
开篇寄语
这一篇文章主要是学习Popup,就是页面中的各种提示,包括但不限于弹出框,弹出提示,底部提示等,该项功能类似于Javascript中的alert,当然在App中,表现的形式也是千变万化,本篇文章介绍几种带有普遍性的弹出框,以便快速掌握入手,分享给大家。
前情提要
- 《Flutter制作自己的第一个全平台APP学习之Widgets篇》
- 《Flutter制作自己的第一个全平台APP学习之Layouts篇》
- 《Flutter制作自己的第一个全平台APP学习之Lists篇》
- 《Flutter制作自己的第一个全平台APP学习之AppBar篇》
- 《Flutter制作自己的第一个全平台APP学习之Navigation篇》
内容详情
以下内容大多是更改lib下的main.dart文件内容,删掉里面的内容,复制粘贴代码,开启调试就可以出现了。
Alert Dialog
- 有点类似于Javascript中的alert,警告弹出提示,用到的是AlertDialog这个类,试举一例,如下所示:
import 'dart:async'; import 'package:flutter/material.dart'; void main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Trial', home: Scaffold( appBar: AppBar(title: Text('Hello World')), body: new MyHome())); } } class MyHome extends StatelessWidget { // Wrapper Widget @override Widget build(BuildContext context) { Future.delayed(Duration.zero, () => showAlert(context)); return Container( child: Text("Hello world"), ); } void showAlert(BuildContext context) { showDialog( context: context, builder: (context) => AlertDialog( content: Text("hi"), )); } }
效果如下图所示:

更高级版的则是有取消或者确定等按钮,然后在底部生成提示返回框,代码如下:
import 'dart:async'; import 'package:flutter/material.dart'; void main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Trial', home: Scaffold( appBar: AppBar(title: Text('Hello World')), body: new MyHome())); } } class MyHome extends StatelessWidget { // Wrapper Widget @override Widget build(BuildContext context) { Future.delayed(Duration.zero, () => showAlert(context)); return Container( child: Text("Hello world"), ); } void showAlert(BuildContext context) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Dialog title'), content: const Text( 'Sample alert', ), actions: <Widget>[ TextButton( onPressed: () => Navigator.pop(context, 'Cancel'), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.pop(context, 'OK'), child: const Text('OK'), ), ], ), ).then((returnVal) { if (returnVal != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('You clicked: $returnVal'), action: SnackBarAction(label: 'OK', onPressed: () {}), ), ); } }); } }
效果如下图所示:
展示弹窗 点击后
date picker timeline
- 显示时间轴控件,可以进行时间的选择,试举一例:
首先是安装date_picker_timeline这个flutter第三方资料库,具体可以参看这个官网介绍:
代码如下:
import 'package:date_picker_timeline/date_picker_timeline.dart'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); // ignore: use_key_in_widget_constructors class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), // ignore: prefer_const_constructors home: MyHomePage(title: 'Date Picker Timeline Demo'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, this.title}) : super(key: key); final String? title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { // ignore: prefer_final_fields DatePickerController _controller = DatePickerController(); DateTime _selectedValue = DateTime.now(); @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( // ignore: prefer_const_constructors child: Icon(Icons.replay), onPressed: () { _controller.animateToSelection(); }, ), appBar: AppBar( title: Text(widget.title!), ), body: Container( // ignore: prefer_const_constructors padding: EdgeInsets.all(20.0), color: Colors.blueGrey[100], child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // ignore: prefer_const_constructors Text('You Selected:'), const Padding( padding: EdgeInsets.all(10), ), Text(_selectedValue.toString()), const Padding( padding: EdgeInsets.all(20), ), // ignore: avoid_unnecessary_containers Container( child: DatePicker( DateTime.now(), width: 60, height: 80, controller: _controller, initialSelectedDate: DateTime.now(), selectionColor: Colors.black, selectedTextColor: Colors.white, onDateChange: (DateTime date) { setState(() { _selectedValue = date; }); }, ), ), ], ), )); } }
效果如下图所示:

DatePickerDialog
- 日期选择内置语法,选择一个时间,试举例如下:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); static const String _title = 'Flutter Code Sample'; @override Widget build(BuildContext context) { return const MaterialApp( restorationScopeId: 'app', title: _title, home: MyStatefulWidget(restorationId: 'main'), ); } } class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({Key? key, this.restorationId}) : super(key: key); final String? restorationId; @override _MyStatefulWidgetState createState() => _MyStatefulWidgetState(); } class _MyStatefulWidgetState extends State<MyStatefulWidget> with RestorationMixin { @override String? get restorationId => widget.restorationId; final RestorableDateTime _selectedDate = RestorableDateTime(DateTime.now()); late final RestorableRouteFuture<DateTime?> _restorableDatePickerRouteFuture = RestorableRouteFuture<DateTime?>( onComplete: _selectDate, onPresent: (NavigatorState navigator, Object? arguments) { return navigator.restorablePush( _datePickerRoute, arguments: _selectedDate.value.millisecondsSinceEpoch, ); }, ); static Route<DateTime> _datePickerRoute( BuildContext context, Object? arguments, ) { return DialogRoute<DateTime>( context: context, builder: (BuildContext context) { return DatePickerDialog( restorationId: 'date_picker_dialog', initialEntryMode: DatePickerEntryMode.calendarOnly, initialDate: DateTime.fromMillisecondsSinceEpoch(arguments! as int), firstDate: DateTime(2021, 1, 1), lastDate: DateTime(2050, 1, 1), ); }, ); } @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_selectedDate, 'selected_date'); registerForRestoration( _restorableDatePickerRouteFuture, 'date_picker_route_future'); } void _selectDate(DateTime? newSelectedDate) { if (newSelectedDate != null) { setState(() { _selectedDate.value = newSelectedDate; ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( 'Selected: ${_selectedDate.value.day}/${_selectedDate.value.month}/${_selectedDate.value.year}'), )); }); } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: OutlinedButton( onPressed: () { _restorableDatePickerRouteFuture.present(); }, child: const Text('Open Date Picker'), ), ), ); } }
生成效果如下图所示:

showDateRangePicker
- 选择一段时间区域,由用户选择,试举一例:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); static const String _title = 'Flutter Code Sample'; @override Widget build(BuildContext context) { return const MaterialApp( restorationScopeId: 'app', title: _title, home: MyStatefulWidget(restorationId: 'main'), ); } } class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({Key? key, this.restorationId}) : super(key: key); final String? restorationId; @override _MyStatefulWidgetState createState() => _MyStatefulWidgetState(); } class _MyStatefulWidgetState extends State<MyStatefulWidget> with RestorationMixin { @override String? get restorationId => widget.restorationId; final RestorableDateTimeN _startDate = RestorableDateTimeN(DateTime(2021, 1, 1)); final RestorableDateTimeN _endDate = RestorableDateTimeN(DateTime(2021, 1, 5)); late final RestorableRouteFuture<DateTimeRange?> _restorableDateRangePickerRouteFuture = RestorableRouteFuture<DateTimeRange?>( onComplete: _selectDateRange, onPresent: (NavigatorState navigator, Object? arguments) { return navigator .restorablePush(_dateRangePickerRoute, arguments: <String, dynamic>{ 'initialStartDate': _startDate.value?.millisecondsSinceEpoch, 'initialEndDate': _endDate.value?.millisecondsSinceEpoch, }); }, ); void _selectDateRange(DateTimeRange? newSelectedDate) { if (newSelectedDate != null) { setState(() { _startDate.value = newSelectedDate.start; _endDate.value = newSelectedDate.end; }); } } @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_startDate, 'start_date'); registerForRestoration(_endDate, 'end_date'); registerForRestoration( _restorableDateRangePickerRouteFuture, 'date_picker_route_future'); } static Route<DateTimeRange?> _dateRangePickerRoute( BuildContext context, Object? arguments, ) { return DialogRoute<DateTimeRange?>( context: context, builder: (BuildContext context) { return DateRangePickerDialog( restorationId: 'date_picker_dialog', initialDateRange: _initialDateTimeRange(arguments! as Map<dynamic, dynamic>), firstDate: DateTime(2021, 1, 1), currentDate: DateTime(2021, 1, 25), lastDate: DateTime(2022, 1, 1), ); }, ); } static DateTimeRange? _initialDateTimeRange(Map<dynamic, dynamic> arguments) { if (arguments['initialStartDate'] != null && arguments['initialEndDate'] != null) { return DateTimeRange( start: DateTime.fromMillisecondsSinceEpoch( arguments['initialStartDate'] as int), end: DateTime.fromMillisecondsSinceEpoch( arguments['initialEndDate'] as int), ); } return null; } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: OutlinedButton( onPressed: () { _restorableDateRangePickerRouteFuture.present(); }, child: const Text('Open Date Range Picker'), ), ), ); } }
生成效果如下图所示:

showTimePicker
- 选定24小时时钟时间,试举例如下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); // ignore: use_key_in_widget_constructors class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( builder: (BuildContext context, Widget? child) => MediaQuery( data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), child: child!), home: Container( color: Colors.white, child: Center( child: Builder( builder: (BuildContext context) => ElevatedButton( onPressed: () => showTimePicker( context: context, initialTime: TimeOfDay.now()), child: const Text('Show Time Picker'), ), ), ), ), ); } }
生成效果如下图所示:
SnackBar
- 底部弹出的信息框,试举一例:
import 'package:flutter/material.dart'; void main() => runApp(SnackBarDemo()); class SnackBarDemo extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'SnackBar Demo', home: Scaffold( appBar: AppBar( title: Text('SnackBar Demo'), ), body: SnackBarPage(), ), ); } } class SnackBarPage extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: ElevatedButton( onPressed: () { final snackBar = SnackBar( content: Text('Yay! A SnackBar!'), action: SnackBarAction( label: 'Undo', onPressed: () { // Some code to undo the change. }, ), ); // Find the ScaffoldMessenger in the widget tree // and use it to show a SnackBar. ScaffoldMessenger.of(context).showSnackBar(snackBar); }, child: Text('Show SnackBar'), ), ); } }
生成效果如下图所示:

showAboutDialog
- 显示App关于页面,这个基本上每个App都是需要的,试举一例:
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', home: _MyAppContent(), ); } } class _MyAppContent extends StatefulWidget { @override _MyAppContentState createState() => new _MyAppContentState(); } class _MyAppContentState extends State<_MyAppContent> { @override void initState() { super.initState(); this.initMyLibrary(); } void initMyLibrary() { // ignore: invalid_use_of_visible_for_testing_member LicenseRegistry.reset(); LicenseRegistry.addLicense(() async* { yield LicenseEntryWithLineBreaks(<String>['ACustomLibrary'], ''' Copyright 2016 Woolha.com. All rights reserved. * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS'''); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter Demo'), ), body: Center( child: ElevatedButton( child: Text('Show AboutDialog'), onPressed: () { showAboutDialog( context: context, applicationIcon: FlutterLogo(), applicationName: 'Flutter Demo', applicationVersion: '0.0.1', applicationLegalese: '©2020 Flutter.dev', children: <Widget>[ Padding( padding: EdgeInsets.only(top: 15), child: Text('This is an about dialog in Flutter')) ], ); }, ), ), ); } }
生成效果如下图所示:
showModalBottomSheet
- 这个是从底部弹出,类似于snack bar但是可以展现的内容则更加丰富,试举例如下:
// main.dart import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( // Remove the debug banner debugShowCheckedModeBanner: false, title: 'Flutter Demo', home: HomeScreen(), ); } } class HomeScreen extends StatelessWidget { const HomeScreen({Key? key}) : super(key: key); void _show(BuildContext ctx) { showModalBottomSheet( elevation: 10, backgroundColor: Colors.amber, context: ctx, builder: (ctx) => Container( width: 300, height: 250, color: Colors.white54, alignment: Alignment.center, child: const Text('Hello World!'), )); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter Demo'), ), body: SafeArea( child: Center( child: ElevatedButton( child: const Text('Click Me'), onPressed: () => _show(context), ), ), ), ); } }
生成效果如下图所示:

- 我的微信
- 微信扫一扫加好友
-
- 我的微信公众号
- 扫描关注公众号
-