I am developing a taxi App
i am able to set the current location to my current location, how to i set it for user to select their own location.at the moment it only picks up my location as current location and i am unable to select new pickup location.
Below is my search screen code
I am developing a taxi App
i am able to set the current location to my current location, how to i set it for user to select their own location.at the moment it only picks up my location as current location and i am unable to select new pickup location.
Below is my search screen code
I am developing a taxi App
i am able to set the current location to my current location, how to i set it for user to select their own location.at the moment it only picks up my location as current location and i am unable to select new pickup location.
Below is my search screen code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:qube_rider_app/AllWidget/progressBox.dart';
import 'package:qube_rider_app/Assistants/requestAssistant.dart';
import 'package:qube_rider_app/DataHandler/appData.dart';
import 'package:qube_rider_app/Models/address.dart';
import 'package:qube_rider_app/Models/placePredictions.dart';
import 'package:qube_rider_app/userMap.dart';
class SearchScreen extends StatefulWidget {
#override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen>
{
TextEditingController pickUpTextEditingController = TextEditingController();
TextEditingController dropOffTextEditingController = TextEditingController();
List<PlacePredictions> placePredictionList = [];
#override
Widget build(BuildContext context)
{
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: [
new Container(
height: 190.0,
decoration: BoxDecoration(
image: new DecorationImage(image: new AssetImage("images/mapbg2.jpg"), fit: BoxFit.cover,),
color: Colors.white,
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 6.0,
spreadRadius: 0.5,
offset: Offset(0.7, 0.7),
),
],
),
child: Padding(
padding: EdgeInsets.only(left: 25.0, top: 30.0, right: 25.0, bottom: 2.0),
child: Column(
children: [
SizedBox(height: 5.0),
Stack(
children: [
GestureDetector(
onTap:()
{
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back),
),
Center(
child: Text("Enter Drop of Location", style: TextStyle(fontSize: 17.0, fontFamily: "Brand-Regular"),),
),
],
),
SizedBox(height: 16.0),
Row(
children: [
Image.asset("images/pickicon.png", height: 20.0, width: 20.0,),
SizedBox(width: 18.0),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: EdgeInsets.all(3.0),
child: TextField(
onChanged: (text)
{
findPlace(text);
},
controller: pickUpTextEditingController,
decoration: InputDecoration(
hintText: "PickUp Location",
hintStyle: TextStyle(color: Colors.grey[400],),
fillColor: Colors.grey[200],
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 11.0, top: 8.0, bottom: 8.0),
),
),
),
),
),
],
),
SizedBox(height: 10.0),
Row(
children: [
Image.asset("images/desticon.png", height: 20.0, width: 20.0,),
SizedBox(width: 18.0),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: EdgeInsets.all(3.0),
child: TextField(
onChanged: (val)
{
findPlace(val);
},
controller: dropOffTextEditingController,
decoration: InputDecoration(
hintText: "Where to",
hintStyle: TextStyle(color: Colors.grey[400],),
fillColor: Colors.grey[200],
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 11.0, top: 8.0, bottom: 8.0),
),
),
),
),
),
],
),
],
),
),
),
//tile for predictions
SizedBox(height: 5.0,),
(placePredictionList.length > 0)
? Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 10.0),
child: ListView.separated(
padding: EdgeInsets.all(0.0),
itemBuilder: (context, index)
{
return PredictionTile(placePredictions: placePredictionList[index],);
},
separatorBuilder: (BuildContext context, int index) => Divider(),
itemCount: placePredictionList.length,
shrinkWrap: true,
physics: ClampingScrollPhysics(),
),
)
: Container(),
],
),
);
}
void findPlace(String placeName) async
{
if(placeName.length > 2)
{
String autoCompleteUrl = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$placeName&key=$mapkey&sessiontoken=1234567890&components=country:za";
var res = await RequestAssistant.getRequest(autoCompleteUrl);
if(res == "failed")
{
return;
}
if(res["status"] == "OK")
{
var predictions = res["predictions"];
var placesList = (predictions as List).map((e) => PlacePredictions.fromJson(e)).toList();
setState(() {
placePredictionList = placesList;
});
}
}
}
}
class PredictionTile extends StatelessWidget
{
final PlacePredictions placePredictions;
PredictionTile({Key key, this.placePredictions}) : super(key: key);
#override
Widget build(BuildContext context)
{
return TextButton(
onPressed: ()
{
getPlaceAddressDetails(placePredictions.place_id, context);
},
child: Container(
child: Column
(
children: [
SizedBox(width: 10.0),
Row(
children: [
Icon(Icons.add_location_alt),
SizedBox(width: 14.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(placePredictions.main_text, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 14.0),),
SizedBox(height: 3.0,),
Text(placePredictions.secondary_text, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 10.0, color: Colors.grey),),
],
),
),
],
),
SizedBox(width: 10.0),
],
),
),
);
}
void getPlaceAddressDetails(String placeId, context) async
{
showDialog(
context: context,
builder: (BuildContext context) => ProgressBox(message: "Getting drop-off location...",)
);
String placeDetailsUrl = "https://maps.googleapis.com/maps/api/place/details/json?place_id=$placeId&key=$mapkey";
var res = await RequestAssistant.getRequest(placeDetailsUrl);
Navigator.pop(context);
if(res == "failed")
{
return;
}
if(res["status"] == "OK")
{
Address address = Address();
address.placeName = res["result"]["name"];
address.latitude = res["result"]["geometry"]["location"]["lat"];
address.longitude = res["result"]["geometry"]["location"]["lng"];
Provider.of<AppData>(context, listen: false).updatedropOffLocationAddress(address);
print("Drop off location Selected ::");
print(address.placeName);
Navigator.pop(context, "obtainDirection");
}
}
}
Related
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()
);
I have implemented BLOC architecture for a user profile edit for a logged in user in flutter. The inputs are filled with user's existing info which I got from the API. But whenever input is focused and keyboard closes the entered value gets replaced with the initial value which I got from the API response.
This is my View profile UI
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:payd/services/profile_service.dart';
import 'package:payd/bloc/profile_bloc.dart';
import 'package:payd/model/profile_model.dart';
void main() {
runApp(EditProfile());
}
class EditProfile extends StatefulWidget {
#override
_EditProfilesState createState() => _EditProfilesState();
}
class _EditProfilesState extends State<EditProfile>
with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Image.asset('assets/logo.png', fit: BoxFit.cover),
actions: [
IconButton(
onPressed: () {},
icon: Image.asset('assets/Icon feather-bell.png'),
iconSize: 30,
),
],
elevation: 5,
),
backgroundColor: Color(0xFF33138C),
body: BlocProvider(
create: (context) => ProfileBloc(ProfileService()),
child: Body(),
),
);
}
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
class Body extends StatelessWidget {
static final _formKey = GlobalKey<FormState>();
void _submit() {
final isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
_formKey.currentState.save();
}
#override
Widget build(BuildContext context) {
final textFieldFocusNode = FocusNode();
final profileBloc = BlocProvider.of<ProfileBloc>(context);
var userSlug = '52q6x93k4y';
profileBloc.add(FetchProfile(userSlug));
Size size = MediaQuery.of(context).size;
return Container(
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(
image: DecorationImage(
image: new ExactAssetImage('assets/app-background.png'),
fit: BoxFit.cover)),
child: Padding(
padding: const EdgeInsets.all(0),
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
children: <Widget>[
SizedBox(
height: size.height,
child: Stack(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: size.height * 0.04),
// height: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0),
topRight: Radius.circular(40.0),
),
),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Column(
children: [
Container(
padding: EdgeInsets.only(
top: 30.0,
left: 20.0, bottom: 25.0),
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.keyboard_arrow_left),
iconSize: 30,
),
),
],
),
Column(
children: [
Container(
padding: EdgeInsets.only(
top: 30.0,
right: 30.0, bottom: 25.0),
alignment: Alignment.centerLeft,
child: Text(
'Edit Account',
style: const TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.w600,
color: Colors.black54),
),
),
],
),
],
),
BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
print(state);
if (state is ProfileIsLoaded) {
return Container(
child: Flexible(
child: SingleChildScrollView(
reverse: true,
padding:
EdgeInsets.only(left: 16, right: 16),
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
bottom:
size.height > 700
? 20
: 15),
padding: EdgeInsets.only(
left: 20.0,
right: 20.0,
bottom: 25.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: TextEditingController(
text: state.getProfile.firstName),
decoration: InputDecoration(
labelText: 'First Name'),
keyboardType: TextInputType
.name,
onFieldSubmitted: (
value) {
//Validator
},
validator: (value) {
if (value.isEmpty) {
return 'Required';
}
return null;
},
),
//box styling
SizedBox(
height: MediaQuery
.of(context)
.size
.width *
0.1,
),
TextFormField(
controller: TextEditingController(
text: state.getProfile.lastName),
decoration: InputDecoration(
labelText: 'Last Name'),
keyboardType: TextInputType
.name,
onFieldSubmitted: (
value) {
//Validator
},
validator: (value) {
if (value.isEmpty) {
return 'Required';
}
return null;
},
),
//box styling
SizedBox(
height: MediaQuery
.of(context)
.size
.width *
0.1,
),
SizedBox(
width: double.infinity,
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty
.all(
EdgeInsets.only(
top: 16.0,
bottom: 16.0),),
foregroundColor:
MaterialStateProperty
.all<Color>(
Colors.white),
backgroundColor: MaterialStateProperty
.all<Color>(
Color(
0xFF33138C)),
shape: MaterialStateProperty
.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(
25.0),
side: BorderSide(
color: Color(
0xFF33138C)))),),
onPressed: () =>
_submit(),
child: Text('Save',
style: TextStyle(
fontSize: 16.0
),),
),
),
],
),
),
),
],
),
),
),
);
} else {
return Center(child : CircularProgressIndicator());
}
}
),
SizedBox(height: 150),
],
)),
],
))
],
),
),
),
);
}
}
class ProfileError extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Image.asset('assets/empty-list.png')],
),
Text(
'Error',
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.black87),
),
Padding(
padding: EdgeInsets.only(left: 30.0, right: 30.0),
child: Text(
'After your first order you\'ll be able to view it here',
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w600,
color: Colors.grey,
),
textAlign: TextAlign.center,
),
),
],
),
);
}
}
I have two widgets which I shared codes below, In first card widget for user selecting ingredients, second card will be used for displaying selected ingrediens, initial both screen will be empty, when user add an igredients both widget will be rebuilt by according to selected ingredients, I could handle it displaying in first widget, but I can not handle to display selectedIngredient list data when it changes, I know I have to use provider packages but I could not implement for my code, I have stuck please help me.. .
class AddIngredientsCard extends StatefulWidget {
AddIngredientsCard({this.subCategoryId,this.subCategoryCardId});
final int subCategoryCardId;
final int subCategoryId;
#override
_AddIngredientsCardState createState() => _AddIngredientsCardState();
}
class _AddIngredientsCardState extends State<AddIngredientsCard>{
String textValue;
double _animatedContainerHeight=350;
double _top=15;
double _right=30;
double _left=30;
double _bottom=15;
List<String> items= [];
List<String>selectedIngredients=[];
#override
void initState() {
ingredients=ingredients..sort((String a, String b)=>a.compareTo(b));
items.addAll(ingredients);
super.initState();
}
void filterSearchResults(String query) {
List<String> searchList = [];
searchList.addAll(ingredients);
if(query.isNotEmpty) {
List<String> listData = [];
searchList.forEach((item) {
if(item.contains(query)) {
listData.add(item);
}
});
setState(() {
items.clear();
items.addAll(listData);
});
return;
} else {
setState(() {
items.clear();
items.addAll(ingredients);
});
}
}
void _toggleCardSize(){
_top==15?_top=7.5: _top=15;
_right==30?_right=7.5: _right=30;
_left==30?_left=7.5: _left=30;
_bottom==15?_bottom=7.5: _bottom=15;
}
void _toggleCardHeight(){
_animatedContainerHeight==350?_animatedContainerHeight=600:_animatedContainerHeight=350;
}
#override
Widget build(BuildContext context) {
return AnimatedPadding(
duration: Duration(milliseconds: 500),
curve: Curves.linearToEaseOut,
padding:EdgeInsets.only(top: _top,right: _right,left: _left,bottom: _bottom),
child: AnimatedContainer(
height:_animatedContainerHeight,
duration: Duration(milliseconds: 500),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
border:Border.all(style: BorderStyle.solid, width: 1),
color: Colors.white,
borderRadius: BorderRadius.circular(90),
),
height: 60,
child: TextField(
style: TextStyle(
color: Colors.black,
fontFamily:"OpenSans",
fontSize: 20,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.center,
onChanged: (value){
if(value.length>0){
value=value[0].toUpperCase()+value.substring(1);
filterSearchResults(value);
}
else{
filterSearchResults(value);
}
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
border:OutlineInputBorder(
borderRadius: BorderRadius.circular(90),
borderSide: BorderSide(
color: kColorTheme10,
),
),
hintText: "Malzeme ismi arayın",
hintStyle: TextStyle(
color: Colors.black.withOpacity(0.5),
fontFamily: "OpenSans",
),
),
),
),
SizedBox(height: 2,),
Expanded(
flex: _animatedContainerHeight==350?1:4,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: selectedIngredients.length,
itemBuilder: (context,index){
return Padding(
padding: EdgeInsets.all(1),
child: GestureDetector(
onTap: (){
setState(() {
selectedIngredients.removeAt(index);
if (selectedIngredients.length == 0) {
_toggleCardHeight();
_toggleCardSize();
}
}
);
},
child: Container(
decoration: BoxDecoration(
color: kColorTheme11,
borderRadius: BorderRadius.circular(90),
border: Border.all(style: BorderStyle.solid,width: 1),
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BorderedText(strokeColor: Colors.black,strokeWidth: 5,child: Text(selectedIngredients[index],style:
TextStyle(fontWeight: FontWeight.bold,fontSize:20,color: Colors.white),)),
SizedBox(width: 5,),
Icon(
Icons.cancel,color: Colors.white,size: 20,
),
],
),
),
),
),
);
}
),
),
SizedBox(height: 2,),
Expanded(
flex: 40,
child: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(2.0),
child: GestureDetector(
onTap: (){
setState(() {
if(selectedIngredients.length==0){
selectedIngredients.add("${items[index]}");
_toggleCardHeight();
_toggleCardSize();
}
else{
selectedIngredients.add("${items[index]}");
}
});
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(90),
border: Border.all(style:BorderStyle.solid,width: 1),
color: Colors.white54,
),
child: Padding(
padding: EdgeInsets.all(5),
child: Text('${items[index]}',style: TextStyle(fontWeight: FontWeight.bold),)),
),
),
);
},
),
),
SizedBox(height: 8,),
Expanded(
flex: _animatedContainerHeight==350?1:4,
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
color: _animatedContainerHeight==350?categoryModels[widget.subCategoryId].
subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.1):kColorTheme11,
borderRadius: BorderRadius.circular(20),
border: _animatedContainerHeight==350?null:
Border.all(style: BorderStyle.solid,width: 2),
),
child: Padding(
padding: EdgeInsets.all(5),
child: GestureDetector(
onTap: (){
AddIngredientsAmount(subCategoryId:widget.subCategoryId,subCategoryCardId: widget.subCategoryId,selectedIngredients: selectedIngredients,);
/////////////////////////////////////// => isPageSaved için Provider eklenecek...
},
child: Center(child: BorderedText(strokeWidth:3,strokeColor: Colors.black,child:
Text("KAYDET",style: TextStyle(fontSize: 25, fontWeight: FontWeight.w900 ,color: Colors.white))),
),
),
),
)
),
],
),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(30),
color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
)
),
);
}
}
class AddIngredientsAmount extends StatefulWidget {
AddIngredientsAmount({this.subCategoryId,this.subCategoryCardId, this.selectedIngredients});
final List selectedIngredients;
final int subCategoryCardId;
final int subCategoryId;
#override
_AddIngredientsAmountState createState() => _AddIngredientsAmountState();
}
class _AddIngredientsAmountState extends State<AddIngredientsAmount> {
String textValue;
double _animatedContainerHeight=300;
double _top=15;
double _right=30;
double _left=30;
double _bottom=15;
#override
Widget build(BuildContext context) {
void _toggleCardSize(){
_top==15?_top=7.5: _top=15;
_right==30?_right=7.5: _right=30;
_left==30?_left=7.5: _left=30;
_bottom==15?_bottom=7.5: _bottom=15;
}
void _toggleCardHeight(){
_animatedContainerHeight==300?_animatedContainerHeight=500:_animatedContainerHeight=300;
}
return AnimatedPadding(
duration: Duration(milliseconds: 500),
curve: Curves.linearToEaseOut,
padding:EdgeInsets.only(top: _top,right: _right,left: _left,bottom: _bottom),
child: GestureDetector(
onTap: (){
setState(() {
_toggleCardHeight();
_toggleCardSize();
});
},
child: AnimatedContainer(
height:_animatedContainerHeight,
duration: Duration(milliseconds: 500),
child: Padding(
padding: EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
decoration: BoxDecoration(
border:Border.all(style: BorderStyle.solid, width: 1),
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(90))),
child: Center(
child: Text("Malzemelerinizin Miktarını Belirlerin",style: TextStyle(
color: Colors.black,
fontFamily:'OpenSans',
fontSize:25,
fontWeight: FontWeight.w300,
),
),
),
),
SizedBox(height: 7.5,),
Expanded(
child: Container(
decoration: BoxDecoration(
color:Colors.white,
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(10),
),
child: ListView.builder(
itemCount: widget.selectedIngredients.length==null?0:
widget.selectedIngredients.length,
itemBuilder: (context, index){
return Padding(
padding: EdgeInsets.all(2),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(90),
border: Border.all(style:BorderStyle.solid,width: 1),
color: Colors.white54,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(5),
child: Text('${widget.selectedIngredients[index]}',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 30),)),
],
),
),
);
},
),
),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(30),
color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
)
)
),
);
}
}
//------------------------------------------------------------------------
class AddRecipeVoice extends StatefulWidget {
AddRecipeVoice({this.subCategoryId,this.subCategoryCardId});
final int subCategoryCardId;
final int subCategoryId;
#override
_AddRecipeVoiceState createState() => _AddRecipeVoiceState();
}
class _AddRecipeVoiceState extends State<AddRecipeVoice> {
String textValue;
#override
Widget build(BuildContext context) {
return AnimatedPadding(
duration: Duration(seconds: 1),
curve: Curves.linearToEaseOut,
padding:EdgeInsets.only(top: 15,left: 30,right: 30,bottom: 7.5),
child: GestureDetector(
onTap: (){
setState(() {
});
},
child: Container(
height:130,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
decoration: BoxDecoration(
border:Border.all(style: BorderStyle.solid, width: 1),
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(90))),
child: Center(
child: Text("Tarifinizi anlatın",style: TextStyle(
color: Colors.black,
fontFamily:'OpenSans',
fontSize:25,
fontWeight: FontWeight.w300,
),
),
),
),
SizedBox(height: 7.5,),
Expanded(
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color:kColorTheme7,
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(Icons.mic,size: 40,color: Colors.white,),
SizedBox(width: 50,),
Text(
"KAYIT ZAMANI !!",
style: TextStyle(
fontSize: 30,
fontFamily: "OpenSans",
color: Colors.white,
fontWeight: FontWeight.bold
),
),
],
),
),
),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(30),
color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
)
)
),
);
}
}
Make a provider class that mixin with ChangeNotifier.
Wrap your widget prior calling the provider class with MultiProvider widget. Likewise:
MultiProvider (
providers: [
ChangeNotifierProvider.value(value: IngredientsProvider()),
],
child: YourWidget(), //You can wrap your MaterialApp here
)
Create your needed methods that changes the selected data and call notifyListeners() inside your method. It will rebuild your desired widget where you listen to them.
Example:
class IngredientsProvider with ChangeNotifier {
List<String> _selectedIngredients = [];
List<String> get selectedIngredients() {
return _selectedIngredients;
}
void addIngredient(String ingredient) {
_selectedIngredients.add(ingredient);
notifyListeners();
}
}
In your widget listen to them:
Widget1 {
//Call this in you onPress/onTap
void addIngredient(String ing, BuildContext ctx) {
Provider.of<IngredientsProvider>(ctx, listen:
false).addIngredient(ing);
}
........
#override
Widget build(BuildContext context) {
//Use this list to select
List<String> _ingredients = Provider.of<IngredientsProvider>(context, listen:
true).ingredients;
}
........
}
Use in the 2nd Widget in this way.
Widget2 {
........
#override
Widget build(BuildContext context) {
//Use this list to show
List<String> _ingredients = Provider.of<IngredientsProvider>(context, listen:
true).ingredients;
}
........
}
I am creating a app using flutter and firebase. but when i am trying to create a user instance it is showing this error:- "PlatformException(ERROR_INVALID_EMAIL, The email address is badly formatted., null)"
I am attaching the code.///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
import 'package:chatbox/services/auth.dart';
import 'package:chatbox/services/database.dart';
import 'package:chatbox/views/chatRoom.dart';
import 'package:chatbox/widgets/widget.dart';
import 'package:flutter/material.dart';
class SignUp extends StatefulWidget {
final Function toggle;
SignUp(this.toggle);
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
bool isLoading = false;
DatabaseMethods databaseMethods=new DatabaseMethods();
AuthMethods authMethods = new AuthMethods();
final formKey = GlobalKey<FormState>();
TextEditingController userNameTextEditingController =
new TextEditingController();
TextEditingController emailTextEditingController =
new TextEditingController();
TextEditingController passwordTextEditingController =
new TextEditingController();
signMeUp() async {
if(formKey.currentState.validate()) {
Map<String,String> userInfoMap={
"email": emailTextEditingController.text,
"name" : userNameTextEditingController.text,
};
setState(() {
isLoading =true;
});
authMethods.signUpWithEmailAndPassword(emailTextEditingController.text, passwordTextEditingController.text)
.then((val){
// print("${val.uid}");
databaseMethods.uploadUserInfo(userInfoMap);
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context)=>chatRoom(),
));
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarMain(context),
body: isLoading ? Container(
child: Center(child: CircularProgressIndicator()) ,
) : SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height - 50,
alignment: Alignment.bottomCenter,
padding: EdgeInsets.symmetric(horizontal: 24),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (val) {
return val.isEmpty || val.length < 2 ? "invalid" : null;
},
controller: userNameTextEditingController,
style: simpleTextstyle(),
decoration: textFieldInputDecoration("username"),
),
TextFormField(
validator: (val){
return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(val) ? null : "Enter correct email";
},
controller: emailTextEditingController,
style: simpleTextstyle(),
decoration: textFieldInputDecoration("email"),
),
TextFormField(
validator: (val) {
return val.length < 6
? "Enter Password 6+ characters"
: null;
},
controller: passwordTextEditingController,
style: simpleTextstyle(),
obscureText: true,
decoration: textFieldInputDecoration("password"),
),
],
),
),
SizedBox(
height: 8,
),
Container(
alignment: Alignment.centerRight,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text(
"forget password",
style: simpleTextstyle(),
),
)),
SizedBox(
height: 8,
),
GestureDetector(
onTap: () {
signMeUp();
},
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
const Color(0xff007EF4),
const Color(0xff2A75BC)
]),
borderRadius: BorderRadius.circular(40)),
child: Text(
"Sign up",
style: TextStyle(color: Colors.white, fontSize: 17),
),
),
),
SizedBox(
height: 8,
),
Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(40)),
child: Text(
"Sign up with google",
style: TextStyle(color: Colors.black, fontSize: 17),
),
),
SizedBox(
height: 8,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Already have an account?",
style: meadiumTextstyle(),
),
GestureDetector(
onTap: (){
widget.toggle();
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Text("Sign in Now",
style: TextStyle(
color: Colors.white,
fontSize: 17,
decoration: TextDecoration.underline,
)),
),
),
],
),
SizedBox(
height: 60,
),
]),
),
),
);
}
}
Assume email is correct
From issue https://github.com/FirebaseExtended/flutterfire/issues/1760#issuecomment-570766212 and https://github.com/FirebaseExtended/flutterfire/issues/1760#issuecomment-613303831
email text field value might contain white space
You can use emailTextEditingController.text.trim()
code snippet
authMethods.signUpWithEmailAndPassword(emailTextEditingController.text.trim(), passwordTextEditingController.text)
...
Map<String,String> userInfoMap={
"email": emailTextEditingController.text.trim(),
"name" : userNameTextEditingController.text,
};
You can also use package https://pub.dev/packages/email_validator to validate email
code snippet
import 'dart:core';
import 'package:email_validator/email_validator.dart';
void main() {
const String email = 'fredrik.eilertsen#gail.com';
final bool isValid = EmailValidator.validate(email);
print('Email is valid? ' + (isValid ? 'yes' : 'no'));
}
The error is because your email id is not in the correct format. Try editing your email id.
In your email validator add this.
Validator(val){
if(!val.contains("#")){
retrun enter a valid email}
else{ return null}
}
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),
),
],
),
);
}