Hey guys I'm working on some project and need to create a custom dropdown,
like this
I am able to make that here is the code, the code is messy but I will refactor it once I make it work. Or if you have some other way how I can accomplish this I'm open to suggestions.
GlobalKey? actionKey = GlobalKey();
List<String> picked = [];
List<IconData> icons = [
Icons.blur_circular_outlined,
Icons.sports_basketball,
Icons.sports_baseball_sharp,
Icons.sports_tennis_rounded,
Icons.people,
];
List<String> sports = [
"Fudbal",
"Kosarka",
"Tenis",
"Stoni tenis",
"Kuglanje"
];
List<int> ints = [0, 1, 2, 3, 4];
List<bool> booles = [false, false, false, false, false];
OverlayEntry? overlayEntry;
var position;
double? y;
double? x;
void findDropdownData() {
RenderBox renderBox =
actionKey!.currentContext!.findRenderObject() as RenderBox;
position = renderBox.localToGlobal(Offset.zero);
y = position!.dy;
x = position!.dx;
}
OverlayEntry _overlayEntryBuilder() {
return OverlayEntry(
builder: (context) {
return Positioned(
// top: position,
left: 16.w,
right: 16.w,
child: Material(
child: dropdownExpanded(),
),
);
},
);
}
Widget buildRows(i) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 15.h),
child: Row(
children: [
SizedBox(
height: 24.h,
width: 24.w,
child: Checkbox(
activeColor: style.purpleMain,
value: booles[i],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4)),
onChanged: (value) {
setState(() {
booles[i] = value!;
booles[i] == true
? picked.add(sports[i])
: picked.remove(sports[i]);
});
},
),
),
SizedBox(
width: 10.w,
),
Text(
sports[i],
style: TextStyle(
color: booles[i] == true ? style.purpleMain : Colors.grey,
),
),
const Spacer(),
Icon(
icons[i],
color: booles[i] == true ? style.purpleMain : Colors.grey,
size: 15,
),
],
),
);
}
Widget dropdown() {
return GestureDetector(
key: actionKey,
onTap: () {
setState(() {
isPressed = !isPressed;
});
if (isPressed == false) {
overlayEntry = _overlayEntryBuilder();
Overlay.of(context)!.insert(overlayEntry!);
}
},
child: Container(
width: double.infinity,
height: 50.h,
decoration: BoxDecoration(
border: Border.all(color: style.e8e8e8),
borderRadius: BorderRadius.circular(8),
),
padding: EdgeInsets.only(left: 16.w, right: 13.w),
child: Row(
children: [
picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
const Spacer(),
const Icon(
Icons.arrow_drop_down,
color: style.bdbdbd,
),
],
),
),
);
}
Widget pickedEmpty() {
return Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(
fontSize: 16.sp,
color: style.bdbdbd,
fontWeight: FontWeight.w400,
),
);
}
Widget pickedNotEmpty() {
List<Widget> list = <Widget>[];
for (var i = 0; i < picked.length; i++) {
list.add(
Padding(
padding: EdgeInsets.only(right: 5.w),
child: Text(
picked[i],
style: TextStyle(
fontSize: 16.sp,
color: style.bdbdbd,
fontWeight: FontWeight.w400,
),
),
),
);
}
return Row(children: list);
}
Widget dropdownExpanded() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: style.purpleMain),
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
isPressed = !isPressed;
});
overlayEntry?.remove();
},
child: Container(
width: double.infinity,
height: 50.h,
padding: EdgeInsets.only(left: 16.w, right: 13.w),
child: Row(
children: [
picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
const Spacer(),
const Icon(
Icons.arrow_drop_up,
color: style.bdbdbd,
),
],
),
),
),
const Divider(
height: 0,
thickness: 1,
color: style.e8e8e8,
indent: 17,
endIndent: 17,
),
Column(
children: [
for (int i in ints) buildRows(i),
],
),
],
),
);
}
Here are results
This is what I want to accomplish
So I just want to move down this expanded dropdown and how to update these booles in the overlay if I don't use overlay it's working as it should but I need to open that dropdown on the top of another content. Thanks for the help.
Use smart_select it is fully customizable and you can achieve the design you want easily using this library.
Updated Answer
Regarding the UI, it is like an Expansions Tile Widget in flutter. You can implement that dropdown with expansions tile and pass list of items in children,
for expand, collapse tile after select each item, you can create a global key and control that in UI.
final GlobalKey<AppExpansionTileState> expansionTile = new GlobalKey();
collapse → expansionTile.currentState.collapse();
ExpansionTile(
title: Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
),
children: <Widget>[
// put items here
],
),
smaple :
Widget customDropDown() => Container(
// color: Colors.white,
padding: const EdgeInsets.all(10),
child: ListTileTheme(
dense: true,
child: ExpansionTile(
title: const Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
),
children: <Widget>[
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.vertical(bottom: Radius.circular(20))),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: const [
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
)
],
),
),
)
],
),
),
);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: Stack(
children: [pageDesign(), customDropDown()],
),
),
),
);
}
fakeWidget(color) => Container(
height: 100,
width: double.infinity,
color: color,
child: const Center(
child: Text("widget1"),
),
);
Widget pageDesign() => Column(
children: [
/* you should control this size in diffrent orientation and for big size
device to handle responsive
*/
const SizedBox(
height: 80,
),
fakeWidget(
Colors.green,
),
fakeWidget(
Colors.yellow,
),
fakeWidget(
Colors.orange,
),
fakeWidget(
Colors.blue,
),
],
);
Related
I'm a beginner in Flutter.
I designed this page:
Instead of repeating the entire Listview.builder. I would like to use two instances of custom Listview.builder with two lists, one list for fruits, and the other for vegetables.
As appeared in the above screen, I tried to display vegetables in the vegetables section through the following:
Listview.builder Widget:
import 'package:flutter/material.dart';
import 'package:grocery_store/models/products_list.dart';
import '../utilities/add_product.dart';
import '../utilities/constants.dart';
class ProductsListView extends StatelessWidget {
final String? productImage;
final String? productName;
final String? productCategory;
final String? productPrice;
const ProductsListView({
Key? key,
this.productImage,
this.productName,
this.productCategory,
this.productPrice,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: fruitsList.length,
itemBuilder: (BuildContext context, int index) {
return ClipRect(
child: Container(
width: 140.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 10,
color: Colors.black,
),
],
),
margin: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 10),
child: Column(
children: [
Image.asset(
fruitsList[index].fruitImage!,
height: 80.0,
width: 90.0,
),
const SizedBox(
height: 15,
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
fruitsList[index].fruitName!,
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
Text(
fruitsList[index].fruitCategory!,
textAlign: TextAlign.left,
style: const TextStyle(
height: 1.5,
color: kDarkGrey,
fontSize: 12.5,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
Text(
fruitsList[index].fruitPrice!,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const AddProduct(),
],
)
],
),
),
),
);
},
);
}
}
Fruits and vegetables lists:
import '../utilities/constants.dart';
class Fruits {
final String? fruitImage;
final String? fruitName;
final String? fruitCategory;
final String? fruitPrice;
Fruits(
{this.fruitImage, this.fruitName, this.fruitCategory, this.fruitPrice});
}
final Fruits bananas = Fruits(
fruitImage: '${kFruitsImagesAsset}bananas.png',
fruitName: 'Bananas',
fruitCategory: 'Organic',
fruitPrice: '\$4.99',
);
final Fruits apples = Fruits(
fruitImage: '${kFruitsImagesAsset}apples.png',
fruitName: 'Apples',
fruitCategory: 'Organic',
fruitPrice: '\$5.00',
);
final Fruits chikku = Fruits(
fruitImage: '${kFruitsImagesAsset}chikku.png',
fruitName: 'Chikku',
fruitCategory: 'Organic',
fruitPrice: '\$9.00',
);
final Fruits peaches = Fruits(
fruitImage: '${kFruitsImagesAsset}peaches.png',
fruitName: 'Peaches',
fruitCategory: 'Organic',
fruitPrice: '\$12.00',
);
List<Fruits> fruitsList = [bananas, apples, chikku, peaches];
class Vegetables {
final String? vegetableImage;
final String? vegetableName;
final String? vegetableCategory;
final String? vegetablePrice;
Vegetables(
{this.vegetableImage,
this.vegetableName,
this.vegetableCategory,
this.vegetablePrice});
}
final Vegetables okra = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}okra.png',
vegetableName: 'Okra',
vegetableCategory: 'Organic',
vegetablePrice: '\$6.99',
);
final Vegetables peas = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}peas.png',
vegetableName: 'Peas',
vegetableCategory: 'Organic',
vegetablePrice: '\$10.50',
);
final Vegetables potatoes = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}potatoes.png',
vegetableName: 'Potatoes',
vegetableCategory: 'Organic',
vegetablePrice: '\$5.99',
);
final Vegetables taro = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}taro.png',
vegetableName: 'Taro',
vegetableCategory: 'Organic',
vegetablePrice: '\$5.50',
);
List<Vegetables> vegetablesList = [okra, peas, potatoes, taro];
Homepage where I want to display the two lists:
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:grocery_store/models/product_cards_column.dart';
import 'package:grocery_store/utilities/constants.dart';
import 'package:grocery_store/utilities/grocery_text_field.dart';
import '../models/products_cards.dart';
import '../models/products_list.dart';
class GroceryPage extends StatelessWidget {
const GroceryPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
var discountPortrait =
MediaQuery.of(context).orientation == Orientation.portrait;
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 1, 0),
child: Row(
children: [
const Text(
'Grocery',
style: kTitleTextStyle,
),
const Spacer(),
ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Image.asset(
'images/apple.jpg',
width: 46.0,
height: 46.0,
fit: BoxFit.cover,
),
),
],
),
),
const SizedBox(height: 10.0),
Row(children: [
GroceryTextField.groceryTextField(
groceryText: 'Search...',
),
const SizedBox(width: 5.0),
Container(
height: 50.0,
width: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18.0),
color: kLightGrey,
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
'images/funnel.svg',
semanticsLabel: 'Funnel',
color: kDarkGrey,
),
),
),
]),
const SizedBox(height: 10.0),
Container(
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: const Color(0xFFE9F9F2),
),
width: double.infinity,
child: Stack(
children: [
Positioned(
bottom: -150,
right: discountPortrait ? -30 : 30,
height: 290,
width: 430,
child: Image.asset(
'${kProductsImagesAsset}lettuce.png',
),
),
Positioned(
top: discountPortrait ? 35 : 15,
left: discountPortrait ? 25 : 100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Get Up To',
style: kGreenTitleStyle.copyWith(
fontSize: discountPortrait ? 20 : 60,
),
),
Text(
'%10 off',
style: kGreenTitleStyle.copyWith(
fontSize: 40.0,
),
),
],
),
),
],
),
),
Column(
children: const [
ProductCardsRow(
groceryType: 'Fruits',
),
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
),
),
],
),
Column(
children: const [
ProductCardsRow(
groceryType: 'Vegetables',
),
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
),
),
],
),
],
),
),
),
),
);
}
}
Hope someone can help
You can set an other variable in constructor and call it list and pass your Vegetables and Fruits to it like this:
class ProductsListView extends StatelessWidget {
final List list;
const ProductsListView({
Key? key,
required this.list,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return ClipRect(
child: Container(
width: 140.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 10,
color: Colors.black,
),
],
),
margin: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 10),
child: Column(
children: [
Image.asset(
list is List<Fruits> ? (list[index] as Fruits).fruitImage! : (list[index] as Vegetables).vegetableImage!,
height: 80.0,
width: 90.0,
),
const SizedBox(
height: 15,
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
list is List<Fruits> ? (list[index] as Fruits).fruitName! : (list[index] as Vegetables).vegetableName!,
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
Text(
list is List<Fruits> ? (list[index] as Fruits).fruitCategory! : (list[index] as Vegetables).vegetableCategory!
textAlign: TextAlign.left,
style: const TextStyle(
height: 1.5,
color: kDarkGrey,
fontSize: 12.5,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
Text(
list is List<Fruits> ? (list[index] as Fruits).fruitPrice! : (list[index] as Vegetables).vegetablePrice!,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const AddProduct(),
],
)
],
),
),
),
);
},
);
}
}
and use it like this:
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
list: vegetablesList,
),
),
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
list: fruitsList,
),
),
Yeah it is pretty straightfroward, just click on the listview.builder method in your project and then click on FLutter Outline on the right hand side of the Android Studio IDE window, like this :
Once you have done that the ListView.Builder will be visible in this tree of widgets. What you need to do is to right click on the widget you want to extract and then click on extract method.
you'll get a dialog asking for the name of the newly created widget :
and a new widget will be created at the bottom of your file.
Just change the parameters for both the listview.builders and it'll look something like this :
Widget build(BuildContext context) {
return CommonList(typeList: fruitslist); // use this to change the list
}
And in the newly created widget you'd need to do the same:
class CommonList extends StatelessWidget {
final List typeList; //add a list parameter
const CommonList({
Key? key, required this.typeList, //request that list parameter
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: typeList.length, // change the list type
itemBuilder: (BuildContext context, int index) {
return ClipRect(
child: Container(
width: 140.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 10,
color: Colors.black,
),
],
),
margin: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 10),
child: Column(
children: [
Image.asset(
typeList[index].fruitImage!, //update list to use it everywhere
height: 80.0,
width: 90.0,
),
const SizedBox(
height: 15,
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
typeList[index].fruitName!, //like here
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
Text(
typeList[index].fruitCategory!, //here
textAlign: TextAlign.left,
style: const TextStyle(
height: 1.5,
color: kDarkGrey,
fontSize: 12.5,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
Text(
typeList[index].fruitPrice!, //and here again
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const AddProduct(),
],
)
],
),
),
),
);
},
);
}
i am trying to update the state of the animated switcher in the middle area. i am trying to do this using a setstate in the lower area. but it does not work.
the first thing i did is to create a variable with a boolean data type in the home class.
then i passed the variable to both the middle area and the lower area
the idea was that if the same variable is passed to the class whose state i am trying to update, and the class with the set state, it would work. but it seems i am wrong. i would appreciate some assistance.
the boolean variable i am trying to make work is the _rep variable
This is the Home widget
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
late AnimationController _animationController;
late AnimationController _controller;
late Animation<Offset> _animation;
late Animation<Offset> _anime;
bool _rep = true;
#override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2)
);
_animation = Tween<Offset>(
begin:Offset (0.0, 0.0),
end: Offset (0.0,3.0),
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.easeIn));
_anime = Tween<Offset>(
begin:Offset (0.0, 0.0),
end: Offset (0.0,-0.55),
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.easeIn));
super.initState();
}
#override
void dispose() {
_animationController.dispose();
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
child: Padding(
padding: EdgeInsets.only(top: 3.h),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TopIcon(icons: Icons.arrow_back, color:Colors.grey.shade300 ,),
SizedBox(
height: 13.h,
width: 13.w,
child: Image.asset('assets/images/download.png')
),
TopIcon(icons: Icons.shopping_bag_outlined, color: Colors.grey.shade300,),
],
),
SizedBox(
height: 3.h,
),
Text('Frappuccino',
style: TextStyle(
fontSize: 27.sp,
fontWeight: FontWeight.bold
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('White Chocolate',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey.shade400
),
),
),
MiddleArea(
controller: _animationController,
animation: _animation,
rep: _rep,
),
LowerArea(controller: _animationController, anime: _anime, rep = _rep),
],
),
),
),
);
}
}
This is the middle area
class MiddleArea extends StatefulWidget {
MiddleArea({Key? key, required this.controller, required this.animation, required this.rep}) : super(key: key);
AnimationController controller;
Animation<Offset> animation;
final bool rep;
#override
State<MiddleArea> createState() => _MiddleAreaState();
}
class _MiddleAreaState extends State<MiddleArea> {
bool _flag = true;
bool _favourite = true;
#override
Widget build(BuildContext context) {
print(widget.rep);
return SizedBox(
height: 52.h,
child: Stack(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 135.0),
child: Text('STARBUCKS',
style: TextStyle(
fontFamily: 'Typette',
color: Colors.brown.shade200,
fontSize: 30.sp,
fontWeight: FontWeight.w400
),
),
),
Text('STARBUCKS',
style: TextStyle(
fontFamily: 'Typette',
color: Colors.brown.shade100,
fontSize: 30.sp,
fontWeight: FontWeight.w400
),
),
Text('STARBUCKS',
style: TextStyle(
fontFamily: 'Typette',
color: Colors.brown.shade50,
fontSize: 30.sp,
fontWeight: FontWeight.w400
),
),
],
),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
SizeAndFave(text: 'Preference'),
SizeAndFave(text: 'Fave!')
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: (){
setState(() {
_flag = !_flag;
});
},
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
transitionBuilder: (Widget child, Animation<double> animation){
return FadeTransition(opacity: animation, child: child,);
},
child: widget.rep == true?Padding(
padding: const EdgeInsets.all(14.0),
key: const Key('1'),
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
border: Border.all(
color: Colors.brown.shade300,
width: 3
),
borderRadius: BorderRadius.circular(10)
),
child: const Center(
child: Icon(
Icons.coffee_outlined,
size: 20,
),
)
),
):null,
)
),
GestureDetector(
onTap: (){
setState(() {
_favourite = !_favourite;
});
},
child: _favourite? TopIcon(icons: Icons.favorite_border, color: Colors.brown.shade300)
:TopIcon(
icons: Icons.favorite, color: Colors.brown.shade300)
)
],
)
],
),
AnimatedSwitcher(
duration: Duration(seconds: 1),
transitionBuilder: (Widget child, Animation<double> animation) {
return FadeTransition( opacity: animation,
child: child);
},
child: _flag == true ? Center(
key: const Key('1'),
child: SlideTransition(
position: widget.animation,
child: SizedBox(
height: 80.h,
width: 80.w,
child: Image.asset('assets/images/starcup.png'),
),
),
):Center(
key: const Key('2'),
child: SlideTransition(
position: widget.animation,
child: SizedBox(
height: 80.h,
width: 80.w,
child: Image.asset('assets/images/greeen.png'),
),
),
),
),
Positioned(
child:
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(top: 30.h),
child: TopIcon(
icons: Icons.car_crash_outlined, color: Colors.brown.shade300),
),
)),
const Positioned(
child:
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: EdgeInsets.only(top: 330.0, left: 14),
child: Text('\$ 5.99',
style: TextStyle(
fontSize: 27,
fontWeight: FontWeight.bold
),
),
),
))
],
),
);
}
}
and lastly, the lower area
class LowerArea extends StatefulWidget {
final AnimationController controller;
final Animation<Offset> anime;
bool rep;
LowerArea({Key? key, required this.controller, required this.anime, required this.rep}) : super(key: key);
#override
State<LowerArea> createState() => _LowerAreaState();
}
class _LowerAreaState extends State<LowerArea> {
bool _bigger = true;
bool _fade = true;
void move(){
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: EdgeInsets.all(1.h),
child: const Text('Tall Frappuccino',
style: TextStyle(
fontWeight: FontWeight.w500
),
),
),
Padding(
padding: EdgeInsets.only(right: 5.h),
child: const Text('Swipe Down',
style: TextStyle(
fontWeight: FontWeight.w500
),
),
),
Padding(
padding: EdgeInsets.all(2.h),
child: const Text('Pickup',
style: TextStyle(
fontWeight: FontWeight.w500
),
),
)
],
),
),
SlideTransition(
position: widget.anime,
child: AnimatedContainer(
// height: 11.h,
width: _bigger ? 35.h: 80.h,
duration: const Duration(milliseconds: 500),
child: Stack(
fit: StackFit.loose,
children: [
Center(child: Image.asset('assets/images/baggie.png')),
Center(
child: Padding(
padding: EdgeInsets.only(bottom: 4.h),
child: GestureDetector(
onTap: (){
widget.controller.forward();
setState(() {
_bigger = !_bigger;
_fade = !_fade;
widget.rep = !widget.rep;
print('this is fade $_fade ');
});
},
child: AnimatedSwitcher(
duration: Duration(milliseconds: 300),
transitionBuilder: (Widget child, Animation<double> animation){
return FadeTransition(opacity: animation, child: child,);
},
child: _fade? Container(
key: Key('1'),
height: 8.h,
width: 7.w,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(15)
),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(0.3.h),
child: Icon(
Icons.lock_outline,
color: Colors.white54,
size: 2.5.h,
),
),
Icon(
Icons.arrow_drop_down,
color: Colors.white12,
size: 3.h,
),
],
),
):null,
),
),
),
)
],
),
),
)
],
);
}
use provider pacakges https://pub.dev/packages/provider
Create a class that inherits the functions of ChangeNotifyer to create a flag to control and create a setter.
provider class
class StateController extends ChangeNotifier{
bool _req = false;
bool get req => _req; //getter
setReqValue(){
_req = !_req;
notifyListener();
}
}
Declare the provider class in the main function. You can change the location of the declaration according to Wiget tree, but first declare it in main
Change main.dart
void main(){
runApp(
Multiprovider(
providers: [
ChangeNotifierProvider(create: (_) => StateController()),
],
child: HomePage(),
)
);
}
The UI is updated by notifyListener().
change UI
child: context.watch<StateController>().req == true ? Padding(
padding: const EdgeInsets.all(14.0),
key: const Key('1'),
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
border: Border.all(
color: Colors.brown.shade300,
width: 3
),
borderRadius: BorderRadius.circular(10)
),
child: const Center(
child: Icon(
Icons.coffee_outlined,
size: 20,
),
)
),
):null,
Change State
onTap: (){
widget.controller.forward();
setState(() {
_bigger = !_bigger;
_fade = !_fade;
context.read<StateController>().setReqValue();
print('this is fade $_fade ');
});
},
I am too lazy to try understand your code. But if you want to update state of the page after you pop from Navigation to it.
In page you want to update
Navigation.push(context, /* Page that will change something */)
// Future will trigger then you return to this page.
.then((_) => setState(() {}))
I was trying to make this page but this design in last is not shifting to the last bottom, I've tried padding but this doesn't look good and also I've tried positioned widget but it is showing some error please someone tell how I can shift that design to bottom last
this is my git repo: https://github.com/cryptic-exe/Otp_verfication
this is my code:
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String dropdownValue = 'English';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Column(
children: [
Icon(
Icons.photo_outlined,
size: 100.0,
),
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Please Select Your Language',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Text(
'You can change the language \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t at any time',
style: TextStyle(
fontWeight: FontWeight.w300, fontSize: 15.0),
),
),
Padding(
padding: const EdgeInsets.only(top: 9.0),
child: Container(
width: 200,
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
border: Border.all(),
),
child: DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_drop_down_outlined),
isExpanded: true,
iconSize: 30,
elevation: 16,
style: const TextStyle(color: Colors.black),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>[
'English',
'Hindi',
'French',
'Spanish',
'Russian',
'Arabic'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(
fontSize: 20,
letterSpacing: 0.9,
fontWeight: FontWeight.w300),
),
);
}).toList(),
),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
width: 200,
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: Colors.deepPurple,
border: Border.all(),
),
child: TextButton(
onPressed: () {},
child: Text(
'NEXT',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w400,
letterSpacing: 0.9),
),
),
),
),
],
),
),
Stack(
children: [
Positioned.fill(
child: Container(
width: 393,
child: Image(
image: AssetImage('Images/design2.png'),
fit: BoxFit.fill,
),
),
),
Positioned(
child: Container(
width: 393,
child: Image(
image: AssetImage('Images/design1.png'),
colorBlendMode: BlendMode.overlay,
fit: BoxFit.fill,
),
),
),
],
),
],
),
);
}
}
you can use bottomSheet to place your image.
Add the below code inside your Scaffold
bottomSheet: Container(
width: double.infinity,
child: Image(
image: AssetImage('Images/design1.png'),
colorBlendMode: BlendMode.overlay,
fit: BoxFit.fill,
),
),
You can also use a spacer to push the content down
https://api.flutter.dev/flutter/widgets/Spacer-class.html
On mobile so I cannot give snippet
So this is the main code where I fetch the data from json and update my UI.
I have placed" //Area of Interest " comments where the code related to the problem lies.
class MainScreen extends StatefulWidget {
final curLocdata;
MainScreen({this.curLocdata});
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
Weather weather = Weather();
var cityName;
int temp;
int temp_min;
int temp_max;
Icon weatherIcon;
//Area of Interest 1
RotateAnimatedTextKit textSum;//created a widget of RotateAnimatedTextKit library.
String st;
//Area of Interest 2
#override
void initState() {
// TODO: implement initState
super.initState();
updateUI(widget.curLocdata);//calling update function to rebuild my UI state with new data
}
void updateUI(data) {
setState(() {
if (data == null) {
temp = 0;
cityName = 'Error';
weatherIcon = Icon(Icons.error);
return;
}
cityName = data['name'];
temp = data['main']['temp'].toInt();
temp_min = data['main']['temp_min'].toInt();
temp_max = data['main']['temp_max'].toInt();
var condition = data['weather'][0]['id'];
weatherIcon = weather.getIcon(condition);
textSum = weather.getMessage(temp);//Area of Interest 3
st = weather.subtext(condition);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: SafeArea(
child: Column(
children: <Widget>[
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () async {
updateUI(await Network().getData());
},
child: Icon(
FontAwesomeIcons.locationArrow,
),
),
SizedBox(
width: 180.0,
child: TextLiquidFill(
waveDuration: Duration(seconds: 3),
loadDuration: Duration(seconds: 10),
text: 'OpenWeather',
waveColor: Colors.red,
boxBackgroundColor: Color(0xFF1B1B1D),
textStyle: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
fontFamily: 'Source Sans Pro',
),
boxHeight: 50.0,
),
),
FlatButton(
onPressed: () async {
String SName = await Navigator.push(context,
MaterialPageRoute(builder: (context) {
return Search();
}));
if (SName != null) {
updateUI(await Network().getDataName(
SName));
}
},
child: Icon(
Icons.add,
color: Colors.white,
size: 40,
),
),
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(50, 50, 50, 0),
child: Row(
children: <Widget>[
SizedBox(
// margin: EdgeInsets.fromLTRB(0, 50, 260, 0),
child: TypewriterAnimatedTextKit(
totalRepeatCount: 200,
isRepeatingAnimation: true,
speed: Duration(milliseconds: 700),
text: [cityName,],
textAlign: TextAlign.left,
textStyle: TextStyle(
fontSize: 20,
fontFamily: 'Source Sans Pro',
),
),
),
],
)),
Expanded(
flex: 9,
child: Container(
margin: EdgeInsets.fromLTRB(50, 30, 50, 80),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
//mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 2,
child: Padding(
padding: EdgeInsets.only(left: 20),
child: Text(
'$temp°',
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: 'Source Sans Pro',
),
),
),
),
Expanded(
flex: 2,
child: Padding(
padding: EdgeInsets.only(left: 20),
child: Text(
st,
style: TextStyle(
fontSize: 30,
fontFamily: 'Source Sans Pro',
color: Colors.grey[500]),
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 0, 50),
child: Container(
child: textSum,//Used this textSum to show my animated text. problem
Area of Interest 4
),
),
Expanded(
child: SizedBox(
//width: double.infinity,
//height: 100,
child: Divider(
color: Colors.red,
),
),
),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.fromLTRB(20, 0, 0, 38),
child: Text(
'$temp_min° - $temp_max°',
style: TextStyle(
fontSize: 20,
color: Colors.grey[500],
fontFamily: 'Source Sans Pro',
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.fromLTRB(20, 0, 0, 20),
//padding: const EdgeInsets.all(8.0),
child: AvatarGlow(
endRadius: 30.0, //required
child: Material(
//required
elevation: 0.0,
shape: CircleBorder(),
child: CircleAvatar(
//backgroundColor: Colors.grey[100],
child: weatherIcon
// radius: 40.0,
//shape: BoxShape.circle
),
),
),
),
)
],
)`enter code here`
],
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Color(0xFF0C0C0C),
),
),
),
Now the weather.dart file from where I am returning RotateAnimatedTextKit widget depending upon the condition
class Weather{
//This return RotateAnimatedTextKit which is then held by textSum and is put as a child inside a container in MainScreen
RotateAnimatedTextKit getMessage(int temp) {
if (temp > 25) {
return RotateAnimatedTextKit(
isRepeatingAnimation: true,
totalRepeatCount: 200,
transitionHeight: 40,
text: ['It\'s 🍦','time and','drink plenty','of water'],
textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
textAlign: TextAlign.start,
alignment: AlignmentDirectional.topStart // or Alignment.topLeft
);
} else if (temp > 20) {
return RotateAnimatedTextKit(
isRepeatingAnimation: true,
totalRepeatCount: 200,
transitionHeight: 50,
text: ['Time for','shorts','👕','but keep','some warm','clothes handy'],
textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
textAlign: TextAlign.start,
alignment: AlignmentDirectional.bottomStart// or Alignment.topLeft
);
} else if (temp < 10) {
return RotateAnimatedTextKit(
isRepeatingAnimation: true,
totalRepeatCount: 200,
transitionHeight: 50,
text: ['You\'ll need','a 🧣','and','a 🧤','and a hot', 'soup and turkey'],
textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
textAlign: TextAlign.start,
alignment: AlignmentDirectional.bottomStart // or Alignment.topLeft
);
} else {
return RotateAnimatedTextKit(
isRepeatingAnimation: true,
transitionHeight: 50,
totalRepeatCount: 200,
text: ['Bring a','🧥','just in case','and also avoid', 'cold breeze','and cold drinks'],
textStyle: TextStyle(fontSize: 30.0, fontFamily: "Source Sans Pro", color: Colors.red),
textAlign: TextAlign.start,
alignment: AlignmentDirectional.bottomStart // or Alignment.topLeft
);
}
}
The thing is that the UI doesn't get updated even when the conditions are different. So any Solutions to why the widget tree is not updating? But it runs only the default text. Also, the cityName which is under the TextLiquidFill doesn't get updated.
Short answer:
Use Keys
Example:
import 'package:animated_text_kit/animated_text_kit.dart';
import 'package:flutter/material.dart';
class MyAnimatedText extends StatefulWidget {
const MyAnimatedText({Key? key}) : super(key: key);
#override
State<MyAnimatedText> createState() => _MyAnimatedTextState();
}
class _MyAnimatedTextState extends State<MyAnimatedText> {
bool isDarkMode = true;
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: isDarkMode ? Colors.grey[850] : Colors.amber[300]),
child: Column(
children: [
Container(
alignment: Alignment.topRight,
child: IconButton(
onPressed: () {
setState(() {
isDarkMode = !isDarkMode;
});
},
icon: Icon(isDarkMode ? Icons.light_mode : Icons.dark_mode))),
Padding(
padding: const EdgeInsets.all(15.0),
child: AnimatedTextKit(
key: ValueKey<bool>(isDarkMode),
animatedTexts: [
TypewriterAnimatedText(
isDarkMode ? 'Have a nice evening ;)' : 'Have a nice day :)',
cursor: isDarkMode ?'>':'<',
textStyle: TextStyle(
fontSize: 38,
color: isDarkMode ? Colors.amber[300] : Colors.grey[850]),
speed: const Duration(milliseconds: 100),
),
],
),
),
],
),
);
}
}
Result:
Background Information
I faced the same problem, when I tried to implement a dark / light change. The background color was defined in an other widget and changed, the font color was defined in the TypewriterAnimatedText Widget and only changed in the second loop. The color was not changing in the runnig animation.
Solution: use Keys
The Animation does not change beacause Flutter tries to keep the state of an StatefulWidget and the AnimatedTextKit is a Stateful Widget.
To force a rebuild you can use a Key.
a nice article can be found here: How to force a Widget to redraw in Flutter?
You can use WidgetsBinding.instance.addPostFrameCallback
For detail, you can reference https://www.didierboelens.com/faq/week2/
code snippet
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
updateUI(widget.curLocdata);
});
}
Hi I have designed a screen in flutter. I have AlertDialog on which I want to close the dialog and screen on pressing. Right now AlertDialog dismiss on press but screen is not closing.
Does anyone know how to do this ?
class ForgotPasswordScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return ForgotPasswordScreenState();
}
}
class ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
var emailController = new TextEditingController();
var authHandler = new Auth();
bool isLoading = false;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
children: <Widget>[
new Expanded(
child: isLoading
? Center(child: CircularProgressIndicator())
: new Container()),
],
),
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
"EMAIL",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.redAccent,
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin:
const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.redAccent,
width: 0.5,
style: BorderStyle.solid),
),
),
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField(
controller: emailController,
textAlign: TextAlign.left,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'PLEASE ENTER YOUR EMAIL',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
),
new Container(
width: MediaQuery.of(context).size.width,
margin:
const EdgeInsets.only(left: 30.0, right: 30.0, top: 20.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: Colors.redAccent,
onPressed: () {
setState(() {
isLoading = true;
});
authHandler
.sendPasswordResetEmail(emailController.text)
.then((void nothing) {
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
content: new Text(
"Password reset email has been sent."),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("OK"),
onPressed: () {
Navigator.pop(context);
},
),
],
);
},
);
setState(() {
isLoading = false;
});
}).catchError((e) => print(e));
},
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
"FORGOT PASSWORD",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
],
)));
}
}
Ideally, you'll want to call pop more than once. One for the modal, another for the actual route.
There are a few ways to achieve this. But ideally you'll want to await the close of the dialog before triggering another close:
foo() async {
await showDialog(
context: context,
builder: (context) => AlertDialog(
actions: [
new FlatButton(
child: new Text("OK"),
onPressed: () => Navigator.pop(context),
),
],
),
);
Navigator.pop(context);
}
This way, both the route and the modal can handle their close however they like.
This is how i did with mine
bool _logout = false;
and then at the start of build Widget
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
_onBackPressed(context);
return _logout;
},
child: Container(),
);
}
and the method _onBackPressed returns a custom dialog Class like so
void _onBackPressed(BuildContext c) async {
await showDialog(
barrierColor: CustomColors.darkGrey.withOpacity(0.8),
barrierDismissible: true,
context: context,
builder: (BuildContext context) {
return CustomDialogBox(
title: 'Logout',
description: 'Are you sure you want to logout?',
rightButtonText: 'Yes',
onPClick: () {
_logout = true;
if (_logout == true) {
Get.back();
}
},
onNClick: () {
_logout = false;
Get.back();
},
);
});
if (_logout == true) {
Get.back();
}
}
and my custom Dialog class is here
class CustomDialogBox extends StatefulWidget {
final String? title, description, leftButtonText, rightButtonText;
final VoidCallback? onPClick, onNClick;
final Image? image;
const CustomDialogBox({
Key? key,
this.title,
this.description,
this.leftButtonText,
this.rightButtonText,
this.image,
this.onPClick,
this.onNClick,
}) : super(key: key);
#override
_CustomDialogBoxState createState() =>
// ignore: no_logic_in_create_state
_CustomDialogBoxState(onPClick!, onNClick!);
}
class _CustomDialogBoxState extends State<CustomDialogBox> {
final VoidCallback onPClick, onNClick;
_CustomDialogBoxState(this.onPClick, this.onNClick);
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Dimensions.BORDER_RADIUS_4),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: Container(
//height: 200,
padding: const EdgeInsets.only(
left: 10,
right: 0,
bottom: 10,
),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: CustomColors.darkGrey,
offset: const Offset(0, 30),
blurRadius: 20,
),
]),
child: Wrap(children: <Widget>[
dialogBody(context),
]),
),
);
}
Widget dialogBody(context) {
return Column(children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Image.asset(
Images.LOGO,
height: MediaQuery.of(context).size.height * 0.035,
),
IconButton(
//padding: const EdgeInsets.all(0),
onPressed: () {
Get.back();
},
icon: const CircleAvatar(
radius: 12.5,
child: Icon(
Icons.close,
color: Colors.white,
),
backgroundColor: Colors.red,
),
),
]),
Padding(
padding: const EdgeInsets.only(
right: 10,
),
child: Column(children: [
//----//
customText(
text: widget.title ?? '',
fontFamily: 'black',
fontSize: 16,
),
//----//
const Space(0, 0.01),
//----//
customText(
text: widget.description ?? '',
fontSize: 14,
),
]),
),
//----//
const Space(0, 0.03),
//----//
Padding(
padding: const EdgeInsets.only(
right: 10,
),
child:
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
//----//
raisedButton(
text: widget.leftButtonText ?? 'Cancel',
fontFamily: 'roman',
height: 35,
width: 105,
buttonColor: CustomColors.red,
onClick: () {
return onNClick();
},
context: context,
),
//----//
raisedButton(
text: widget.rightButtonText ?? 'Okay',
fontFamily: 'roman',
height: 35,
width: 105,
buttonColor: CustomColors.green,
onClick: () {
return onPClick();
},
context: context,
),
//----//
]),
),
]);
}
}
the buttons and texts are custom so feel free to change them. and where you see Get.back(); is GetX code.. you can replace with Navigator.of(context).pop();
try this
showPop() async {
await showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
actions: [
new FlatButton(
child: new Text("Close"),
onPressed: () => Navigator.pop(context),
),
],
),
);
}