Updating State of StatefulWidget from other StatefulWidget in Flutter? - android

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(() {}))

Related

How to remove extra space below a TabBarView inside the body SliverToBoxAdapter in NestedScrollView?

The space between tab bar view and bottom navigation bar is the extra space that I want to remove.
in the image, you can see the space that shouldn't be there
class Tab_Bar2 extends StatefulWidget {
const Tab_Bar2({Key? key}) : super(key: key);
#override
_Tab_Bar2State createState() => _Tab_Bar2State();
}
class _Tab_Bar2State extends State<Tab_Bar2> with SingleTickerProviderStateMixin {
final bodyGlobalKey = GlobalKey();
final List<Widget> myTabs = [
Text(..),
Text(..),
Text(..),
Text(..),
Text(..),
Text(..),
];
late TabController _tabController;
late ScrollController _scrollController;
#override
void initState() {
_scrollController = ScrollController();
_tabController = TabController(length: 6, vsync: this);
super.initState();
}
#override
void dispose() {
_tabController.dispose();
_scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Dashboard"),
centerTitle: true,
backgroundColor: const Color(0xffFFC36A),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications),
),
]),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Color(0xffFFC36A),
),
child: Padding(
padding: EdgeInsets.only(top: 20.0, left: 60),
child: Text(
'Drawer',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20),
),
),
),
ListTile(
title: const Text('Log Out'),
onTap: () {
},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, value) {
return [
SliverToBoxAdapter(child: Column(
children: [img1(), grid(), rsp(), LiveChart()],
),),
SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.symmetric(horizontal: 15,vertical: 15),
child: Text('Latest',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
fontFamily: 'railway',
color: Theme_Data.font_color,
),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 3.5),
padding: EdgeInsets.symmetric(horizontal: 2.5,vertical: 2.5),
height: 35,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade200),
borderRadius: BorderRadius.all(
Radius.circular(25),
),
),
child: TabBar(
controller: _tabController,
labelPadding: EdgeInsets.symmetric(horizontal: 2.0, vertical: 5),
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(50), // Creates border
color: Theme_Data.th_light_color),
tabs: myTabs,
),
),
],
),
),
];
},
body: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.white
),
child: TabBarView(
controller: _tabController,
children: <Widget>[
SalesTable(),
QuotationsTable(),
PurchasesTable(),
TransfersTable(),
ConsumersTable(),
SuppliersTable(),
],
),
),
),
),
);
}
}
in above code i think there might be the issues between the usage of SviverToBoxAdapter what widget should i use instead to achieve the required design

Can't solve problem with FloatingActionButton

I want the dialog to open when a button is clicked, but an error occurs due to BLoC. Previously, there was such an error with the class itself, but I successfully solved it, and in this case, the complexity already arises. I've already tried a couple of options but couldn't solve it. I tried to make the event in onPressed as a separate widget, and the same error did not work either.
home_page
class HomePage extends StatelessWidget {
final todoRepository = TodoRepository();
#override
Widget build(BuildContext context) {
// final TodoBloc todoBloc = context.read<TodoBloc>();
return BlocProvider<TodoBloc>(
create: (context) => TodoBloc(todoRepository),
child: Scaffold(
appBar: AppBar(
title: const Text('Flutter Todos'),
),
// floatingActionButton: FloatingActionButton(
// onPressed: () {
// // _addTodo(context);
// final newTodo = Todo(description: 'Todo 1');
// BlocProvider.of<TodoBloc>(context).add(CreateTodos(newTodo));
// },
// child: const Icon(Icons.add),
// ),
body: SingleChildScrollView(
child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
// ActionButton(),
TodoList(),
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add, size: 32, color: Colors.black),
onPressed: () {
// showAddTodoSheet(context);
// showAddTodoSheet(BuildContext context) {
final TodoBloc todoBloc = context.read<TodoBloc>();
final _todoDescriptionFromController = TextEditingController();
showModalBottomSheet(
context: context,
builder: (builder) {
return BlocBuilder<TodoBloc, TodoState>(
builder: (context, state) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
color: Colors.transparent,
child: Container(
height: 230,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0))),
child: Padding(
padding: const EdgeInsets.only(
left: 15, top: 25.0, right: 15, bottom: 30),
child: ListView(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextFormField(
controller:
_todoDescriptionFromController,
textInputAction:
TextInputAction.newline,
maxLines: 4,
style: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.w400),
autofocus: true,
decoration: const InputDecoration(
hintText: 'I have to...',
labelText: 'New Todo',
labelStyle: TextStyle(
color: Colors.indigoAccent,
fontWeight: FontWeight.w500)),
validator: (value) {
if (value!.isEmpty) {
return 'Empty description!';
}
return value.contains('')
? 'Do not use the # char.'
: null;
},
),
),
Padding(
padding: const EdgeInsets.only(
left: 5, top: 15),
child: CircleAvatar(
backgroundColor: Colors.indigoAccent,
radius: 18,
child: IconButton(
icon: const Icon(
Icons.save,
size: 22,
color: Colors.white,
),
onPressed: () {
final newTodo = Todo(
description:
_todoDescriptionFromController
.value.text);
if (newTodo
.description.isNotEmpty) {
todoBloc
.add(CreateTodos(newTodo));
Navigator.pop(context);
}
},
),
),
)
],
),
],
),
),
),
),
);
});
});
},
),
));
}
You have to use MultiBlocProvider before MaterialApp.
just do like that
#override
Widget build(BuildContext context) => MultiBlocProvider(
providers: [
BlocProvider(create: (_) => TodoBloc()),
],
child: MaterialApp()
);

How i can create dropdown like this in flutter

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,
),
],
);

Why is my widget not taking up all the space in the bottomNavigationBar?

I'm new to Flutter and I just start coding the UI of a chat app so I figure out that my widget doesn't take all the space of the bottom navigation bar like the photo shows : shows
This is my camera widget code :
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class Camera extends StatefulWidget {
#override
_CameraState createState() => _CameraState();
}
class _CameraState extends State<Camera> {
File _image;
final imagePicker = ImagePicker();
Future getImage() async {
final image = await imagePicker.getImage(source: ImageSource.camera);
setState(() {
_image = File(image.path);
});
}
#override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 80.0,
height: 80.0,
child: FloatingActionButton(
backgroundColor: Colors.white,
onPressed: getImage,
child: Icon(
Icons.camera_alt_rounded,
color: Colors.lightBlue[600],
size: 35.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
),
),
],
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.lightBlue[50],
boxShadow: [
BoxShadow(color: Colors.grey[100], spreadRadius: 3),
],
),
height: 50,
),
);
}
}
and this is the chat screen code :
import 'dart:io';
import 'package:mychat/services/auth.dart';
import 'package:flutter/material.dart';
import 'package:mychat/chat/chat.dart';
import 'package:mychat/widgets/Med_form.dart';
import 'package:mychat/widgets/bottomButtons.dart';
import 'package:mychat/widgets/camera.dart';
import 'package:mychat/widgets/incrementAndDecrement.dart';
import 'package:mychat/widgets/yesOrno.dart';
class ChatScreen extends StatefulWidget {
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
File _image;
final AuthService _auth = AuthService();
List<String> messages = [
'fizikefgzerpgr',
'fioezhfejzifojef',
'fvfzerfergnyolnkyokjy',
'rgop^l^lmf^prlgprgprp'
];
List<String> responses = [
'fizikefgzerpgr',
'fezfzefzefezff',
'ofpkoepzkfopkzef',
'fjeziofjiozejfozejf'
];
//final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(90),
child: AppBar(
title: new Text(
"لاباس ⸮",
style: TextStyle(
color: Colors.black,
fontSize: 30.0,
fontWeight: FontWeight.bold),
),
centerTitle: true,
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomRight,
colors: [Colors.blueGrey[300], Colors.grey[50]])),
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_forward_ios_outlined,
color: Colors.black,
),
onPressed: () async {
await _auth.signOut();
})
],
elevation: 0.0,
),
),
body: Chat_page(messages: messages, responses: responses),
bottomNavigationBar: Camera(),
),
));
}
}
and this is the code of the messages:
import 'package:bubble/bubble.dart';
import 'package:flutter/material.dart';
class Chat_page extends StatefulWidget {
List<String> messages;
List<String> responses;
Chat_page({this.messages, this.responses});
#override
_Chat_pageState createState() => _Chat_pageState();
}
class _Chat_pageState extends State<Chat_page> {
String message;
int data;
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
/* Container(
padding: EdgeInsets.only(top: 15, bottom: 10),
child: Text(
"Today, 10",
style: TextStyle(fontSize: 20, color: Colors.white),
),
), */
Flexible(
child: widget.messages.length > 0
? ListView.builder(
reverse: true,
shrinkWrap: true,
itemCount: widget.messages.length,
itemBuilder: (context, index) => Column(
children: [
widget.messages.length > 0
? chat(widget.messages[index].toString(), 1)
: Container(),
widget.responses.length > 0
? chat(widget.responses[index].toString(), 0)
: Container(),
],
))
: Container(),
),
SizedBox(
height: 20,
),
SizedBox(
height: 15.0,
)
],
));
}
}
Widget chat(String message, int data) {
return Container(
padding: EdgeInsets.only(left: 20, right: 20),
child: Row(
mainAxisAlignment:
data == 1 ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
data == 0
? Container(
height: 60,
width: 60,
child: CircleAvatar(
child: Icon(Icons.account_circle),
),
)
: Container(),
Padding(
padding: EdgeInsets.all(10.0),
child: Bubble(
radius: Radius.circular(15.0),
color: data == 0 ? Color(0xFFf7ede2) : Color(0xFFf7ede2),
elevation: 0.0,
child: Padding(
padding: EdgeInsets.all(2.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
width: 10.0,
),
Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: 200),
child: Text(
message,
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
),
))
],
),
)),
),
data == 1
? Container(
height: 60,
width: 60,
child: CircleAvatar(
child: Icon(Icons.account_circle),
),
)
: Container(),
],
),
);
}
so how can I fix this the make my camera widget take the full space
try to change
SizedBox(
height: 100,
child: Container(
to
Container(
height: 100,
width:double.infinty,

Screen is not closing on click on press of alert dialog in flutter

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),
),
],
),
);
}

Categories

Resources