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.
Related
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!;
});
}
}
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.
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
}]
Exception has occurred.
FlutterError setState() or markNeedsBuild() called during build.
This TextFormField widget cannot be marked as needing to build because the framework is already in the process of building widgets.
A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building.
This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
TextFormField
The widget which was currently being built when the offending call was made was:
Builder)
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:project_1_money_management/Screens/Home/home_screen.dart';
import 'package:project_1_money_management/db/transaction_db.dart';
import 'package:project_1_money_management/models/category_model.dart';
import 'package:project_1_money_management/update/update_category.dart';
import '../Screens/Adding_items/Widgets/date_picker.dart';
import '../db/category_db.dart';
import '../models/transactions_model.dart';
final purposecontroller = TextEditingController();
final amountcontroller = TextEditingController();
class UpdateScreen extends StatefulWidget {
final TransactionModel value;
const UpdateScreen({Key? key, required this.value}) : super(key: key);
#override
State<UpdateScreen> createState() => _UpdateScreenState();
}
class _UpdateScreenState extends State<UpdateScreen> {
CategoryType? type;
DateTime? _date;
CategoryModel? cat;
#override
// ignore: must_call_super
void initState() {
CategoryDB().refreshUI();
TransactionDB.instance.refresh();
super.initState();
amountcontroller.text = widget.value.amount.toString();
purposecontroller.text = widget.value.purpose;
_date = widget.value.date;
cat = widget.value.category;
type = widget.value.type;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromARGB(255, 35, 32, 32),
body: SafeArea(
child: ListView(
children: [
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Add Transactions',
style: GoogleFonts.inconsolata(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
const SizedBox(
height: 40,
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8),
child: Card(
color: const Color.fromARGB(48, 175, 171, 171),
elevation: 60,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
child: Padding(
padding: const EdgeInsets.only(top: 40.0, bottom: 40),
child: Column(
children: [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
primary: const Color.fromARGB(255, 255, 251,
253), //change background color of button
onPrimary: const Color.fromARGB(
255, 56, 120, 204), //change text color of button
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
elevation: 15.0,
),
onPressed: () {
selectDates(context);
},
icon: const Icon(Icons.calendar_month),
label: Text(
'${_date!.day}/${_date!.month}/${_date!.year}',
),
),
const SizedBox(
height: 10,
),
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10),
child: Row(
children: [
CateogryUpdate(cats: cat!, types: type!),
],
)),
Form(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: amountcontroller,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: purposecontroller,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 40.0, horizontal: 10.0),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),
],
)),
ClipRRect(
borderRadius: BorderRadius.circular(19),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color.fromARGB(255, 81, 185, 67),
Color.fromARGB(255, 32, 188, 32),
Color.fromARGB(255, 52, 181, 32),
],
),
),
),
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.only(),
primary:
const Color.fromARGB(255, 247, 247, 247),
textStyle: GoogleFonts.inconsolata(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
onPressed: () async {
await update(
widget.value.id!,
amountcontroller.text,
);
},
child: const Text(' Update '),
),
],
),
),
const SizedBox(
height: 14,
),
],
),
),
),
),
],
),
),
);
}
selectDates(BuildContext context) async {
selected = await showDatePicker(
context: context,
initialDate: _date!,
firstDate: DateTime(2021),
lastDate: DateTime.now(),
);
if (selected != null && selected != _date!) {
setState(() {
_date = selected!;
});
}
}
update(String id, String amt) async {
final _update = TransactionModel(
amount: double.tryParse(amt)!,
purpose: purposecontroller.text,
category: cat!,
date: _date!,
type: type,
id: id,
);
await TransactionDB.instance.updateTransact(_update);
Navigator.of(context)
.push(MaterialPageRoute(builder: (route) => const ScreenHome()));
}
}
Try below code before seState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (selected != null && selected != _date!) {
setState(() {
_date = selected!;
});
}
});
I'm trying to make a profile page where user can upload their profile picture. I have done all the required method but this error pops up:
Unhandled Exception: MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods)
a tab should pop up when I press on the IconButton asking for permission, but in here nothing happens just the above error pops up.
This is the code I did:
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
class EditProfilePage extends StatefulWidget {
#override
_EditProfilePageState createState() => _EditProfilePageState();
}
class _EditProfilePageState extends State<EditProfilePage> {
bool showPassword = false;
String imageUrl;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
elevation: 1,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.orangeAccent,
),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Container(
padding: EdgeInsets.only(left: 16, top: 25, right: 16),
child: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: ListView(
children: [
Text(
"Edit Profile",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
SizedBox(
height: 15,
),
Center(
child: Stack(
children: [
Container(
child: (imageUrl != null)
? Image.network(imageUrl)
: Image.asset('assets/background.jpg'),
width: 130,
height: 130,
decoration: BoxDecoration(
border: Border.all(
width: 4,
color: Theme.of(context).scaffoldBackgroundColor),
boxShadow: [
BoxShadow(
spreadRadius: 2,
blurRadius: 10,
color: Colors.black.withOpacity(0.1),
offset: Offset(0, 10))
],
shape: BoxShape.circle,
),
),
Positioned(
bottom: 0,
right: 0,
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: 4,
color: Theme.of(context).scaffoldBackgroundColor,
),
color: Colors.orangeAccent,
),
child: IconButton(
icon: Icon(Icons.edit),
color: Colors.white,
onPressed: () => uploadImage(),
),
)),
],
),
),
SizedBox(
height: 35,
),
buildTextField("Full Name", "Yeap Wei Kang", false),
buildTextField("E-mail", "jonywk1103#gmail.com", false),
buildTextField("Password", "********", true),
buildTextField("Location", "Ipoh, Perak", false),
SizedBox(
height: 35,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
OutlineButton(
padding: EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
onPressed: () {
Navigator.pop(context);
},
child: Text("CANCEL",
style: TextStyle(
fontSize: 14,
letterSpacing: 2.2,
color: Colors.black)),
),
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
color: Colors.orangeAccent,
padding: EdgeInsets.symmetric(horizontal: 50),
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
child: Text(
"SAVE",
style: TextStyle(
fontSize: 14,
letterSpacing: 2.2,
color: Colors.white),
),
)
],
)
],
),
),
),
);
}
Widget buildTextField(
String labelText, String placeholder, bool isPasswordTextField) {
return Padding(
padding: const EdgeInsets.only(bottom: 35.0),
child: TextField(
obscureText: isPasswordTextField ? showPassword : false,
decoration: InputDecoration(
suffixIcon: isPasswordTextField
? IconButton(
onPressed: () {
setState(() {
showPassword = !showPassword;
});
},
icon: Icon(
Icons.remove_red_eye,
color: Colors.grey,
),
)
: null,
contentPadding: EdgeInsets.only(bottom: 3),
labelText: labelText,
floatingLabelBehavior: FloatingLabelBehavior.always,
hintText: placeholder,
hintStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black,
)),
),
);
}
uploadImage() async {
final _storage = FirebaseStorage.instance;
final _picker = ImagePicker();
PickedFile image;
//Check Permissions
await Permission.photos.request();
var permissionStatus = await Permission.photos.status;
if (permissionStatus.isGranted){
//Select Image
image = await _picker.getImage(source: ImageSource.gallery);
var file = File(image.path);
if (image != null){
//Upload to Firebase
var snapshot = await _storage.ref()
.child('folderName/imageName')
.putFile(file);
var downloadUrl = await snapshot.ref.getDownloadURL();
setState(() {
imageUrl = downloadUrl;
});
} else {
print('No Path Received');
}
} else {
print('Grant Permissions and try again');
}
}
}
Can anyone tell me whats wrong in my coding?
stop the running app, go to terminal > flutter clean > then build the app again