Building widgets outside of AlertDialog - flutter

Is it possible to build a widget, for example a button, in the barrier area of a dialog? By the barrier area I mean the area out of the bounds of an AlertDialog. For example: an AlertDialog is shown in the middle of the screen and a TextButton is in the bottom-right of the screen outside of shown AlertDialog.

You just call from outside and pass the context
getDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) => Center(
child: AlertDialog(
insetPadding: EdgeInsets.all(20),
contentPadding: EdgeInsets.all(0),
content: Container(
height: 200,
width: MediaQuery.of(context).size.width,
child: Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: TextButton(
child: Text("Close"),
)),
)),
),
),
));
}
Here is the full source code
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:so_test/screen/shop_card.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: "ListView.builder",
theme: new ThemeData(primarySwatch: Colors.green),
debugShowCheckedModeBanner: false,
home: HomeApp(),
);
}
}
class HomeApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: InkWell(
onTap: () {
getDialog(context);
},
child: Center(child: Text("Open Dialog")),
),
),
);
}
}
getDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) => Center(
child: AlertDialog(
insetPadding: EdgeInsets.all(20),
contentPadding: EdgeInsets.all(0),
content: Container(
height: 200,
width: MediaQuery.of(context).size.width,
child: Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: TextButton(
child: Text("Close"),
)),
)),
),
),
));
}
output:

Related

How to use the pageview inside show dialog (Flutter)?

The first section is an automatic page that I want to make in a dialog box with Flutter.
This is the code I used to try it out, but I couldn't get to what I wanted
Please help me with this by showing the pageView and auto indicator in the dialog
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final PageController _controller = PageController(initialPage: 0);
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: const Text("Show Dialog"),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('Warning'),
content: PageView(
controller: _controller,
children: [
Container(width: double.infinity, height: double.infinity, color: Colors.yellow),
Container(width: double.infinity, height: double.infinity, color: Colors.red),
Container(width: double.infinity, height: double.infinity, color: Colors.black),
],
),
actionsAlignment: MainAxisAlignment.center,
actions: <Widget>[
Column(
children: [
ElevatedButton(onPressed: () {}, child: const Text("CONTINUE")),
OutlinedButton(onPressed: () {}, child: const Text("NO THANKS"))
],
),
],
),
);
},
),
),
);
}
}
We need to provide size on PageView. Based on your attached image, I am using LayoutBuilder to get the constraints and providing 30% height of the dialog. Use constraints to provide size.
showDialog(
context: context,
builder: (BuildContext context) =>
LayoutBuilder(builder: (context, constraints) {
debugPrint("${constraints.toString()}");
return AlertDialog(
title: const Text('Warning'),
content: Column(
children: [
SizedBox(
height: constraints.maxHeight * .3,
width: constraints.maxWidth,
child: PageView(
controller: _controller,
children: [
Container(color: Colors.yellow),
Container(color: Colors.red),
Container(color: Colors.black),
],
),
),
],
),
actionsAlignment: MainAxisAlignment.center,
actions: <Widget>[
Column(
children: [
ElevatedButton(
onPressed: () {},
child: const Text("CONTINUE")),
OutlinedButton(
onPressed: () {},
child: const Text("NO THANKS"))
],
),
],
);
}));
If you find the content get overflow after adding many widget wrap top column with SingleChildScrollView
showDialog(
context: context,
builder: (BuildContext context) =>
LayoutBuilder(builder: (context, constraints) {
debugPrint("${constraints.toString()}");
return AlertDialog(
title: const Text('Warning'),
content: SingleChildScrollView(
child: Column(
More about LayoutBuilder

Flutter Dismissed Dismissible widget still part of tree issue, can't resolve

I am currently trying to implement a list of dimissable widget items in combination with provider state management, but after hours of searching online i can't find a solution, so decide to post it here.
Here is my code
import 'package:crypto_trader_app/models/strategy.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import '../providers/strategies.dart';
import '../widgets/strategy_item.dart';
import '../widgets/app_drawer.dart';
import './edit_strategy_screen.dart';
class StrategiesScreen extends StatelessWidget {
static const routeName = '/strategies';
Future<void> _refreshStrategies(BuildContext context) async {
await Provider.of<Strategies>(context, listen: false)
.fetchAndSetStrategies();
}
#override
Widget build(BuildContext context) {
print('rebuilding...');
return Scaffold(
appBar: AppBar(
title: const Text('Your Strategies'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
Navigator.of(context).pushNamed(EditStrategyScreen.routeName);
},
),
],
),
drawer: AppDrawer(),
body: FutureBuilder(
future: _refreshStrategies(context),
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return Center(
child: Text("ERROR: ${snapshot.error}"),
);
} else {
return buildStrategyItems(context);
}
},
),
);
}
Widget buildStrategyItems(BuildContext context) {
return RefreshIndicator(
onRefresh: () => _refreshStrategies(context),
child: Consumer<Strategies>(
builder: (ctx, strategiesData, _) => Padding(
padding: EdgeInsets.all(8),
child: ListView.builder(
itemCount: strategiesData.strategies.length,
itemBuilder: (ctx, i) {
final strategy = strategiesData.strategies[i];
return Column(
children: [
Dismissible(
key: UniqueKey(),
background: Container(
color: Colors.red,
child: Icon(
Icons.delete,
color: Colors.white,
size: 40,
),
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 30),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
// remove the strategy item from the list
strategiesData.strategies.removeAt(i);
Provider.of<Strategies>(ctx, listen: false)
.deleteStrategy(strategy.name);
// Then show a snackbar.
Scaffold.of(ctx).showSnackBar(SnackBar(
content: Text("Strategy successfully deleted")));
},
child: Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2.0)),
child: InkWell(
onTap: () {
Navigator.of(ctx).pushNamed(
EditStrategyScreen.routeName,
arguments: strategy.name);
},
child: Padding(
padding: EdgeInsets.all(1),
child: ListTile(
leading: CircleAvatar(
child: Padding(
padding: EdgeInsets.all(5),
child: FittedBox(
child:
Text(strategy.asset.name.toUpperCase()),
),
),
),
title: Text(strategy.name),
subtitle: Text(
DateFormat('dd MMM yyyy')
.format(strategy.dateStarted),
style: TextStyle(fontSize: 10),
),
trailing: Text('1 mins'),
),
),
),
),
),
],
);
},
),
),
),
);
}
}
Essentially every time i swipe to delete a list, then click on a different item and go back to the list i get the following
I would really appreciate if you could help me figure this one out
lets try to use this
key: UniqueKey(),

How to create a button in flutter that always sticks to the bottom of the page?

I want to achieve the following PhonePe UI in flutter. How can I make sure that the "Proceed" button always remains at the bottom position ?
Image
You can copy paste run full code below
You can use bottomSheet attribute of Scaffold
return Scaffold(
...
bottomSheet: Container(
width: MediaQuery.of(context).size.width,
child: RaisedButton(
child: Text('PROCEED'),
onPressed: () {},
),
),
);
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BottomSheetTestPage(),
);
}
}
class BottomSheetTestPage extends StatefulWidget {
#override
_BottomSheetPageState createState() => _BottomSheetPageState();
}
class _BottomSheetPageState extends State<BottomSheetTestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('bottom sheet'),
),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(index.toString()),
subtitle: Text("${index}"),
);
},
itemCount: 300,
),
bottomSheet: Container(
width: MediaQuery.of(context).size.width,
child: RaisedButton(
child: Text('PROCEED'),
onPressed: () {},
),
),
);
}
}
You will solve using Expanded widget.
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: MaterialButton(
onPressed: () => {},
child: Text(’Proceed'),
),
),
),
You can expand the first part of the layout
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Text('FirstPart')),
InkWell(
onTap: () => print('pushed'),
child: Container(
width: 100,
height: 60,
alignment: Alignment.center,
color: Colors.black26,
child: Text('PROCEED'),
),
)
],
);
}
}
You can use stack like this
Stack(
children: <Widget>[
//your other widgets here
Align(
alignment: Alignment.bottomCenter,
child: yourButton,
)
],
),
a simple way to do this is using a Scaffold since the scaffold has a bottomNavigationBar attribute that takes a widget then you can simply pass to it a button like this
Widget build(BuildContext context) {
return Scaffold(
// will always be at the bottom
bottomNavigationBar: FlatButton(onPressed: (){},child: Text("Proceed"),),
body: Text("your body goes here"),
);
}

Flutter :- Custom showDialog with background Color

void _showDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Alert Dialog title"),
content: new Text("Alert Dialog body"),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
I need to create this event where at the moment of showing the dialogue window, the other part of the screen changes color, I am having trouble consulting other sources and the truth is that I cannot coincide with the event.
The goal is to achieve something like this:
just pass barrierColor param to showDialog
showDialog(
context: context,
barrierColor: Color(0x640000FF),
builder: (BuildContext context) {
return AlertDialog(
// ...
);
},
);
You just need to show another screen which act as the dialog on the previous screen. For it first you need to use the Stack widget for it. I have created the demo one, please check it once.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutterlearningapp/colors.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
bool isDialog = false;
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: SafeArea(
top: true,
bottom: true,
child: Stack(
children: <Widget>[
Container(
color: Colors.white,
child: Align(
alignment: Alignment.center,
child: Column(
children: <Widget>[
Container(
color: Colors.pink,
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.4,
),
SizedBox(
height: 10.0,
),
RaisedButton(
onPressed: () {
setState(() {
isDialog = true;
});
},
child: Text("Open Dialog")),
],
),
)),
Positioned.fill(
child: Align(
alignment: Alignment.centerRight,
child: isDialog ? transparentWidget(context) : Container(),
),
)
],
)));
}
Widget transparentWidget(BuildContext context) {
return Container(
color: const Color(0x4D2980b9),
width: double.infinity,
height: double.infinity,
child: Align(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(40.0),
topRight: const Radius.circular(40.0),
bottomLeft: const Radius.circular(40.0),
bottomRight: const Radius.circular(40.0),
)),
child: Center(
child: Text("Your sheet"),
),
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width * 0.8,
),
RaisedButton(
onPressed: () {
setState(() {
isDialog = false;
});
},
child: Text("Cancel"))
],
)),
);
}
}
And thee output of the above program as follow, please check it

Navigation.of(context) not going to another route

I'm trying to go to a new route using the following code but it doesn't work. There are no errors showing up in my IDE and my code seems pretty similar to all the resources I've checked on how to go to a new page.
I've compared my code to others online. I'm guessing its how I've implemented it. I have also tried using:
MaterialPageRoute(builder: (context) => SecondRoute())
But that was not the issue. Here is most of my app:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
Widget setTimer = Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.purpleAccent,width: 3)
),
padding: EdgeInsets.all(32),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Set Timer'),
onPressed: (){
//Go to the second route
Navigator.of(context).pushNamed('/page2');
},
)
],
),
);
return MaterialApp(
title: 'Hands Off',
routes: <String, WidgetBuilder>{
'/page2': (BuildContext context) => SecondRoute(),
},
home: Scaffold(
appBar: AppBar(
title: Text('Timer config'),
),
body: Column(
children: <Widget>[
setTimer,
],
),
),
);
}
}
class SecondRoute extends StatelessWidget{
#override
Widget build(BuildContext context) {
Widget firstRouteButton = Container(
child: Row(
children: <Widget>[
RaisedButton(
child: Text('Go back'),
onPressed: (){
//Go back to main route (first route)
Navigator.of(context).pop(true);
},
)
],
),
);
return Scaffold(
appBar: AppBar(
title: Text('hel'),
),
);
}
}
It should go to a new page but whenever I press the button nothing happens. Can you guys explain why it doesn't work as well please?
Pretty simple.
Use a Builder to pass the context down.
Builder(builder: (BuildContext context) {
return Whatever_Widget;
},)
so the code will be
body: Builder(builder: (BuildContext context) {
return Column(
children: <Widget>[
Container(
decoration: BoxDecoration(border: Border.all(color: Colors.purpleAccent, width: 3)),
padding: EdgeInsets.all(32),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Set Timer'),
onPressed: () {
//Go to the second route
// Navigator.of(context).push(MaterialPageRoute(builder: (context) => SecondRoute()));
Navigator.of(context).pushNamed('/page2');
},
)
],
),
),
],
);
},)