
开篇寄语
这一篇文章主要是学习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),
),
),
),
);
}
}
生成效果如下图所示:

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







