SharedPreferences in Flutter - flutter

I'm having trouble getting certain items from an array and saving them in SharedPreferences.
This is my login function, where it returns a body with all the user information.
I store the whole array inside my SharedPreferences but I can't access the items separately. I need them separated, as I want to show the name of the logged in user on another screen, etc.
This is the print of "resposta.body"
login_widget.dart
The login function is on bottom
import 'package:biolivre2/cadastro_usuario/cadastro_usuario_widget.dart';
import 'package:biolivre2/index.dart';
import 'package:biolivre2/services/service-prefs.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:page_transition/page_transition.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class LoginWidget extends StatefulWidget {
const LoginWidget({Key key}) : super(key: key);
#override
_LoginWidgetState createState() => _LoginWidgetState();
}
bool _isObscure = false;
class _LoginWidgetState extends State<LoginWidget> {
final _formkey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _senhaController = TextEditingController();
#override
void initState() {
bool _isObscure = false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromARGB(255, 5, 45, 106),
body: Form(
key: _formkey,
child: SingleChildScrollView(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 1,
constraints: BoxConstraints(
maxWidth: 800,
),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 80, 0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset(
'assets/images/logo-livre.png',
width: 130,
height: 130,
fit: BoxFit.contain,
),
],
),
Padding(
padding: const EdgeInsets.fromLTRB(20.0, 30, 20, 0),
child: TextFormField(
style: TextStyle(color: Colors.white),
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
labelStyle: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w500,
),
filled: true,
fillColor: Color.fromARGB(255, 5, 45, 106),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.white, width: 1.56),
borderRadius: BorderRadius.circular(10)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: const BorderSide(
color: Colors.white, width: 1.56),
)),
validator: (email) {
if (email == null || email.isEmpty) {
return 'Por favor, digite seu e-mail';
} else if (!RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(_emailController.text)) {
return 'Por favor, digite um e-mail correto';
}
return null;
},
),
),
const Padding(
padding:
EdgeInsets.symmetric(horizontal: 8, vertical: 8)),
Padding(
padding: const EdgeInsets.fromLTRB(20.0, 10, 20, 0),
child: TextFormField(
style: TextStyle(color: Colors.white),
controller: _senhaController,
obscureText: _isObscure,
keyboardType: TextInputType.text,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(_isObscure
? Icons.visibility_off
: Icons.visibility),
color: Theme.of(context).primaryColorLight,
onPressed: () {
setState(() {
_isObscure = !_isObscure;
});
}),
labelText: 'Senha',
labelStyle: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w500,
),
filled: true,
fillColor: Color.fromARGB(255, 5, 45, 106),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.white, width: 1.56),
borderRadius: BorderRadius.circular(10)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: const BorderSide(
color: Colors.white, width: 1.56),
)),
validator: (senha) {
if (senha == null || senha.isEmpty) {
return 'Por favor, digite uma senha';
} else if (senha.length < 6) {
return "Por favor, digite uma senha com mais de 6 caracteres";
}
return null;
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 30, 0, 20),
child: TextButton(
onPressed: () async {
FocusNode currentFocus = FocusScope.of(context);
if (_formkey.currentState.validate()) {
var valido = await login();
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
if (valido) {
verificaUser();
} else {
_senhaController.clear();
ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
}
}
},
child: const Text("Login"),
style: TextButton.styleFrom(
fixedSize: const Size(150, 50),
backgroundColor: Colors.white,
primary: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 30, 0, 20),
child: Container(
child: const Text(
"Ainda não um tem cadastro?\n"
"Clique no botão abaixo",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.white)),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: TextButton(
onPressed: () {
Navigator.push(
context,
PageTransition(
type: PageTransitionType.fade,
duration: Duration(milliseconds: 300),
reverseDuration:
Duration(milliseconds: 300),
child: CadastroUsuarioWidget(),
),
);
},
child: const Text("Cadastrar"),
style: TextButton.styleFrom(
fixedSize: const Size(150, 50),
backgroundColor: Colors.blue,
primary: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
),
),
],
),
],
),
),
),
],
),
),
),
);
}
final snackBar = const SnackBar(
content: Text(
"Email ou senha incorretos",
textAlign: TextAlign.center,
),
backgroundColor: Colors.redAccent,
);
Future<bool> login() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
SharedPreferences usuario = await SharedPreferences.getInstance();
var email = _emailController.text;
var senha = _senhaController.text;
var auth = 'Basic ' + base64Encode(utf8.encode('$email:$senha'));
var url = Uri.parse("http://177.70.102.109:3005/autenticacao");
var resposta = await http.get(
url,
headers: (<String, String>{'authorization': auth}),
);
print(resposta.body);
if (resposta.statusCode == 200) {
await sharedPreferences.setString(
'token', "Token ${jsonDecode(resposta.body)['token']}");
await usuario.setString(
'usuario', "Usuario ${jsonDecode(resposta.body)['usuario']}");
print(usuario);
return true;
} else {
return false;
}
}
verificaUser() async {
//trocar por nivel usuario logado
var email = _emailController.text;
if (email == "admin#kitlivre.com") {
await Navigator.push(
context,
PageTransition(
type: PageTransitionType.fade,
duration: Duration(milliseconds: 300),
reverseDuration: Duration(milliseconds: 300),
child: InicioUsuarioWidget(),
),
);
} else {
await Navigator.push(
context,
PageTransition(
type: PageTransitionType.fade,
duration: Duration(milliseconds: 300),
reverseDuration: Duration(milliseconds: 300),
child: InicioUsuarioWidget(),
),
);
}
}
}
Json
[
{
"nome": "",
"email": "",
"data_de_nascicmento": "1900-01-01T00:00:00.000Z",
"documento": "",
"telefone_fixo": null,
"telefone_celular": null,
"cep": "",
"logradouro": "",
"numero": "",
"complemento": "",
"bairro": "",
"cidade": "",
"estado": "",
"situacao_lesao": "",
"nivel_lesao": "",
"detalhe_lesao": "",
"foto_documento": "",
"foto_com_documento": "",
"foto_reconhecimento": null,
"foto_documento64": null,
"foto_com_documento64": null,
"foto_reconhecimento64": null,
"nivel": 1,
"senha": "$2a$10$22bLU3zd7Ry8JoqcXuePieNdHrvqQklSvIe9nN6nOF1l30D5e47b2",
"telefone": "",
"sobrenome": "",
"ativo": true,
"id": 1,
"tipo_usuario": "USUÁRIO",
"painel_de_gerenciamento": false,
"atualizar_equipamentos": false,
"estoque_de_equipamentos": false,
"solicitacao_de_equipamentos": true,
"devolucao_de_equipamentos": true
}]

Related

Field has not been initialized

tags in my code is a List which is comes from previous page,
I want to be able to remove and add items to it in my current page,
first I tried to initialize it in my initState but when I want to remove tags it doesn't work.
I guessed it is about the initialization, so I removed it from initState but now I am getting this error message Field 'tags' has not been initialized. I will attach my full code and I appreciate any suggestions about it. Thanks.
PS: I tried initializing tags with tags=[] in my initState but I can't remove any of the tags. It has a GestureDetector to remove tags, when I press it nothing happens. I guess initializing in the build function causes it, but I don't know where to initialize it that I could be able to edit it while the list is coming from another screen.
also when I added tags = widget.tags.where((e) => e != null && e != "").toList(); to my initiState and I inspect tags value, there is an empty string in addtion to other values at the end of the list.
import 'dart:convert';
import 'dart:developer';
import 'package:double_back_to_close/toast.dart';
import 'package:flutter/material.dart';
import 'package:pet_store/main.dart';
import 'package:pet_store/widgets/tag_preview.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import 'dart:async';
import 'dart:math';
import 'package:http/http.dart' as http;
import 'package:pet_store/widgets/tag_retrieve_preview.dart';
import 'utils/utils.dart';
class update_pet extends StatefulWidget {
var id;
var name;
var status;
var category;
var tags ;
update_pet(
{this.id, this.name, this.status, this.category, this.tags, Key? key})
: super(key: key);
#override
_update_petState createState() => _update_petState();
}
class _update_petState extends State<update_pet> {
final _picker = ImagePicker();
Future<void> _openImagePicker() async {
final XFile? pickedImage =
await _picker.pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
setState(() {
final bytes = File(pickedImage.path).readAsBytesSync();
base64Image = "data:image/png;base64," + base64Encode(bytes);
});
}
}
String? base64Image;
TextEditingController nameController = TextEditingController();
TextEditingController categoryController = TextEditingController();
TextEditingController tagController = TextEditingController();
late File imageFile;
late List<dynamic> tags;
bool isLoading = false;
void initState() {
super.initState();
nameController.text = widget.name;
categoryController.text = widget.category;
addTag();
}
void addTag() {
setState(() {
tags.add(tagController.text);
tagController.clear();
});
}
String? dropdownvalue;
var items = [
'available',
'pending',
'sold',
];
#override
Widget build(BuildContext context) {
tags = widget.tags.where((e) => e != null && e != "").toList();
// inspect(tags);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.indigo,
title: const Text('Update a pet'),
leading: GestureDetector(
child: Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onTap: () {
// Navigator.pop(context);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
PetStoreHomePage(LoggedIn: true),
),
(route) => false,
);
},
),
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Card(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
children: [
const ListTile(
// leading,
title: Text(
"General Information",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
TextField(
controller: nameController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Enter your pet's name",
),
),
DropdownButton(
hint: const Text('Select Status'),
value: dropdownvalue,
icon: const Icon(Icons.keyboard_arrow_down),
items: items.map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
});
},
),
],
),
),
elevation: 8,
shadowColor: Colors.grey.shade300,
margin: const EdgeInsets.all(20),
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.white)),
),
Card(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
children: [
const ListTile(
// leading,
title: Text(
"Category",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
TextField(
controller: categoryController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Specify your pet's category",
),
),
],
),
),
elevation: 8,
shadowColor: Colors.grey.shade300,
margin:
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.white)),
),
Card(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
// leading,
title: Text(
"Tags",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Flexible(
fit: FlexFit.loose,
child: ListView.builder(
shrinkWrap: true,
itemCount: tags.length,
itemBuilder: (_, index) {
print(tags);
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 5.0, vertical: 3.0),
child: GestureDetector(
child: tagRetrievePreview(tags[index]),
onTap: () {
print("REMOVED "+tags[index]);
tags.removeAt(index);
}),
);
},
),
),
TextField(
controller: tagController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Specify your pet's tags",
suffixIcon: IconButton(
icon: const Icon(
Icons.add_circle_outline_sharp,
color: Color.fromARGB(255, 129, 128, 128),
size: 30,
),
onPressed: () {
addTag();
print(tags);
},
),
),
),
],
),
),
elevation: 8,
shadowColor: Colors.grey.shade300,
margin:
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.white)),
),
Card(
child: Column(
children: [
const ListTile(
title: Text(
"Images",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
(base64Image != null)
? SizedBox(
width: 100,
height: 100,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: DecorationImage(
image: image(base64Image!).image,
fit: BoxFit.fill),
)),
)
: SizedBox(
width: 100,
height: 100,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.grey.shade300,
),
child: Icon(
Icons.camera_alt,
color: Colors.grey.shade800,
size: 30,
),
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 100),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
const Color.fromARGB(255, 129, 128, 128)),
padding: MaterialStateProperty.all(
const EdgeInsets.symmetric(horizontal: 20)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: const BorderSide(
color: Color.fromARGB(255, 129, 128, 128),
width: 2.0,
),
),
),
),
child: const Text(
'Select Image',
style:
TextStyle(fontSize: 15.0, color: Colors.white),
),
onPressed: _openImagePicker),
),
],
),
elevation: 8,
shadowColor: Colors.grey.shade300,
margin:
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.white)),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 120),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.indigo),
padding: MaterialStateProperty.all(
const EdgeInsets.symmetric(horizontal: 40)),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: const BorderSide(
color: Colors.indigo,
width: 2.0,
),
),
),
),
child: isLoading
? const SizedBox(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white)),
height: 15.0,
width: 15.0,
)
: const Text(
'Update Pet',
style:
TextStyle(fontSize: 17.0, color: Colors.white),
),
onPressed: () async {
if (nameController.text.isEmpty) {
nameController.text = widget.name;
}
if (tagController.text.isEmpty) {
tagController.text = widget.tags;
}
if (categoryController.text.isEmpty) {
categoryController.text = widget.category;
}
if (dropdownvalue == null) {
dropdownvalue = widget.status;
}
print('Pressed');
Map data = {
"id": random.nextInt(10000),
///random it integer
"name": nameController.text,
"category": {
"id": set_category_id(categoryController.text),
"name": categoryController.text,
},
"photoUrls": [base64Image],
"tags": set_tags(tags),
"status": dropdownvalue
};
var body = json.encode(data);
var response = await http.put(
Uri.parse(
"https://api.training.testifi.io/api/v3/pet"),
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: body);
print(response.body);
print(response.statusCode);
if (response.statusCode == 201 ||
response.statusCode == 200) {
print('success');
Toast.show("Pet is successfully updated.", context);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
PetStoreHomePage(LoggedIn: true),
),
(route) => false,
);
} else {
Toast.show(
"ERROR! Updating pet failed. Please try again.",
context);
}
}),
),
],
),
),
),
);
}
}
tags = widget.tags.where((e) => e != null && e != "").toList();
This line in build method will constantly take value from widget.tags and create a list of items thats not null and empty.
Please add this in initState.
Just initialize it
List<dynamic> tags = [];
PS: I tried initializing tags with tags=[] in my initState but I can't
remove any of the tags.
You need to add setState to rebuild the page.

Flutter Image Picker to Image URL

i have the following code below. ive used image_picker package to upload pictures to be used as profile pictures. ive commented my previous code that uses an image url instead. my question is if there's a way to convert the images uploaded to images url, that way, i can display the profile picture when i get into the home screen.
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
import 'dart:io';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:firebase_auth/firebase_auth.dart' as firebase;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:ibchat/pages/verify_email_page.dart';
import 'package:ibchat/screens/screens.dart';
import 'package:ibchat/theme.dart';
import 'package:image_picker/image_picker.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import '../app.dart';
class SignUpScreen extends StatefulWidget {
static Route get route => MaterialPageRoute(
builder: (context) => const SignUpScreen(),
);
const SignUpScreen({Key? key}) : super(key: key);
#override
State<SignUpScreen> createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
final auth = firebase.FirebaseAuth.instance;
final functions = FirebaseFunctions.instance;
final _formKey = GlobalKey<FormState>();
PickedFile? _imageFile;
final ImagePicker _picker = ImagePicker();
//final _profilePictureController = TextEditingController();
final _nameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _designationController = TextEditingController();
final _companyController = TextEditingController();
final _emailRegex = RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+");
bool _loading = false;
Future<void> _signUp() async {
if (_formKey.currentState!.validate()) {
setState(() {
_loading = true;
});
try {
// Authenticate with Firebase
final creds =
await firebase.FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
final user = creds.user;
if (user == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Member not found')),
);
return;
}
// Set Firebase display name and profile picture
List<Future<void>> futures = [
/*if (_profilePictureController.text.isNotEmpty)
creds.user!.updatePhotoURL(_profilePictureController.text),*/
/*if (_picker.toString().isNotEmpty)
creds.user!.updatePhotoURL(_picker.toString()),*/
creds.user!.updateDisplayName(_nameController.text),
];
await Future.wait(futures);
// Create Stream user and get token using Firebase Functions
final callable = functions.httpsCallable('createStreamUserAndGetToken');
final results = await callable();
// Connect user to Stream and set user data
final client = StreamChatCore.of(context).client;
await client.connectUser(
User(
//image: _profilePictureController.text,
//image: _picker.toString(),
id: creds.user!.uid,
name: _nameController.text,
extraData: {
"email": _emailController.text,
"designation": _designationController.text,
"company": _companyController.text,
}),
results.data,
);
// Navigate to verify email page
await Navigator.of(context).pushReplacement(VerifyEmailPage.route);
} on firebase.FirebaseAuthException catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Colors.red,
content: Text(e.message ?? 'Verification error')),
);
} catch (e, st) {
logger.e('Sign up error', e, st);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.red, content: Text('An error occured')),
);
}
setState(() {
_loading = false;
});
}
}
String? _nameInputValidator(String? value) {
if (value == null || value.isEmpty) {
return 'Name cannot be empty';
}
return null;
}
String? _emailInputValidator(String? value) {
if (value == null || value.isEmpty) {
return 'Email cannot be empty';
}
if (!_emailRegex.hasMatch(value)) {
return 'Not a valid email';
}
return null;
}
String? _passwordInputValidator(String? value) {
if (value == null || value.isEmpty) {
return 'Password Cannot be empty';
}
if (value.length <= 6) {
return 'Password needs to be longer than 6 characters';
}
return null;
}
#override
void dispose() {
//_profilePictureController.dispose();
_nameController.dispose();
_emailController.dispose();
_passwordController.dispose();
_designationController.dispose();
_companyController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Image.asset('assets/images/logo.png', scale: 2),
backgroundColor: Colors.transparent,
),
body: (_loading)
? const Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(color: AppColors.accent)))
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
onWillPop: () async => false,
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 24),
child: Text(
'Registeration',
style: GoogleFonts.lato(
fontSize: 28, fontWeight: FontWeight.w800),
),
),
/*Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
controller: _profilePictureController,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: AppColors.accent, width: 2),
),
hintText: 'Picture URL',
hintStyle: TextStyle(fontSize: 17),
),
style: const TextStyle(fontSize: 17),
keyboardType: TextInputType.url,
),
),*/
imageProfile(),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
controller: _nameController,
validator: _nameInputValidator,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: AppColors.accent, width: 2),
),
hintText: 'Name',
hintStyle: TextStyle(fontSize: 17),
),
style: const TextStyle(fontSize: 17),
keyboardType: TextInputType.name,
autofillHints: const [
AutofillHints.name,
AutofillHints.username
],
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
controller: _emailController,
validator: _emailInputValidator,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: AppColors.accent, width: 2),
),
hintText: 'Email',
hintStyle: TextStyle(fontSize: 17),
),
style: const TextStyle(fontSize: 17),
keyboardType: TextInputType.emailAddress,
autofillHints: const [AutofillHints.email],
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
controller: _passwordController,
validator: _passwordInputValidator,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: AppColors.accent, width: 2),
),
hintText: 'Password',
hintStyle: TextStyle(fontSize: 17),
),
style: const TextStyle(fontSize: 17),
obscureText: true,
enableSuggestions: false,
autocorrect: false,
keyboardType: TextInputType.visiblePassword,
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
controller: _designationController,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: AppColors.accent, width: 2),
),
hintText: 'Designation',
hintStyle: TextStyle(fontSize: 17),
),
style: const TextStyle(fontSize: 17),
keyboardType: TextInputType.name,
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextFormField(
controller: _companyController,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: AppColors.accent, width: 2),
),
hintText: 'Company',
hintStyle: TextStyle(fontSize: 17),
),
style: const TextStyle(fontSize: 17),
keyboardType: TextInputType.name,
),
),
const SizedBox(height: 30),
Padding(
padding: const EdgeInsets.all(12.0),
child: SizedBox(
height: 50,
width: 250,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
))),
onPressed: _signUp,
child: Text('Sign Up',
style: GoogleFonts.lato(
fontSize: 21,
fontWeight: FontWeight.bold,
color: Colors.black)),
),
),
),
const SizedBox(
height: 20,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Already a Member?',
style: Theme.of(context).textTheme.subtitle2),
const SizedBox(width: 8),
TextButton(
style: TextButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
primary: AppColors.accent),
onPressed: () {
Navigator.of(context).push(SignInScreen.route);
},
child: const Text('Sign In',
style: TextStyle(color: AppColors.secondary)),
),
],
),
],
),
),
),
),
);
}
Widget imageProfile() {
return Center(
child: Stack(
children: <Widget>[
CircleAvatar(
radius: 34,
backgroundImage: _imageFile == null
? const AssetImage("assets/images/profile_default.png")
as ImageProvider
: FileImage(File(_imageFile!.path)),
),
Positioned(
bottom: -2,
right: -1,
child: InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: ((builder) => bottomSheet()),
);
},
child: const Icon(CupertinoIcons.camera_fill,
color: AppColors.accent, size: 20)),
)
],
),
);
}
Widget bottomSheet() {
return Container(
height: 100,
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 20,
),
child: Column(
children: <Widget>[
const Text(
"Upload a Profile Photo",
style: TextStyle(
fontSize: 18.0,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
icon: const Icon(CupertinoIcons.camera_fill),
onPressed: () {
takePhoto(ImageSource.camera);
},
label: const Text("Camera")),
FlatButton.icon(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
icon:
const Icon(CupertinoIcons.photo_fill_on_rectangle_fill),
onPressed: () {
takePhoto(ImageSource.gallery);
},
label: const Text("Photos")),
],
)
],
));
}
void takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(source: source);
setState(() {
_imageFile = pickedFile!;
});
}
}

setState not updating the value in the screen using Flutter desktop

So I'm trying to update the value of the drop down list using the setState, but when I select a value from the list, the value on the screen won't be able to change
import 'package:demo_app_admin/Custom/custom_Font.dart';
import 'package:flutter/material.dart';
import '/Custom/Custom_Raised_Bottun.dart';
import '/Custom/Header.dart';
import '/Custom/inputField.dart';
class LoginView extends StatefulWidget {
#override
_LoginViewState createState() => _LoginViewState();
}
class _LoginViewState extends State<LoginView> {
#override
Widget build(BuildContext context) {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
String _dropdownvalue = "Global admin";
List<String> _items = <String> ["Global admin", "Institution admin"];
return Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(begin: Alignment.topCenter, colors: [
Colors.teal[700]!,
Colors.teal[200]!,
Colors.teal[400]!
]),
),
child: Column(
children: <Widget>[
const SizedBox(
height: 80,
),
if (!isKeyboard)
Header(
padding: const EdgeInsets.all(20),
crossAxisAlignment: CrossAxisAlignment.start,
head: "Welcome",
headTextStyle:
const TextStyle(color: Colors.white, fontSize: 40),
sizedBoxHeight: 10,
subtitle: "Sign In to Your Admin Account",
subtitleTextStyle:
const TextStyle(color: Colors.white, fontSize: 18),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
)),
child: Padding(
padding: const EdgeInsets.all(30),
child: SingleChildScrollView(
reverse: true,
padding: EdgeInsets.all(32),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
const SizedBox(
height: 40,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)),
child: Column(
children: <Widget>[
InputField(
labelText: 'Email',
padding: EdgeInsets.all(10),
borderSide: BorderSide(color: Colors.grey),
hintText: "Enter your email",
color: Colors.grey,
inputBorder: InputBorder.none,
obscureText: false,
enableSuggestion: true,
autoCorrect: true,
onSaved: (value) {},
// (value){controller.email = value!;},
validator: (value) {
if (value == null) {
print("ERROR");
}
},
),
InputField(
labelText: 'Password',
padding: EdgeInsets.all(10),
borderSide: BorderSide(color: Colors.grey),
hintText: "Enter your password",
color: Colors.grey,
inputBorder: InputBorder.none,
obscureText: true,
enableSuggestion: false,
autoCorrect: false,
onSaved: (value) {},
// (value){ controller.password = value!;},
validator: (value) {
if (value == null) {
print("ERROR");
}
},
),
],
),
),
const SizedBox(
height: 40,
),
here is the issue
DropdownButton<String>(
value: _dropdownvalue,
icon: Icon(Icons.keyboard_arrow_down),
items: _items.map((String _items) {
return DropdownMenuItem<String>(
value: _items,
child: CustomFont(text: _items),
);
}).toList(),
onChanged: (value) {
setState(() => _dropdownvalue = value!);
}),
const SizedBox(
height: 40,
),
CustomRaisedButton(
width: 200,
height: 50.0,
margin: const EdgeInsets.symmetric(horizontal: 50),
color: Colors.teal.shade500,
borderRadius: BorderRadius.circular(10),
text: "LOGIN",
textColor: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold,
function: () {}
// {
// _formKey.currentState?.save();
// if(_formKey.currentState?.validate() !=null){
// controller.signInWithEmailAndPassword();
// }
// },
),
SizedBox(
height: 10,
),
],
),
),
),
),
))
],
),
),
);
}
}
The issue is here, you are declaring variables inside build. Therefore, variables get reset to default value on every build. Means setState.
Declare variables outside the build method.
class _LoginViewState extends State<LoginView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _dropdownvalue = "Global admin";
List<String> _items = <String>["Global admin", "Institution admin"];
#override
Widget build(BuildContext context) {
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
return Scaffold(
More about StatefulWidget.

Can i Select Multiple Accounts in a Banking app and pay them different amounts at the same time in flutter?

import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:money_formatter/money_formatter.dart';
import 'package:shukela_app/api/banking_app_api.dart';
import 'package:shukela_app/screens/stokvel_detail.dart';
import 'package:shukela_app/screens/stokvels.dart';
import 'package:shukela_app/utils/constants.dart';
import 'package:shukela_app/utils/global_variables.dart';
import 'package:sizer/sizer.dart';
import 'package:shukela_app/model/bankingapp_model.dart';
import '../utils/user_preferences.dart';
class PayMultipleStokvelScreen extends StatefulWidget {
const PayMultipleStokvelScreen({Key? key}) : super(key: key);
#override
State<PayMultipleStokvelScreen> createState() =>
_PayMultipleStokvelScreenState();
}
TextEditingController txtSearch = TextEditingController();
TextEditingController txtAmount = TextEditingController();
class _PayMultipleStokvelScreenState extends State<PayMultipleStokvelScreen> {
String? selectedType;
bool hasText = false;
String buttonText = "PAY NOW";
bool isLoading = false;
Widget? showHideIcon() {
if (hasText) {
return IconButton(
icon: const Icon(
Icons.clear,
color: AppColors.primaryBlue,
),
onPressed: () {
txtSearch.clear();
setState(() {
hasText = false;
});
},
);
} else {
return null;
}
}
// void _showMultiSelectDialog(BuildContext context) async {
// await showDialog(
// context: context,
// builder: (ctx) {
// return MultiSelectDialog(
// items: _animals.map((e) => MultiSelectItem(e, e)).toList(),
// initialValue: _selectedAnimals,
// onConfirm: (values) {...},
// );
// },
// );
// }
double? balance;
final _formKey = GlobalKey<FormState>();
var selectedValue;
List<StokvelDetail> selectedStokvel = [];
#override
void initState() {
super.initState();
balance = double.parse(UserPreferences.getBalance() ?? '');
}
mf() {
MoneyFormatter mf = MoneyFormatter(amount: balance!);
return mf;
}
StokvelListState currentState = StokvelListState.showAllListState;
#override
Widget build(BuildContext context) => KeyboardDismisser(
gestures: const [GestureType.onTap],
child: SafeArea(
child: Scaffold(
backgroundColor: AppColors.secondaryColor,
appBar: AppBar(
backgroundColor: AppColors.secondaryColor,
elevation: 0,
title: const Text('Pay Multiple Stokvel',
style: screenTitleTextStyle),
leading: IconButton(
icon: const Icon(
Icons.arrow_back_ios,
color: AppColors.primaryBlue,
),
onPressed: () => Navigator.pop(context),
),
),
body: Form(
key: _formKey,
child: Column(
children: [
SizedBox(height: 5.h),
Container(
height: 6.h,
width: 98.w,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TypeAheadFormField<Stokvel?>(
debounceDuration: const Duration(milliseconds: 500),
hideSuggestionsOnKeyboardHide: false,
suggestionsBoxDecoration: const SuggestionsBoxDecoration(
constraints: BoxConstraints(maxHeight: 450),
color: AppColors.secondaryColor,
borderRadius: BorderRadius.all(Radius.circular(10))),
textFieldConfiguration: TextFieldConfiguration(
style: const TextStyle(
color: AppColors.primaryBlue,
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
controller: txtSearch,
onChanged: (value) {
setState(() {
hasText = true;
});
},
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.search,
color: AppColors.primaryBlue,
),
suffixIcon: showHideIcon(),
hintText: 'Search Stokvel',
border: const OutlineInputBorder(
borderSide:
BorderSide(color: AppColors.primaryBlue),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide:
const BorderSide(color: AppColors.primaryBlue),
),
),
),
validator: (val) {
if (val!.isEmpty) {
return "Please select stokvel";
}
return null;
},
suggestionsCallback: BankingAppApi.getStokvelSuggestions,
itemBuilder: (context, Stokvel? suggestion) {
final stokvel = suggestion!;
//
return ListTile(
trailing: SizedBox(
height: 20.0,
width: 20.0,
child: Container(
color: AppColors.primaryBlue,
),
),
title: Text(
stokvel.stokvelName!,
style: const TextStyle(
fontFamily: Fonts.primaryFont,
fontWeight: FontWeight.bold,
color: AppColors.primaryBlue,
),
),
subtitle: Text(
stokvel.stokvelType!,
style: const TextStyle(
fontFamily: Fonts.primaryFont,
fontWeight: FontWeight.bold,
color: AppColors.primaryBlue),
),
);
},
noItemsFoundBuilder: (context) => const SizedBox(
height: 60,
child: Center(
child: Text(
'No Stokvel Found.',
style: TextStyle(fontSize: 20),
),
),
),
onSuggestionSelected: (Stokvel? suggestion) {
final stokvel = suggestion!;
setState(() {
txtSearch.text = stokvel.stokvelName!;
hasText = true;
});
stokvelID = stokvel.stokvelID;
memberID = stokvel.memberID;
},
),
),
SizedBox(
height: 4.h,
),
SizedBox(height: 3.h),
Container(
height: 6.h,
width: 98.w,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TextFormField(
controller: txtAmount,
decoration: const InputDecoration(
labelStyle: TextStyle(
color: AppColors.primaryBlue,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
suffixText: "ZAR",
border: OutlineInputBorder(
borderSide:
BorderSide(color: AppColors.primaryBlue)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
labelText: 'Amount',
contentPadding:
EdgeInsets.only(left: 20, right: 15, bottom: 8),
),
keyboardType: TextInputType.number,
style: const TextStyle(
fontSize: 20.0,
fontFamily: Fonts.primaryFont,
color: AppColors.primaryBlue),
validator: (val) {
if (val!.isEmpty) {
return "Please enter amount";
}
return null;
},
),
),
SizedBox(height: 3.h),
Container(
height: 6.h,
width: 98.w,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TextField(
readOnly: true,
style: const TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "Wallet Balance : R " + mf().output.nonSymbol,
border: const OutlineInputBorder(
borderSide:
BorderSide(color: AppColors.primaryBlue),
borderRadius: BorderRadius.horizontal()),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
),
),
),
SizedBox(height: 3.h),
Container(
height: 50,
width: 400,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.white)),
child: isLoading
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
CircularProgressIndicator(
color: AppColors.secondaryColor),
SizedBox(width: 24),
Text(
"Submitting payment...",
style: TextStyle(
color: AppColors.secondaryColor),
)
],
)
: Text(
buttonText,
style: const TextStyle(
fontFamily: Fonts.primaryFont,
fontWeight: FontWeight.bold,
color: AppColors.primaryBlue),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
if (double.parse(txtAmount.text) <= balance!) {
setState(
() {
isLoading = true;
},
);
stokvelTransact.amount =
double.parse(txtAmount.text);
stokvelTransact.memberID = memberID;
stokvelTransact.stokvelID = stokvelID;
stokvelTransact.transactionTypeID = 1;
api
.stokvelDeposit(stokvelTransact,
"StokvelTransaction/StokvelTransact")
.then(
(value) => setState(
() {
Future.delayed(
const Duration(seconds: 3));
isLoading = false;
if (value == "Success") {
ScaffoldMessenger.of(context)
.showSnackBar(snackBar(
content:
'Payment made succesfully',
duration: 5));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(snackBar(
content:
'We have encountered technical problems, Try again later',
duration: 5));
}
},
),
)
.catchError(
(err) {
setState(() {
isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
content: err.toString(), duration: 7));
},
);
} else {
ScaffoldMessenger.of(context).showSnackBar(snackBar(
content: "Insuficient funds!", duration: 7));
}
}
},
),
),
],
),
),
),
),
);
}
The above code is for the single page that I want to achieve this
This is what I want to achieve or any suggestions are accepted, I want to mark the Group of Stokvels I want to pay and pay them different accounts I don't know if it's possible please I'm new in flutter it a project I have to get it done as soon as possible this is the source code for my whole payment page, for now, I'm able to pay a single Stokvel Group but I want to select multiple
I highly suggest starting with formatting of the current code - its hard to read and with that hard to maintain.
The simple idea would be:
use List<StokvelDetail> selectedStokvel = []; you created to add the Stokvel's in every time you select Stokvel in SearchBar
Add Map<int,double> amounts = {}; <StokvelId, amount> to keep track of the amount you want to send to each Stokvel
Based on selectedStokvel build multiple 'amount window' widgets
Before submit verify walletBalance >= amounts.values.reduce((a,b)=> a + b)
For each selectedStokvel call api.stokvelDeposit(stokvelTransact, ...
I would primarly focus on spliting this code to multiple Widget classes, there are many schools but I like to have around 150 lines of code in single file at most.
From what i see your file can be easily split into:
Column(
children: [
SizedBox(),
SearchBar(),
SizedBox(),
AmountInput(), --> StokvelAmountInput() for each selectedStokvel
SizedBox(),
WalletBalance(),
SizedBox(),
SubmitButton(),
]),
```

i'm trying to get the placename using the geocoding api but it doesn't work it says placename is null

i created seperated files for the geolocator called helping methods and address class for placename and address attributes and included them in the search page this is the given error
======== Exception caught by widgets library =======================================================
The getter 'placename' was called on null.
Receiver: null
Tried calling: placename
this is the search page file
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:reviver_app/dataproviders/appdata.dart';
import 'package:reviver_app/globalvariables.dart';
import 'package:reviver_app/helpers/requesthelper.dart';
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
var pickupController = TextEditingController();
var destinationController = TextEditingController();
var focusDestination = FocusNode();
bool focused = false;
void setFocus() {
if (!focused) {
FocusScope.of(context).requestFocus(focusDestination);
focused = true;
}
}
void searchPlace(String placeName) async {
if (placeName.length >1){
String url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$placeName+Amphitheatre&key=$mapKey&sessiontoken=123456789';
var response = await RequestHelper.getRequest(url);
if (response == 'failed'){
return;
}
print(response);
}
}
#override
Widget build(BuildContext context) {
setFocus();
String address = Provider.of<AppData>(context).pickupaddress.placename ?? ""; this is the error which is null
pickupController.text = address;
return Scaffold(
body: Column(
children: <Widget>[
Container(
height: 210,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.redAccent,
blurRadius: 5.0,
spreadRadius: 0.5,
offset: Offset(
0.7,
0.7,
),
),
]
),
child: Padding(
padding: EdgeInsets.only(left: 24, top: 48, right:24, bottom: 20 ),
child: Column(
children: <Widget> [
SizedBox(height: 5),
Stack(
children: <Widget>[
GestureDetector(
onTap: (){
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back, color: Colors.redAccent,)
),
Center(
child: Text('Set Booking', style:
TextStyle(fontSize: 20, fontFamily: 'Brand-Bold'),
),
),
],
),
SizedBox(height: 18,),
Row(
children: <Widget> [
Image.asset('images/pickicon.png', height:16, width: 16 ,),
SizedBox(width: 18,),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: EdgeInsets.all(2.0),
child: TextField(
controller: pickupController,
decoration: InputDecoration(
hintText: 'Your Location',
fillColor: Colors.redAccent,
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 10, top: 0, bottom: 0)
),
),
),
),
),
],
),
SizedBox(height: 10,),
Row(
children: <Widget> [
Image.asset('images/desticon.png', height:16, width: 16 ,),
SizedBox(width: 18,),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: EdgeInsets.all(2.0),
child: TextField(
//destination which will be removed
onChanged: (value){
searchPlace(value);
},
focusNode: focusDestination ,
controller: destinationController,
decoration: InputDecoration(
hintText: 'this will be removed ',
fillColor: Colors.redAccent,
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 10, top: 0, bottom: 0)
),
),
),
),
),
],
),
],
),
),
)
],
),
);
}
}
```
this is where I included the geolocotor URL
import 'package:connectivity/connectivity.dart';
import 'package:geolocator/geolocator.dart';
import 'package:reviver_app/datamodels/address.dart';
import 'package:reviver_app/dataproviders/appdata.dart';
import 'package:reviver_app/globalvariables.dart';
import 'package:reviver_app/helpers/requesthelper.dart';
import 'package:provider/provider.dart';
class HelperMethods {
static Future<String> findCordinateAddress(Position position, context) async {
String placeaddress = '';
var connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult != ConnectivityResult.mobile &&
connectivityResult != ConnectivityResult.wifi) {
return placeaddress;
}
String url =
'https://maps.googleapis.com/maps/api/geocode/json?latlng=${position.latitude},${position.longitude}&key=$mapKey';
var response = await RequestHelper.getRequest(url);
if (response == 'failed') {
placeaddress = response['results'][0]['formatted_address'];
Address pickupaddress = new Address();
pickupaddress.longitude = position.longitude;
pickupaddress.latitude = position.latitude;
pickupaddress.placename = placeaddress;
Provider.of<AppData>(context, listen: false)
.updatePickupAddress(pickupaddress);
}
return placeaddress;
}
}
```
this is the app data file
import 'package:flutter/cupertino.dart';
import 'package:reviver_app/datamodels/address.dart';
class AppData extends ChangeNotifier{
Address pickupaddress;
void updatePickupAddress(Address pickup){
pickupaddress = pickup;
notifyListeners();
}
}
this is the address class from where I added place name
class Address {
String placename;
double latitude;
double longitude;
String placeId;
String placeformattedaddress;
Address({
this.placeId,
this.latitude,
this.placename,
this.longitude,
this.placeformattedaddress,
});
}
In your searchpage, update the url String of the searchPlace() method.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:reviver_app/dataproviders/appdata.dart';
import 'package:reviver_app/globalvariables.dart';
import 'package:reviver_app/helpers/requesthelper.dart';
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
var pickupController = TextEditingController();
var destinationController = TextEditingController();
var focusDestination = FocusNode();
bool focused = false;
void setFocus() {
if (!focused) {
FocusScope.of(context).requestFocus(focusDestination);
focused = true;
}
}
void searchPlace(String placeName) async {
if (placeName.length >1){
String url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$placeName&key=$mapKey&sessiontoken=123456789';
var response = await RequestHelper.getRequest(url);
if (response == 'failed'){
return;
}
print(response);
}
}
#override
Widget build(BuildContext context) {
setFocus();
String address = Provider.of<AppData>(context).pickupaddress.placename ?? ""; this is the error which is null
pickupController.text = address;
return Scaffold(
body: Column(
children: <Widget>[
Container(
height: 210,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.redAccent,
blurRadius: 5.0,
spreadRadius: 0.5,
offset: Offset(
0.7,
0.7,
),
),
]
),
child: Padding(
padding: EdgeInsets.only(left: 24, top: 48, right:24, bottom: 20 ),
child: Column(
children: <Widget> [
SizedBox(height: 5),
Stack(
children: <Widget>[
GestureDetector(
onTap: (){
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back, color: Colors.redAccent,)
),
Center(
child: Text('Set Booking', style:
TextStyle(fontSize: 20, fontFamily: 'Brand-Bold'),
),
),
],
),
SizedBox(height: 18,),
Row(
children: <Widget> [
Image.asset('images/pickicon.png', height:16, width: 16 ,),
SizedBox(width: 18,),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: EdgeInsets.all(2.0),
child: TextField(
controller: pickupController,
decoration: InputDecoration(
hintText: 'Your Location',
fillColor: Colors.redAccent,
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 10, top: 0, bottom: 0)
),
),
),
),
),
],
),
SizedBox(height: 10,),
Row(
children: <Widget> [
Image.asset('images/desticon.png', height:16, width: 16 ,),
SizedBox(width: 18,),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: EdgeInsets.all(2.0),
child: TextField(
onChanged: (value){
searchPlace(value);
},
focusNode: focusDestination ,
controller: destinationController,
decoration: InputDecoration(
hintText: 'this will be removed ',
fillColor: Colors.redAccent,
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 10, top: 0, bottom: 0)
),
),
),
),
),
],
),
],
),
),
)
],
),
);
}
}
You have used a placeholder for the placeName, hence you don't have to add the +Amphitheatre as it is considered as a raw string.