Related
My app asks permission to access the photo library, camera, microphone, and location on the CreatePostScreen(). Whenever a user selects any option for those permission prompts, the PageView resets and goes to the first tab for some reason. None of the code in create_post_screen.dart calls for this and it only happens after permissions are set. I cannot figure out why this is happening.
create_post_screen.dart:
class CreatePostScreen extends StatefulWidget {
const CreatePostScreen({Key? key}) : super(key: key);
#override
State<CreatePostScreen> createState() => _CreatePostScreenState();
}
class _CreatePostScreenState extends State<CreatePostScreen> {
final _locationNameFormKey = GlobalKey<FormState>();
final _locationNameController = TextEditingController();
bool _isLoading = false;
List<String> originalFiles = [];
List<File> imageFiles = [];
void selectImages() async {
final result = await showModalActionSheet(
context: context,
title: 'Select Image Source',
actions: [
const SheetAction(label: 'Existing Images', key: 'existing'),
const SheetAction(label: 'New Image', key: 'new')
]);
if (result == 'new' && imageFiles.length < 4) {
newImage();
} else if (result == 'existing' && imageFiles.length < 4) {
existingImages();
}
}
void newImage() async {
setState(() {
_isLoading = true;
});
final XFile? image =
await ImagePicker().pickImage(source: ImageSource.camera);
if (image == null) return;
cropImages([image.path]);
}
void existingImages() async {
setState(() {
_isLoading = true;
});
final List<XFile>? selectedImages = await ImagePicker().pickMultiImage();
if (selectedImages == null) return;
int ableToAdd = 4 - imageFiles.length;
if (selectedImages.length > ableToAdd) {
List<XFile>? filesToAdd = selectedImages.sublist(0, ableToAdd);
List<String> imagePaths = [];
for (var selectedImage in filesToAdd) {
imagePaths.add(selectedImage.path);
}
cropImages(imagePaths);
} else {
List<String> imagePaths = [];
for (var selectedImage in selectedImages) {
imagePaths.add(selectedImage.path);
}
cropImages(imagePaths);
}
}
void cropImages(List<String> paths) async {
for (var path in paths) {
originalFiles.add(path);
final ImageProperties properties =
await FlutterNativeImage.getImageProperties(path);
final int width = properties.width!;
final int height = properties.height!;
int imageSize = width < height ? width : height;
int x = 0;
int y = 0;
File imageFile =
await FlutterNativeImage.cropImage(path, x, y, imageSize, imageSize);
setState(() {
int index = originalFiles.indexOf(path);
imageFiles.insert(index, imageFile);
_isLoading = false;
});
}
}
void customCrop(int index) async {
final fileToCrop = originalFiles[index];
final croppedFile = await ImageCropper().cropImage(
sourcePath: fileToCrop,
aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1),
aspectRatioPresets: [
CropAspectRatioPreset.square
],
uiSettings: [
AndroidUiSettings(toolbarTitle: 'Crop Image'),
IOSUiSettings(title: "Crop Image", showCancelConfirmationDialog: true)
]);
setState(() {
imageFiles[index] = File(croppedFile!.path);
});
}
Position? position;
void _determinePosition() async {
LocationPermission permission;
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
Position positionResult = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.lowest);
setState(() {
position = positionResult;
});
}
pkg.User user = Supabase.auth.currentUser!;
final postId = DateTime.now().millisecondsSinceEpoch.toString();
void uploadPost() async {
if (_locationNameFormKey.currentState!.validate()) {
_locationNameFormKey.currentState!.save();
setState(() {
_isLoading = true;
});
String name = _locationNameController.text;
Location location = Location(
position!.latitude,
position!.longitude,
name,
);
List<String> uploadedUrls = [];
for (var file in imageFiles) {
String fileName = '${DateTime.now().millisecondsSinceEpoch}_post.png';
Supabase.storage
.from('posts')
.upload('${user.id}/$fileName', supaFile.File(file.path));
String url = Supabase.storage.from('posts').getPublicUrl('${user.id}/$fileName');
setState(() {
uploadedUrls.add(url);
});
if (imageFiles.length == uploadedUrls.length) {
Post post = Post(
postId,
uploadedUrls,
user.id,
// profile,
location,
DateTime.now().millisecondsSinceEpoch,
);
print(post);
try {
Supabase.db
.from('posts')
.insert(post.toJson())
.then((value) {
setState(() {
imageFiles = [];
originalFiles = [];
_locationNameController.clear();
position = null;
_isLoading = false;
});
});
} catch (error) {
setState(() {
_isLoading = false;
});
print(error);
}
}
}
}
}
Widget imageItem(int index) {
File imageFile = imageFiles[index];
return SizedBox(
height: 200,
width: 200,
child: Card(
clipBehavior: Clip.hardEdge,
child: Stack(
children: [
Image.file(imageFile, fit: BoxFit.fill),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(5),
child: Row(
children: [
SizedBox(
height: 35,
width: 35,
child: FittedBox(
child: FloatingActionButton(
onPressed: () {
setState(() {
customCrop(index);
});
},
child: const Icon(Icons.edit_outlined),
),
),
),
const SizedBox(width: 5),
SizedBox(
height: 35,
width: 35,
child: FittedBox(
child: FloatingActionButton(
onPressed: () {
setState(() {
imageFiles.removeAt(index);
originalFiles.removeAt(index);
});
},
child: const Icon(Icons.delete_forever_sharp),
),
),
),
],
),
),
)
],
),
),
);
}
Widget picker() {
return imageFiles.isEmpty
? GestureDetector(
onTap: () {
selectImages();
},
child: Center(
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFd3d8e9),
borderRadius: BorderRadius.circular(10),
),
height: 150,
width: 300,
child: const Center(
child: Text(
'Press to add Images - Required',
style: TextStyle(color: Colors.red),
),
),
),
),
)
: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFd3d8e9),
borderRadius: BorderRadius.circular(10),
),
child: DragAndDropGridView(
physics: const ScrollPhysics(),
itemCount: imageFiles.length,
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
return imageItem(index);
},
onWillAccept: () {
return true;
},
onReorder: (oldIndex, newIndex) {
final temp = imageFiles[newIndex];
imageFiles[newIndex] = imageFiles[oldIndex];
imageFiles[oldIndex] = temp;
setState(() {});
},
),
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
resizeToAvoidBottomInset: true,
appBar: FloatingAppBar(
leading: const SizedBox(),
title: const Text('Create Post',
style: TextStyle(color: Color(0xFF7157A0), fontSize: 20)),
actions: [
if (imageFiles.isEmpty || position == null)
const Icon(Icons.send_outlined, color: Colors.grey),
if (imageFiles.isNotEmpty && position != null)
IconButton(
onPressed: () {
uploadPost();
},
icon:
const Icon(Icons.send_outlined, color: Color(0xFF7157A0)),
),
],
),
body: SingleChildScrollView(
child: Column(
children: [
picker(),
Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _locationNameFormKey,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 80,
width: MediaQuery.of(context).size.width - 40,
child: TextFormField(
controller: _locationNameController,
textInputAction: TextInputAction.done,
keyboardType: TextInputType.name,
decoration: const InputDecoration(
suffix: Icon(Icons.edit_location_outlined,
color: Color(0xFF6C74B4)),
labelText: "Location Name",
floatingLabelStyle:
TextStyle(color: Color(0xFF697CB4)),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(8)),
borderSide: BorderSide(
color: Color(0xFF6B6FAB), width: 1)),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(8)),
borderSide: BorderSide(
color: Color(0xFF697CB4), width: 1)),
),
validator: (name) {
if (name == null) {
return 'This cannot be left empty';
}
if (name.length < 4 || name.length > 15) {
return 'Must be 4-15 characters';
}
return null;
},
),
),
],
),
),
),
GestureDetector(
onTap: () {
_determinePosition();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {
_determinePosition();
},
child: const Icon(Icons.location_on_outlined),
),
const SizedBox(width: 10),
if (position == null)
const Text(
'Press to add location - Required',
style: TextStyle(color: Colors.red),
),
if (position != null)
Text(
'Current location: ${position!.latitude.round()}, ${position!.longitude.round()}')
],
),
),
],
),
),
),
if (_isLoading)
const Opacity(
opacity: 0.8,
child: ModalBarrier(dismissible: false, color: Colors.black),
),
if (_isLoading)
const Center(
child: CircularProgressIndicator(color: Color(0xFFb1bbd8)),
),
],
);
}
}
I appreciate any help with this.
Keyboard triggers the api calling while closing and opening
I have search bar I didn't pass anything inside the search bar but when I click the search bar The api call will run.
I don't know why that thing was happen I tried several ways but It won't work
Even Inside the keyboard I choose the one hand keyboard that time also api will run
Also tried the Focusnode also.
class PopupNaviagator extends StatefulWidget {
var body;
String leadsName = "";
Map<String, dynamic> listValues;
PopupNaviagator(this.listValues);
var data;
String pageData = "";
double totalPageCount = 0;
int pageIncrementer = 1;
#override
_PopupNavigatorState createState() => _PopupNavigatorState();
}
class _PopupNavigatorState extends State<PopupNaviagator> {
Utils util = new Utils();
bool isSearching = false;
#override
void initState() {
super.initState();
}
String searchingText = "";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
titleSpacing: 0,
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: util.getColors(1001),
stops: [0.1, 5.0],
),
),
),
title: !isSearching
? Text("Select Search Type")
: TextField(
autofocus: true,
autocorrect: true,
onChanged: (value) {
searchingText = value;
},
cursorColor: Colors.white,
onSubmitted: (value) {
searchingText = value;
campaignAPI(
widget.listValues["colname"].toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
},
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: "Search ",
hintStyle: TextStyle(color: Colors.white)),
),
actions: <Widget>[
isSearching
? IconButton(
icon: Icon(Icons.cancel),
onPressed: () {
setState(() {
searchingText = "";
this.isSearching = false;
campaignAPI(
widget.listValues["colname"].toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
/* filteredCountries = countries;*/
});
},
)
: IconButton(
icon: Icon(Icons.search),
onPressed: () {
setState(() {
this.isSearching = true;
});
},
)
],
),
body: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5))),
child: Scaffold(
body: FutureBuilder(
future: campaignAPI(widget.listValues["colname"].toString(), "1",
searchingText, 0),
builder: (context, snapshot) {
if (snapshot.hasData) {
var body;
if (widget.data == null) {
body = snapshot.data;
} else {
body = widget.data;
}
final records = body["list_records"];
widget.pageData = body["PageValues"];
widget.totalPageCount =
(body["TotalRecordCount"] / 5).toDouble();
return Scaffold(
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (records.length != 0) ...[
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(
top: 0,
bottom: 0,
),
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: records.length,
itemBuilder: (context, index) {
Map<String, dynamic> pickerValues =
records[index];
String titleName =
pickerValues["viewcol_value"]
.toString();
return Container(
margin: const EdgeInsets.all(5.00),
decoration: new BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.grey, width: 1.0),
borderRadius: new BorderRadius.all(
Radius.circular(3.0)),
),
child: FlatButton(
padding: EdgeInsets.all(8.0),
onPressed: () {
setState(() {
List<String> strArr = [
titleName,
pickerValues["rec_id"].toString(),
widget.listValues["colname"]
];
Navigator.pop(context, strArr);
});
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(titleName.toString()),
Icon(
Icons.check_circle_outlined,
color: Colors.grey,
),
]),
),
);
}),
),
] else ...[
Container(
height: MediaQuery.of(context).size.height / 1.4,
child: Center(
child: Container(
padding: EdgeInsets.all(65),
child: Text(
"No Record Found",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.black),
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
width: 2,
),
)),
),
),
],
if (records.length != 0) ...[
Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
if (widget.pageIncrementer > 1) {
widget.pageIncrementer--;
campaignAPI(
widget.listValues["colname"]
.toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
setState(() {});
} else {
util.showToast("No records to show");
}
},
child: Icon(Icons.arrow_left_rounded,
size: 50, color: Colors.white),
),
Text(
widget.pageData,
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
InkWell(
onTap: () {
if (widget.totalPageCount > 1 &&
widget.totalPageCount >=
widget.pageIncrementer) {
widget.pageIncrementer++;
campaignAPI(
widget.listValues["colname"]
.toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
} else {
util.showToast("No reocrds to show");
}
},
child: Icon(Icons.arrow_right_rounded,
size: 50, color: Colors.white),
),
],
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: util.getColors(1001),
stops: [0.1, 5.0],
),
),
)
]
],
),
),
);
} else if (snapshot.hasError) {
return Text('${snapshot.error.toString()}');
}
return Center(
child: CircularProgressIndicator(),
);
},
),
),
));
}
campaignAPI(
String field_col, String page_no, String searchValue, int flag) async {
Utils util = new Utils();
SharedPreferences prefs = await SharedPreferences.getInstance();
final accessKey = prefs.getString('access_key');
final companyName = prefs.getString('company_name');
Object requestParam = {
"companyname": companyName,
"access_key": accessKey.toString(),
"field_col": field_col,
"page_no": page_no,
"searchValue": searchValue,
};
print(requestParam.toString());
APIS apis = new APIS();
Uri url = Uri.parse(apis.searchquickcreate);
util.prints(url);
util.prints(requestParam);
final response = await http.post(url, body: requestParam);
if (response.statusCode == 200) {
final body = json.decode(response.body);
print(body);
String status = body["status"];
if (status != "failed") {
if (flag == 1) {
setState(() {
widget.data = body;
});
}
return body;
} else {
util.logOut(context);
return body;
}
} else {
Navigator.pop(context);
util.showToast("Server Error !");
throw Exception("Server Error !");
}
}
}
I am trying to build a new widget every time a button is pressed.
I am using object of Global key to change the current state of Form as other local keys doesn't provide me the capability to change the state of FormBuilder
final _formKey = GlobalKey<FormBuilderState>();
Problem is when I try to create object of GlobalKey(_formKey) under listTile widget that I 'm trying to build on runtime, form builderr text fields don't work i.e appear and disappear instantly! But when create _formKey oustside the listTile widget under stateful widget, many other errors appears
i.e setState() called after dispose(), Global key used for multiple widgets etc.
Should I use here local keys i.e value,object or unique key? But they aren't providing me to change the current state of form builder!
Check my code:
class _addMenuState extends State<addMenu> {
var _price = TextEditingController();
var _itemName = TextEditingController();
var _desc = TextEditingController();
File _image;
String itemImageUrl;
List<menu> items = [];
final _formKey = GlobalKey<FormBuilderState>();
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
print('Image Path $_image');
});
}
Future getImageFromCamera() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = image;
print('Image Path $_image');
});
}
Future uploadItemOfShop(BuildContext context) async {
FirebaseStorage storage = FirebaseStorage.instance;
Reference ref = storage.ref().child("${this.widget.rr.name}'s ${_itemName.text} Price ${_price.text}" + DateTime.now().toString());
if(_image.toString()==''){
Flushbar(
title: "Menu Item Image is empty",
message: "Please Add some Image first",
backgroundColor: Colors.red,
boxShadows: [BoxShadow(color: Colors.red[800], offset: Offset(0.0, 2.0), blurRadius: 3.0,)],
duration: Duration(seconds: 3),
)..show(context);
}else{
UploadTask uploadTask = ref.putFile(_image);
uploadTask.then((res) async {
itemImageUrl = await res.ref.getDownloadURL();
});
}
/* setState(() {
print("Logo uploaded");
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('Your Restaurnat Logo has Uploaded'),
duration: Duration(seconds: 3),
));
});*/
}
Widget Divido() {
return Divider(
thickness: 5,
color: Colors.black45,
height: 2,
);
}
Widget listTile(int i) {
final _formKey = GlobalKey<FormBuilderState>();
return SingleChildScrollView(
child: ListTile(
title: //Code not needed here for this question as I haven't used key in it
subtitle: FormBuilder(
key: _formKey,
child: Column(
children: [
FormBuilderTextField(
controller: _itemName,
keyboardType: TextInputType.text,
name: 'item_name',
decoration: InputDecoration(labelText: 'Enter Item name'),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
]),
),
FormBuilderTextField(
controller: _price,
name: 'price',
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Enter Price'),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
]),
),
FormBuilderTextField(
maxLength: 150,
controller: _desc,
keyboardType: TextInputType.multiline,
maxLines: null,
name: 'desc',
decoration: InputDecoration(
labelText: 'Description',
),
validator: FormBuilderValidators.compose(
[
FormBuilderValidators.required(context),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
RaisedButton(
child: Text(
"Save",
style: TextStyle(color: Colors.white, fontSize: 16),
),
color: Colors.red,
onPressed: () {
debugPrint("null");
menu item = menu(
_itemName.text, _price.text, _desc.text, itemImageUrl);
items.add(item);
setState(() {
_count = _count + 1;
});
},
),
RaisedButton(
child: Text(
"Reset",
style: TextStyle(color: Colors.white, fontSize: 16),
),
color: Colors.grey,
onPressed: () {
_formKey.currentState.reset();
},
)
],
),
Divido()
],
),
),
selectedTileColor: Colors.red.shade300,
),
);
}
int _count = 1;
bool _showAnotherWidget = false;
#override
Widget build(BuildContext context) {
List<Widget> children = List.generate(_count, (int i) => listTile(i));
return Scaffold(
appBar: AppBar(
title: Text("Add Menu for ${this.widget.rr.name} Shop"),
),
body: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: children
),
),
)
);
}
}
I have page Navigate to second page with variable (dID) with await to return same value if it has been changed ,at the second page if i did't do anything the value must return without any changes ,if i changed slider the value of (dID) must be increase by (1) ,but when i Navigate.pop the return value is same without increasing.
New update : After many test i did the problem is in the second page ,when i change the slider value i call a function to get the new value (newSavedDayId) ,and it is get it correctly but just inside the function ,after the slider change and get the new value ,it is returned to null :
newSavedDayId = Instance of 'Future<dynamic>'
second page which return value :
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../classes/viewdigree.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Days extends StatefulWidget {
#override
_DaysState createState() => _DaysState();
}
TextEditingController insertedDegree = TextEditingController();
class _DaysState extends State<Days> {
#override
Widget build(BuildContext context) {
List digrees = [];
var widthView = MediaQuery.of(context).size.width;
Map rdata = ModalRoute.of(context).settings.arguments;
var did = int.parse(rdata['dayId'].toString());
var u_id = rdata['userID'];
var m_id = rdata['courseId'];
var lang = rdata['lang'];
int w_id;
var newSavedDayId = rdata['savedDayID']; ----// received value
var username;
if (did <= 6) {
w_id = 1;
} else if (did <= 12) {
w_id = 2;
} else if (did <= 18) {
w_id = 3;
} else {
w_id = 4;
}
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
// Insert Func
send_degree(uId, actId, degree, w_id, did, m_id) async {
var sendData = {
'u_id': uId.toString(),
'act_id': actId.toString(),
'digree': degree.toString(),
'm_id': m_id.toString(),
'd_id': did.toString(),
'w_id': w_id.toString()
};
var url = 'https://srdtraining.com/api/controller/data/changedata.php';
var response = await http.post(url, body: sendData);
}
// End of Insert Func
//get user status .................. // this is the function to get new value
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
print('newSavedDayId = $newSavedDayId');----// here it is print new value with increasing correctly
}
// End get user
return FutureBuilder(
future: fetchDigrees(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
child: Center(
child: Text("Loading"),
),
),
);
} else {
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: snapshot.data[0].link,
flags: YoutubePlayerFlags(
autoPlay: false,
mute: false,
));
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, newSavedDayId);
}),
backgroundColor: Colors.pink[900],
title: Text(
'ژیان و قورئان',
style: TextStyle(fontSize: 32),
),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(
padding: EdgeInsets.fromLTRB(25, 20, 25, 20),
shrinkWrap: true,
children: <Widget>[
Text(
lang == 'k'
? snapshot.data[0].title_k
: snapshot.data[0].title_a,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 32, color: Colors.white)),
//for top margin
SizedBox(height: 20.0),
// dexription
Container(
padding: const EdgeInsets.all(15),
width: widthView,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: const Color.fromRGBO(180, 80, 80, 0.3)),
child: Text(snapshot.data[0].aya,
textAlign: TextAlign.justify,
textDirection: TextDirection.rtl,
style: TextStyle(
fontFamily: 'Hafs',
fontSize: 26,
color: Colors.greenAccent[100])),
),
// now populating your ListView for `Directionality`
Column(
children: <Widget>[
// Start activities
Column(
children: snapshot.data.map<Widget>((item) {
double _value =
double.parse(item.mydigree.toString());
return Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
width: 2, color: Colors.white),
color:
Color.fromRGBO(230, 200, 200, 0.2)),
width: widthView,
padding: EdgeInsets.all(25),
margin: EdgeInsets.fromLTRB(0, 25, 0, 25),
child: Column(
children: <Widget>[
Text(
lang == 'k'
? item.activity_k
: item.activity_a,
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 28, color: Colors.white),
),
SizedBox(
height: 15,
),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.yellow[200]
.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 20,
)
],
borderRadius:
BorderRadius.circular(15),
color:
Color.fromRGBO(0, 0, 0, 0.4)),
width: widthView,
padding: EdgeInsets.all(10),
child: Slider(
max: 100,
min: 0,
divisions: 100,
value: _value,
label: _value.round().toString(),
onChanged: (val) {
send_degree(u_id, item.act_id,
val, w_id, did, m_id);
},
onChangeEnd: (val) {
setState(() {
_value = val;
});
getUserStatus(); /// when i print the value here it is give me null
}),
),
SizedBox(
height: 10,
),
Text('$_value',
style: TextStyle(
fontSize: 26,
color: Colors.white))
],
),
)
],
),
);
}).toList()),
// End activities
SizedBox(
height: 20,
),
Text('خەلەکا ئەڤرو',
textAlign: TextAlign.right,
style:
TextStyle(fontSize: 26, color: Colors.yellow)),
SizedBox(
height: 20,
),
YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
progressIndicatorColor: Colors.blueAccent,
),
],
),
],
),
),
);
}
});
}
}
you can usef ValueChanged onChanged and do a callback to the page you want to update ,
you can passe the onChanged funtion on the parametre ,
when you change your value use : onChanged()
than in the page you want to see the update on call your function with set state ,
I solved it by merging two function in one :
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
and they now like this and worked correctly :
Future<List> fetchDigrees() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
username = preferences.getString('username');
var url1 =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response1 = await http.get(url1);
var data1 = jsonDecode(response1.body);
newSavedDayId = int.parse(data1['d_id']);
print('newSavedDayId before retrun = $newSavedDayId');
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
I've one page on that page there is one add button and it will add the widget as much users want but when I am uploading image it will not upload. and when I press the add button it will already upload the image on the next generated widget. and also it is not giving me the value of that images.
Here is the image it will upload image on the click of the image add button but it's not uploading. and also when I am adding multipart it will send the value as null to the backend side
Here is code i've tried.
class BspUnlicensedSignupPage extends StatefulWidget {
static const String routeName = "/bspUnlicensedSignup";
final BspSignupCommonModel bspSignupCommonModel;
BspUnlicensedSignupPage({
Key key,
#required this.bspSignupCommonModel,
}) : super(key: key);
#override
_BspUnlicensedSignupPageState createState() =>
_BspUnlicensedSignupPageState();
}
class _BspUnlicensedSignupPageState extends State<BspUnlicensedSignupPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
List<Object> images = List<Object>();
Future<File> _imageFile;
bool autovalidate = false;
bool informationislegitimate = false;
DateTime expirydate1 = DateTime.now();
DateTime expirydate2 = DateTime.now();
final format = DateFormat("yyyy-MM-dd");
final format2 = DateFormat("yyyy-MM-dd");
String type2 = 'Passport';
List<String> _type = <String>[
'',
'Passport',
'Driving License',
'Voter ID card',
'Ration Card',
'Aadhar',
'Other Id',
];
String type = 'Passport';
// Map<String, String> _formdata = {};
var _myWidgets = List<Widget>();
int _index = 1;
final Map<int, String> identification1Values = Map();
final Map<int, String> documentValues = Map();
final Map<int, DateTime> expiryDateValues = Map();
final Map<int, String> issuingAuthority = Map();
final Map<int, String> identificationPicturesValues = Map();
final List<TextEditingController> _documentControllers = List();
final List<TextEditingController> _issuingauthoritytype = List();
final List<TextEditingController> _expiryDate = List();
final List<TextEditingController> _issuingauthority = List();
final List<List<Object>> _identificationpictures = List();
#override
void initState() {
super.initState();
setState(() {
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
});
}
void _add() {
// TextEditingController controller = TextEditingController();
setState(() {
int keyValue = _myWidgets.length;
_myWidgets = List.from(_myWidgets)
..add(Column(
key: Key("$keyValue"),
children: <Widget>[
SizedBox(height: 10),
Container(
// padding: EdgeInsets.fromLTRB(18,5,18,18),
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 15,
),
],
),
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Align(
alignment: Alignment.topRight,
child: GestureDetector(
child: Icon(Icons.close),
onTap: () {
print("CLose pressed");
setState(() {
_myWidgets = List.from(_myWidgets)
..removeAt(keyValue);
});
},
),
),
SizedBox(
height: 10,
),
Column(
children: <Widget>[
SizedBox(
height: 20,
),
_buildidentificationtype1(keyValue),
_builddocumentnumber1(keyValue),
_builddate(keyValue),
_buildissuingauthority1(keyValue),
_buildidentificationpictures(keyValue),
],
),
],
)
],
),
)
],
));
});
}
bool isClicked = false;
Widget _buildidentificationtype1(int keyValue) {
TextEditingController controller = TextEditingController();
_issuingauthoritytype.add(controller);
return FormBuilder(
autovalidate: autovalidate,
child: FormBuilderCustomField(
attribute: "Business type",
validators: [FormBuilderValidators.required()],
formField: FormField(
builder: (FormFieldState<dynamic> field) {
return InputDecorator(
decoration: InputDecoration(
prefixIcon: Icon(Icons.location_on),
labelText : 'Business type',
),
isEmpty: type == '',
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
value: type,
isDense: true,
onChanged: (String newValue) {
setState(() {
type = controller.text = newValue;
field.didChange(newValue);
});
},
items: _type.map(
(String value) {
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
},
).toList(),
),
),
);
},
)),
);
}
Widget _builddocumentnumber1(int keyValue) {
TextEditingController controller = TextEditingController();
_documentControllers.add(controller);
return new TudoTextWidget(
controller: controller,
prefixIcon: Icon(FontAwesomeIcons.idCard),
labelText : 'Document Number'
onSaved: (val) {
setState(() {
documentValues[keyValue] = val;
});
// _licenseno = val;
},
);
}
Widget _builddate(int keyValue) {
TextEditingController controller = TextEditingController();
_expiryDate.add(controller);
return DateTimeField(
format: format,
autocorrect: true,
autovalidate: autovalidate,
controller: controller,
readOnly: true,
// validator: (date) => date == null ? 'Please enter valid date' : null,
decoration: InputDecoration(
labelText: "Expiry Date",
hintText: "Expiry Date",
prefixIcon: Icon(
FontAwesomeIcons.calendar,
size: 24,
)),
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime.now(),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime(2100));
},
);
}
Widget _buildissuingauthority1(int keyValue) {
TextEditingController controller = TextEditingController();
_issuingauthority.add(controller);
return new TudoTextWidget(
prefixIcon: Icon(FontAwesomeIcons.idCard),
labelText: 'Issuning authority',
validator: (val) => Validators.validateName(val, "Issuing Authority"),
onSaved: (val) {
setState(() {
issuingAuthority[keyValue] = val;
});
// _illusingauthority = issuingAuthority[keyValue] = val;
},
controller: controller,
);
}
Widget _buildidentificationpictures(int keyValue) {
return GridView.count(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 5,
childAspectRatio: 1,
children: List.generate(images.length, (index) {
if (images[index] is ImageUploadModel) {
ImageUploadModel uploadModel = images[index];
return Card(
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
Image.file(
uploadModel.imageFile,
width: 300,
height: 300,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
onTap: () {
setState(() {
images.replaceRange(index, index + 1, ['Add Image']);
_identificationpictures.add(images);
});
},
),
),
],
),
);
} else {
return Card(
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
_onAddImageClick(index);
},
),
);
}
}),
);
}
Future _onAddImageClick(int index) async {
setState(() {
_imageFile = ImagePicker.pickImage(source: ImageSource.gallery);
getFileImage(index);
});
}
void getFileImage(int index) async {
// var dir = await path_provider.getTemporaryDirectory();
_imageFile.then((file) async {
setState(() {
ImageUploadModel imageUpload = new ImageUploadModel();
imageUpload.isUploaded = false;
imageUpload.uploading = false;
imageUpload.imageFile = file;
imageUpload.imageUrl = '';
images.replaceRange(index, index + 1, [imageUpload]);
});
});
}
Widget _buildinformationislegitmate() {
return TudoConditionWidget(
text:
"Above entered Identity information is legitimate and accurate to my knowledge",
);
}
#override
Widget build(BuildContext context) {
final appBar = AppBar(
title: Text("BSP Unlicensed Details"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
NavigationHelper.navigatetoBack(context);
},
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
_add();
});
},
),
],
centerTitle: true,
);
final bottomNavigationBar = Container(
color: Colors.transparent,
height: 56,
//margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () async {
setState(() {
autovalidate = !autovalidate;
});
if (_formKey.currentState.validate()) {
List<Licensed> listOfLicenses = new List<Licensed>();
BspSignupCommonModel model = widget.bspSignupCommonModel;
for (var i = 0; i < _myWidgets.length; i++) {
String document = _documentControllers[i].text;
String issuingAuthorityType = _issuingauthoritytype[i].text;
String expiryDate = _expiryDate[i].text;
String issuingAuthority = _issuingauthority[i].text;
// String picture = _identificationpictures[i].text;
print('Document: $document');
print('IssuingAuthorityType: $issuingAuthorityType');
print('ExpiryDate: $expiryDate');
print('IssuingAuthority: $issuingAuthority');
print('Picture: ${_identificationpictures.length}');
print(_myWidgets.length);
Licensed licensed = new Licensed(
bspLicenseNumber: document,
bspAuthority: issuingAuthority,
bspExpiryDate: expiryDate,
bspIssuing: issuingAuthorityType,
);
licensed.bspLicenseNumber = _documentControllers[i].text;
licensed.bspExpiryDate = _expiryDate[i].text;
licensed.bspIssuing = _issuingauthoritytype[i].text;
licensed.bspAuthority = _issuingauthority[i].text;
listOfLicenses.add(licensed);
}
model.unlicensed = listOfLicenses;
print(model.toJson());
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BspLicensedSignupTermsPage(
bspSignupCommonModel: model),
));
}
}),
],
),
);
return new Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
floatingActionButton: new FloatingActionButton.extended(
onPressed: () {
_add();
},
label: Text(
"Add License",
style: TextStyle(color: Colors.white, fontSize: 16),
),
icon: Icon(
Icons.add,
size: 28,
color: Colors.white,
),
),
body: Container(
height: double.infinity,
width: double.infinity,
child: Form(
autovalidate: autovalidate,
key: _formKey,
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Expanded(
child: SizedBox(
child: ListView(
padding: const EdgeInsets.all(18.0),
children: _myWidgets,
),
),
),
_buildinformationislegitmate(),
],
)
],
)),
),
);
}
}
The problem seems to be that you are using the same list images for every item, you could try to use a Map that has the lists for each item.
I suggest you to try to create a separate widget with the entire card so it can handle it's own state.