can't rebuild widget shown when downloading progress start flutter_downloader - flutter

Hi I'm trying to show different widget depending on the state of my attachment list
when not downloaded - download icon
when downloading in progress - circularprogressIcon / show the progress number
when done downloading - done icon
I manage to use the flutter_downloader and pass the data, but the problem is when we are still downloading the file, it didn't change to circular progress Icon it just stay in the download icon and suddenly when it's done the icon will be changed into done icon. How can I fix this ? I was able to print the progress on the terminal.
The problem is when i first attach the file, and then someone try to download it. It work just fine but when the other party delete it in their gallery and then tried to re-download it again, that's when the problem occur.
Here's my code:
progress == 0 ?
fileExistList[index] == true ?
Icon(
Icons.done,
color:
floatingActionButtonColor,
size: 19.0,
) : GestureDetector(
onTap: () async {
if (fileExistList[
index]) {
//Open file if it's already exist in the Local Path
OpenFile.open(externalDir!.path +
"/" +
fileAttachmentList[index]['name']);
} else {
currentDownload =
fileAttachmentList[index]['name'];
final taskId =
await FlutterDownloader.enqueue(
url: fileAttachmentList[index]['url'],
savedDir: externalDir!.path,
showNotification: true,
openFileFromNotification: true,
);
fileExistList[index] =
true;
}
},
child: Icon(
Icons.download,
color:
floatingActionButtonColor,
size: 17.0),
)
: currentDownload == fileAttachmentList[index]['name'] ?
progress == 100 ? Icon(
Icons.done,
color:
floatingActionButtonColor,
size: 19.0)
: Padding(
padding: EdgeInsets
.only(
right:
4),
child:
SizedBox(
child:
CircularProgressIndicator(
strokeWidth:
2.0,
valueColor:
AlwaysStoppedAnimation<Color>(
floatingActionButtonColor),
),
height:
10.0,
width:
10.0,
),
)
: fileExistList[index] == true
? Icon(
Icons.done,
color:
floatingActionButtonColor,
size: 19.0)
: Icon(
Icons
.download,
color:
floatingActionButtonColor,
size: 17.0)

I think you should go through the official docs. https://pub.dev/packages/flutter_downloader
There are callbacks for getting the updation status.

Related

Pie chart issues in flutter

I'm using the fl_chart package to create an interactive Pie Chart for my application. Although the design came out fine, I'm facing the following issues with the functionality:
Tapping on a particular PieChartSectionData doesn't always select it and even tapping repeatedly doesn't help. It's always two out of the three that are tappable. Please note that the functionality works as it should for all the sections but there is no indication suggesting that the section tapped on was clicked. As defined in my code, every tap on a section should increase the radius and it's font size to make it stand out from the rest.
Every time a PieChartSectionData is clicked, it is supposed to navigate to a new page after a delay of 500 milliseconds. Although this works as expected, I cannot seem to come back to the previous page that has the Pie Chart on it using the phone's back button on the very first click. It is only after repeated clicks that it takes me back to the original page.
The chart seems to be clickable even beyond the PieChartSectionData. So like let's say if I tap an inch away from one of the sections, it tends to take me to that other page I need to navigate to. This shouldn't be the case.
Here is my code:
class ToDoListPieState extends State<ToDoListPie> {
int? index;
double? percent;
int? taskCount;
#override
Widget build(BuildContext context) {
final provider = Provider.of<TodaysTaskList>(context).getToDoList;
// TODO: implement build
return Stack(
children: [
PieChart(PieChartData(
borderData: FlBorderData(show: false),
pieTouchData: PieTouchData(
touchCallback: (FlTouchEvent event, pieTouchResponse) {
setState(() {
if (pieTouchResponse == null ||
pieTouchResponse.touchedSection == null) {
index = -1;
}
index = pieTouchResponse!.touchedSection!.touchedSectionIndex;
});
Future.delayed(const Duration(milliseconds: 500), () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => TaskList())); //This here is the event where clicking on a section should take us to the next page
});
print('Index: $index'); //This prints even if we click away from a section
},
),
sectionsSpace: 5,
centerSpaceRadius: 80,
sections: [
PieChartSectionData(
color: Colors.blue,
title: provider['upcoming'].length.toString(),
value: double.parse(provider['upcoming'].length.toString()),
radius: index == 0 ? 40 : 30,
titleStyle: TextStyle(fontSize: index == 0 ? 25 : 16)),
PieChartSectionData(
color: Colors.amber,
title: provider['today'].length.toString(),
value: double.parse(provider['today'].length.toString()),
radius: index == -1 ? 40 : 30,
titleStyle: TextStyle(fontSize: index == -1 ? 25 : 16)),
PieChartSectionData(
color: Colors.red,
title: provider['previous'].length.toString(),
value: double.parse(provider['previous'].length.toString()),
radius: index == 1 ? 40 : 30,
titleStyle: TextStyle(fontSize: index == 1 ? 25 : 16))
])),
Positioned(
left: 0,
top: SizeVariables.getHeight(context) * 0.18,
right: 0,
bottom: 0,
child: Column(
children: [
FittedBox(
fit: BoxFit.contain,
child: Text(
'${provider['upcoming'].length + provider['today'].length + provider['previous'].length}',
style: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(fontSize: 25),
),
),
Text(
'Tasks',
style: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(fontSize: 18),
)
],
),
)
],
);
}
}
Any help will be appreciated!

Upload multiple file to fire store with progress bar in flutter

I would like to upload more than one file to fire-store while showing a progress indicator. Am trying to achieve this by looping over the files chosen by the user. The files are picked using the flutter filePicker package.
for (var file in choosenFiles) {
String fileName = file.name;
String? filePath = file.path;
File creatFile = File(filePath!);
UploadTask task = FirebaseStorage.instance
.ref('post_files/${value.id}-$fileName')
.putData(creatFile.readAsBytesSync());
task.snapshotEvents.listen((event) {
setState(() {
progress = ((event.bytesTransferred.toDouble() /
event.totalBytes.toDouble() *
100)
.roundToDouble());
});
});
}
for the progress indicator, i use a circularProgressIndicator to listen to the value of variable progress.
Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(
value: progress / 100,
backgroundColor: Colors.green,
color: Colors.red,
strokeWidth: 8,
),
),
)
What could be the problem?. Will be grateful for any help. thanks.

PlatformException(multiple_request, Cancelled by a second request, null, null) in imagePicker

I am using a riverpod provider class to handle picking of image from gallery. However, once an image is picked, I get the error: PlatformException(multiple_request, Cancelled by a second request null, null). Not sure where a second request is coming from. More importantly, no image is applied to my placeholder (CircleAvartar) due to this unknown cancellation.
Here are the two dart files in question and thanks for the help.
imageProvider file:
final myImageProvider =
ChangeNotifierProvider<ImageNotifier>((ref) => ImageNotifier());
class ImageNotifier extends ChangeNotifier {
ImageNotifier() : super();
final file = useState<File?>(null);
final imageFile = useState<XFile?>(null);
final imagePicker = ImagePicker();
Future<void> _pickImage(int type) async {
try {
XFile? userImage = await imagePicker.pickImage(
source: type == 1 ? ImageSource.gallery : ImageSource.camera,
imageQuality: 50,
);
imageFile.value = userImage;
// imageFile.value = XFile(userImage!.path);
} catch (e) {
print(e);
}
notifyListeners();
}
void showPicker(context) {
showModalBottomSheet(
backgroundColor: Theme.of(context).primaryColor,
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Wrap(
children: [
ListTile(
leading: const Icon(
Icons.photo_library,
color: Colors.white,
),
title: const Text(
'Photo Gallery',
style: TextStyle(fontSize: 22),
),
onTap: () => _pickImage(1),
),
ListTile(
leading: const Icon(
Icons.photo_camera,
color: Colors.white,
),
title: const Text(
'Camera',
style: TextStyle(fontSize: 22),
),
onTap: () => _pickImage(2),
),
ListTile(
leading: const Icon(
Icons.close,
color: Colors.white,
),
title: const Text(
'Cancel',
style: TextStyle(fontSize: 22),
),
onTap: () {
imageFile.value = null;
Navigator.of(context).pop();
},
),
],
),
);
},
);
notifyListeners();
}
AuthScreen dart file:
Widget build(BuildContext context, WidgetRef ref) {
final _passwordController = useTextEditingController();
final _passwordFocusScope = useFocusNode();
final _emailFocusScope = useFocusNode();
final _phoneFocusScope = useFocusNode();
final _confirmFocusScope = useFocusNode();
final _isVisible = useState<bool>(true);
var _authMode = useState<AuthMode>(AuthMode.login);
final imageProviderState = ref.watch(myImageProvider.notifier);
final deviceSize = MediaQuery.of(context).size;
final authMode = ModalRoute.of(context)?.settings.arguments as String;
switch (authMode) {
case 'login':
_authMode.value = AuthMode.login;
break;
case 'register':
_authMode.value = AuthMode.register;
break;
case 'google':
_authMode.value = AuthMode.google;
break;
case 'guest':
_authMode.value = AuthMode.guest;
break;
}
return Scaffold(
body: Stack(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(
height: 80,
),
Center(
child: _authMode.value == AuthMode.login
? const Text(
'Access Your Account',
style: TextStyle(
fontSize: 25,
),
)
: Row(
children: [
InkWell(
onTap: () =>
imageProviderState.showPicker(context),
// () => ref
// .read(myImageProvider.notifier)
// .showPicker(context),
child: CircleAvatar(
radius: 50,
backgroundImage:
imageProviderState.imageFile.value !=
null
? FileImage(
// File(ref
// .read(imageProvider.notifier)
// .imageFile
// .value!
// .path),
// )
File(imageProviderState
.imageFile.value!.path),
)
: null,
child: imageProviderState.imageFile.value ==
null
? const Icon(
Icons.camera,
// Icons.add_photo_alternate,
size: 30,
color: Colors.white,
)
: null,
),
),
After testing the code on a real device (iPhone and Android) I was able to select and attach a photo from gallery and camera to my form. The issue is with trying to do this task on a simulator even though one was able to do so once upon a time. Don't even bother anymore until Apple fixes this trouble. My advice is that you debug on a real device to ensure things are working as coded and you can return to the simulator/emulator afterwards. I lost a lot of time trying to make tis work on a simulator to no avail.
I have the latest Flutter 3.3.9 and Xcode 14.1 and this is still a problem. The workaround is very simple though after reading this issue. When using the image_picker, DO NOT pick the first image (with pink flowers):
In addition to my earlier answer and further tweaking with the dev in simulator environment, I just discovered that the uploaded image does show up upon a reload/restart. Weird but works if you must test in simulation mode. Simply restart and the uploaded image will show up. It is still a simulator issue though, IMHO.
It can help to double-click on the image you are selecting from the gallery instead of clicking only once.
For whatever reason, if I clicked only once, it would not show up and the same error as yours appeared.
If I clicked twice there was a short lag, but the image showed up.
Tested on iOS simulator - don't get this issue personally on my Android emulator.
I had this issue picking one of the default album images on my iOS simulator.
I was able to get around this by going to Safari, saving a png to Photos and then selecting that downloaded png in my Flutter app.
Thanks to Marc's post which pointed me in the right direction regarding HEIC support
Hi please have a look at this discussion:
https://github.com/flutter/flutter/issues/70436
on on the image picker package site we can see that it is a well known apple simulator issue. I would say that it should work for you on real devices (or try to test it only with particular pictures from iOS simulator photos)
Make sure ALLOW PHOTO ACCESS permission is set to either Selected Photos or All Photos. In my case, I had denied the permission so there was no error log on the console and the image picker was not opening.
PS I know it's not directly related to the SO's question but might be helpful if someone comes across this.
Don't bother about this issue much. This is just a simulator issue(mostly on iOS). Testing this on a real device is advisable.
I think it because it using 'pickimage' instead of 'pickMultiImage', so u are only allow to pick 1 image at a time, try to make ur 'imageFile' to null first before you pick another image.

want to get an animated container small again to initial size with a click. It expands perfectly but I can't close it again

want to get an animated container small again to initial size with a click. It expands perfectly but I can't close it again.............................................................................................................................
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
width: isTextOpen ? 200 : 95,
height: 50,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(3)),
border: isTextOpen
? Border.all(
color: Colors.deepOrangeAccent,
width: 1.0,
)
: null,
),
child: isTextOpen
? TextField()
: GestureDetector(
onTap: () {
setState(() {
isTextOpen = true;
kapaac = 1;
});
},
child: Text(
"User_007",
style: TextStyle(
color: Colors.deepOrangeAccent,
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
),
),
You are not setting it back to false.
setState(() => isTextOpen = !isTextOpen);
Once the user clicks the textbox if you want to get the textBox size to the initial size then you need to define a double variable with the expanded size then once the user clicks the text box for entering the text you need to reset the variable
double animatedContainerSize = 200;
After that set your AnimatedContainer widget width with the variable
width: isTextOpen ? animatedContainerSize : 95,
Then in your text box onTap function change the size to initial size with setState
isTextOpen
? TextField(
onTap: () {
setState(() {
animatedContainerSize = 95;
});
},
)

How to show icon on specific area after click on button?

My Goal:
When user click on RaisedButton i would like to show a icon.
My problem:
I don't know how to show icon on specific area
My code:
This code generate some responses buttons (Europe, Asia, Africa, ..)
for (var i = 0; i < NumberChoice; i++)
RaisedButton(
color: _colorButton,
child: new Text(
_choice[i],
style: TextStyle(
fontSize: 20.0, color: Colors.white),
),
onPressed: () {
setState(() {
if (_choice[i] == answer) {
print("--------------- Corect ----------------");
//--HERE HOW TO SHOW ICON IF USER CLICK ON BUTTON--
Icon(
Icons.check,
color: Colors.green,
size: 24.0,
);
scoreResult = 1;
} else {
print("--------------- False ------------------------");
//--HERE HOW TO SHOW ICON IF USER CLICK ON BUTTON--
Icon(
Icons.close,
color: Colors.red,
size: 24.0,
);
scoreResult = 0;
}
});
},
)
Example
If user click on "Europe" , then "Icons.check" displayed where i added "Button here" .
From what i understand
create a string like this : -
String choice;
change it to true whenever u click on raised button
choice == answer
? // show widget if correct
: SizedBox()