Info Popup Window | Create Popup window in Flutter Listview
Last updated Mar 01, 2021Some times we might be show the content with popup on the current screen due to the device width and height to make proper UI design. Popup is useful when we want to show some additional information or else submit feedback, etc. In this post we are going to create a Popup window in the flutter listview examples.
In this Popup window flutter example we are showing the info window on the listview items.
Let's get started
Step 1: Create android application
Step 2: Create Popup window file which we are going to show as popup
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
const Duration _kWindowDuration = const Duration(milliseconds: 0);
const double _kWindowCloseIntervalEnd = 2.0 / 3.0;
const double _kWindowMaxWidth = 240.0;
const double _kWindowMinWidth = 48.0;
//double _kWindowMinWidth = Get.width/2;
const double _kWindowVerticalPadding = 0.0;
const double _kWindowScreenPadding = 0.0;
Future<T> showPopupWindow<T>({
@required BuildContext context,
RelativeRect position,
@required Widget child,
double elevation: 8.0,
String semanticLabel,
bool fullWidth,
bool isShowBg = false,
}) {
assert(context != null);
String label = semanticLabel;
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
label = semanticLabel;
break;
case TargetPlatform.android:
break;
case TargetPlatform.fuchsia:
label =
semanticLabel ?? MaterialLocalizations.of(context)?.popupMenuLabel;
break;
case TargetPlatform.linux:
break;
case TargetPlatform.macOS:
break;
case TargetPlatform.windows:
break;
}
return Navigator.push(
context,
new _PopupWindowRoute(
context: context,
position: position,
child: child,
elevation: elevation,
semanticLabel: label,
theme: Theme.of(context, shadowThemeOnly: true),
barrierLabel:
MaterialLocalizations.of(context).modalBarrierDismissLabel,
fullWidth: fullWidth,
isShowBg: isShowBg));
}
class _PopupWindowRoute<T> extends PopupRoute<T> {
_PopupWindowRoute({
@required BuildContext context,
RouteSettings settings,
this.child,
this.position,
this.elevation: 8.0,
this.theme,
this.barrierLabel,
this.semanticLabel,
this.fullWidth,
this.isShowBg,
}) : super(settings: settings) {
assert(child != null);
}
final Widget child;
final RelativeRect position;
double elevation;
final ThemeData theme;
final String semanticLabel;
final bool fullWidth;
final bool isShowBg;
@override
Color get barrierColor => null;
@override
bool get barrierDismissible => true;
@override
final String barrierLabel;
@override
Duration get transitionDuration => _kWindowDuration;
@override
Animation<double> createAnimation() {
return new CurvedAnimation(
parent: super.createAnimation(),
curve: Curves.linear,
reverseCurve: const Interval(0.0, _kWindowCloseIntervalEnd));
}
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
Widget win = new _PopupWindow<T>(
route: this,
semanticLabel: semanticLabel,
fullWidth: fullWidth,
);
if (theme != null) {
win = new Theme(data: theme, child: win);
}
return new MediaQuery.removePadding(
context: context,
removeTop: true,
removeBottom: true,
removeLeft: true,
removeRight: true,
child: new Builder(
builder: (BuildContext context) {
return Material(
type: MaterialType.transparency,
child: GestureDetector(
onTap: () {
Get.back();
// NavigatorUtils.goBack(context);
},
child: Container(
width: double.infinity,
height: double.infinity,
color: isShowBg ? Color(0x99000000) : null,
child: new CustomSingleChildLayout(
delegate: new _PopupWindowLayoutDelegate(
position, null, Directionality.of(context)),
child: win,
),
),
),
);
},
),
);
}
}
class _PopupWindow<T> extends StatelessWidget {
const _PopupWindow({
Key key,
this.route,
this.semanticLabel,
this.fullWidth: false,
}) : super(key: key);
final _PopupWindowRoute<T> route;
final String semanticLabel;
final bool fullWidth;
@override
Widget build(BuildContext context) {
final double length = 10.0;
final double unit = 1.0 /
(length + 1.5); // 1.0 for the width and 0.5 for the last item's fade.
final CurveTween opacity =
new CurveTween(curve: const Interval(0.0, 1.0 / 3.0));
final CurveTween width = new CurveTween(curve: new Interval(0.0, unit));
final CurveTween height =
new CurveTween(curve: new Interval(0.0, unit * length));
final Widget child = new ConstrainedBox(
constraints: new BoxConstraints(
minWidth: fullWidth ? double.infinity : _kWindowMinWidth,
maxWidth: fullWidth ? double.infinity : Get.width / 1.15,
),
child: new SingleChildScrollView(
//padding: EdgeInsets.all(20),
padding:
const EdgeInsets.symmetric(vertical: _kWindowVerticalPadding),
child: route.child,
));
return new AnimatedBuilder(
animation: route.animation,
builder: (BuildContext context, Widget child) {
return new Opacity(
opacity: opacity.evaluate(route.animation),
child: new Material(
type: route.elevation == 0
? MaterialType.transparency
: MaterialType.card,
elevation: route.elevation,
child: new Align(
alignment: AlignmentDirectional.topEnd,
widthFactor: width.evaluate(route.animation),
heightFactor: height.evaluate(route.animation),
child: new Semantics(
scopesRoute: true,
namesRoute: true,
explicitChildNodes: true,
label: semanticLabel,
child: child,
),
),
),
);
},
child: child,
);
}
}
class _PopupWindowLayoutDelegate extends SingleChildLayoutDelegate {
_PopupWindowLayoutDelegate(
this.position, this.selectedItemOffset, this.textDirection);
final RelativeRect position;
final double selectedItemOffset;
final TextDirection textDirection;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints.loose(constraints.biggest -
const Offset(_kWindowScreenPadding * 2.0, _kWindowScreenPadding * 2.0));
}
@override
Offset getPositionForChild(Size size, Size childSize) {
double y;
if (selectedItemOffset == null) {
y = position.top;
} else {
y = position.top +
(size.height - position.top - position.bottom) / 2.0 -
selectedItemOffset;
}
// Find the ideal horizontal position.
double x;
x = (size.width - childSize.width) / 2;
if (x < _kWindowScreenPadding) {
x = _kWindowScreenPadding;
} else if (x + childSize.width > size.width - _kWindowScreenPadding) {
x = size.width - childSize.width - _kWindowScreenPadding;
}
if (y < _kWindowScreenPadding)
y = _kWindowScreenPadding;
else if (y + childSize.height > size.height - _kWindowScreenPadding)
y = size.height - childSize.height - _kWindowScreenPadding;
return new Offset(x, y);
}
@override
bool shouldRelayout(_PopupWindowLayoutDelegate oldDelegate) {
return position != oldDelegate.position;
}
}
|
Step 3: Create dart file where we are going to show list of items and display popup window on tap on any widget
import 'package:flutter/material.dart';
import 'popupwindow.dart';
class MyPopupWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
var _infoKey = List<GlobalKey>();
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Popup Window"),backgroundColor: Colors.pink,),
backgroundColor: Colors.blueGrey,
body: Container(
margin: EdgeInsets.all(8),
child: ListView.builder(
cacheExtent: 10000.0,
itemCount: 2,
/*_homeController
.configResponse.value.configLayoutList.length,*/
itemBuilder: (context, index) {
_infoKey.add(GlobalKey(debugLabel: index.toString()));
return Card(
elevation: 1.5,
child: Container(
margin: EdgeInsets.all(10),
child: Column(children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text("Bill ID: 2021",
style: TextStyle(
color: Colors.black,
fontSize: 12,
)),
Text("Home Delivery",
style: TextStyle(
color: Colors.deepOrange,
fontSize: 12,
)),
]),
Column(
crossAxisAlignment:
CrossAxisAlignment.end,
children: [
Text('12-11-2019 - 8:30 PM',
style: TextStyle(
color: Colors.blueGrey,
fontSize: 12,
)),
Text('22 min ago',
style: TextStyle(
color: Colors.grey,
fontSize: 10,
))
])
]),
SizedBox(height: 5),
Row(children: [
Flexible(
flex: 2500,
child: Row(children: [
Icon(Icons.check_circle_outline,
color: Colors.red, size: 14),
SizedBox(width: 5),
Text('Frawns',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
])),
Flexible(
flex: 700,
child: Row(children: [
Text('X',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
)),
Text('1',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
))
])),
Flexible(
flex: 0,
child: Text('\u20B9 2000',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
))),
]),
SizedBox(height: 2),
Row(children: [
Flexible(
flex: 2500,
child: Row(children: [
Icon(Icons.check_circle,
color: Colors.green, size: 14),
SizedBox(width: 5),
Text('Veg Thaliya',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
])),
Flexible(
flex: 700,
child: Row(children: [
Text('X',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
)),
Text('1',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
))
])),
Flexible(
flex: 0,
child: Text('\u20B9 2000',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)))
]),
SizedBox(height: 3),
Divider(color: Colors.grey.withOpacity(0.2)),
Row(children: [
Flexible(
flex: 2500,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(children: [
Text('Paid',
style: TextStyle(
color: Colors.deepOrange,
fontSize: 14,
)),
SizedBox(width: 3),
Text('(Collect)',
style: TextStyle(
color: Colors.black,
fontSize: 12,
))
]),
Row(children: [
Text('Total',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
)),
SizedBox(width: 3),
GestureDetector(
key: _infoKey[index],
onTap: () {
RenderBox renderBox =
_infoKey[index]
.currentContext
.findRenderObject();
Offset offset =
renderBox.localToGlobal(
Offset.zero);
showPopupWindow(
context: context,
fullWidth: false,
//isShowBg:true,
position: RelativeRect
.fromLTRB(
0,
offset.dy +
renderBox
.size
.height,
0,
0),
child: GestureDetector(
onTap: () {},
child: Container(
padding:
EdgeInsets
.all(10),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Item Total',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
]),
SizedBox(height: 3),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Service Tax',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
]),
SizedBox(height: 3),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Delivery Charge',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
]),
SizedBox(height: 3),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Discount',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
]),
SizedBox(height: 3),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('CGST',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
]),
SizedBox(height: 3),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('SGST',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 14,
))
]),
Divider(color: Colors.green),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('TOTAL',
style: TextStyle(
color: Colors.black,
fontSize: 12,
)),
Text('00',
style: TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.bold,
))
])
]))));
},
child: Icon(
Icons.info_outline,
size: 20,
color: Colors.blue)),
SizedBox(width: 3)
])
])),
Flexible(
flex: 700,
child: Row(children: [
Text('X',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
)),
Text('2',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
))
])),
Flexible(
flex: 0,
child: Text('\u20B9 6000',
style: TextStyle(
color: Colors.black,
fontSize: 14,
)))
]),
SizedBox(height: 15),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(children: [
IntrinsicWidth(
child: Column(children: [
Text('REJECT',
style: TextStyle(
color: Colors.black,
fontSize: 12,
)),
SizedBox(height: 1),
Container(
color: Colors.black, height: 1)
])),
SizedBox(width: 20),
IntrinsicWidth(
child: Column(children: [
Text('BILL',
style: TextStyle(
color: Colors.black,
fontSize: 12,
)),
SizedBox(height: 1),
Container(
color: Colors.black, height: 1)
]))
]),
Container(
decoration: new BoxDecoration(
color: Colors.green,
borderRadius:
BorderRadius.circular(5.0),
),
padding: EdgeInsets.all(8),
child: Text('FOOD READY',
style: TextStyle(
color: Colors.white,
fontSize: 12)))
])
])))
;
}),
),
),
);
}
}
|
Show popup window on tap on Guester event by calling the below code
showPopupWindow()
|
Step 4: Run application and see the Popup window on tap
Article Contributed By :
|
|
|
|
2606 Views |