SlideShare a Scribd company logo
How to Create a Download Button in Flutter?
Apps are brimming with buttons that carry out long-running actions. A
button, for example, could initiate a download, which initiates the
download process, receives data over time, and ultimately grants
access to the downloaded content.
It’s useful to provide the user with the details of how a long-running
procedure is progressing, and the button is a suitable spot to do so.
This recipe will show you how to make a download button that changes
visual states depending on the status of an app download. If you are
having trouble implementing the solution, gets talented Flutter
developers for hire from our company. Our developers are also experts
in creating high-end mobile applications.
• The steps involved in the process of creating a download button in
the flutter development app are mentioned below:
1. Defining a new Stateful widget
2. Defining the possible visual states of the button
3. Display the shape of the button
4. Creating the display of the button’s text
5. Display a spinner while fetching the download
6. Display the progress percentage and a stop button while
downloading
7. Add callbacks to button taps
1. Defining a new stateful widget
The appearance of your button widget must alter over time. As a result,
you’ll need to use a bespoke stateless widget to implement your
button. Then, define a new stateless widget called DownloadButton.
class DownloadButton extends StatelessWidget {
const DownloadButton({
super.key,
});
@override
Widget build(BuildContext context) {
// TODO:
return const SizedBox();
}
}
2. Defining the possible visual states of the button
The current download status determines the visual display of the
download button. After Defining the download’s possible states,
update DownloadButton to accept a DownloadStatus and specify the
duration for how long the button should fly from one visual state to the
next.
When designing a custom widget, you must select whether it receives
all necessary information from its parent or if the Widget orchestrates
the application’s activity internally. DownloadButton, for example,
might get the existing DownloadStatus from its parent, or it may
coordinate the download process within its State object.
Rather than managing behavior within the Widget, the ideal solution
for most widgets is to transfer relevant information into it from its
parent. You assure increased utility for the Widget, simpler testing, and
future modifications to application behavior by handing in all essential
information.
enum DownloadStatus {
notDownloaded,
fetchingDownload,
downloading,
downloaded,
}
3. Display the shape of the button
The form of the download button varies depending on the download
state. During the notDownloaded and downloaded phases, the button
shows a gray, rounded rectangle. During the fetchingDownload and
downloading stages, the button shows a translucent circle.
In the next step, Create an AnimatedContainer with a ShapeDecoration
that shows a rounded rectangle or a circle based on the current
DownloadStatus.
Consider establishing the shape’s widget tree in a separate Stateless
widget to keep the main construct() function simple while allowing for
the modifications that will come later. Then, rather than constructing a
function to return a widget, such as Widget _buildSomething(),
always create a StatelessWidget or a StatefulWidget, which is faster.
Now, the AnimatedContainer appears to be just a SizedBox child, but
you don’t need to worry; we will resolve this state in another step.
@immutable
classButtonShapeWidget extends StatelessWidget {
constButtonShapeWidget({
super.key,
requiredthis.isDownloading,
requiredthis.isDownloaded,
requiredthis.isFetching,
requiredthis.transitionDuration,
});
final bool isDownloading;
final bool isDownloaded;
final bool isFetching;
final Duration transitionDuration;
@override
Widget build(BuildContext context) {
var shape = constShapeDecoration(
shape: StadiumBorder(),
color: CupertinoColors.lightBackgroundGray,
);
if (isDownloading || isFetching) {
shape = ShapeDecoration(
shape: constCircleBorder(),
color: Colors.white.withOpacity(0.0),
);
}
return AnimatedContainer(
duration: transitionDuration,
curve: Curves.ease,
width: double.infinity,
decoration: shape,
child: constSizedBox(),
);
}
}
4. Creating the display of the button’s text
Different messages are displayed through the Download button in its
different phases. The notDownloaded phase displays the GET option.
The downloaded phases display the OPEN option for the users, while
no text is displayed in the intermediate process.
Add widgets to show text throughout each download step, and
animate the opacity of the text between them. For example, in the
button wrapper widget, make the text widget tree a child of the
AnimatedContainer.
return AnimatedContainer(
duration: transitionDuration,
curve: Curves.ease,
width: double.infinity,
decoration: shape,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: AnimatedOpacity(
duration: transitionDuration,
opacity: isDownloading || isFetching ? 0.0 : 1.0,
curve: Curves.ease,
child: Text(
isDownloaded ?'OPEN' : 'GET',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button?.copyWith(
fontWeight: FontWeight.bold,
color: CupertinoColors.activBlue,
),
),
),
),
);
5. Display a spinner while fetching the download
The DownloadButton shows a radial spinner while fetchingDownload is
in progress. This spinner transitions from notDownloaded to
fetchingDownload.
Install a radial spinner on top of the button form that fades in and out
at appropriate intervals.
The function Object() { [native code] } of the ButtonShapeWidget has
been eliminated to focus on its build function and the Stack
widget that we’ve created.
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _onPressed,
child: Stack(
children: [
ButtonShapeWidget(
transitionDuration: transitionDuration,
isDownloaded: _isDownloaded,
isDownloading: _isDownloading,
isFetching: _isFetching,
),
}
Positioned.fill(
child: AnimatedOpacity(
duration: transitionDuration,
opacity: _isDownloading || _isFetching ? 1.0 : 0.0,
curve: Curves.ease,
child: ProgressIndicatorWidget(
downloadProgress: downloadProgress,
isDownloading: _isDownloading,
isFetching: _isFetching,
),
),
),
],
),
);
}
6. Display the progress percentage and a stop
button while downloading
Following the retrieval, the downloading step is exactly that. The
DownloadButton transforms the radial progress spinner with a rising
radial progress bar during the downloading period. A stop button
symbol is also displayed on the DownloadButton, allowing the user to
halt an ongoing download.
After adding an advancement property to the DownloadButton plugin,
change the progress display to a radial toolbar during the downloading
phase. Then, place a stop button icon in the center of the radial
progress bar.
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _onPressed,
child: Stack(
children: [
ButtonShapeWidget(
transitionDuration: transitionDuration,
isDownloaded: _isDownloaded,
isDownloading: _isDownloading,
isFetching: _isFetching,
),
Positioned.fill(
child: AnimatedOpacity(
duration: transitionDuration,
opacity: _isDownloading || _isFetching ? 1.0 : 0.0,
curve: Curves.ease,
child: Stack(
alignment: Alignment.center,
children: [
ProgressIndicatorWidget(
downloadProgress: downloadProgress,
isDownloading: _isDownloading,
isFetching: _isFetching,
),
if (_isDownloading)
const Icon(
Icons.stop,
size: 14.0,
color: CupertinoColors.activeBlue,
),
],
),
),
),
],
),
);
}
7. Add callbacks to button taps
The button behavior is the final thing that your DownloadButton
requires. When the user clicks the button, it must do some action. Add
callbacks for starting a download, canceling a download, and opening a
download to the widget properties.
Finally, use a GestureDetector widget to cover DownloadButton’s
current widget tree and route the tap event to the relevant callback
property.
void _onPressed() {
switch (status) {
case DownloadStatus.notDownloaded:
onDownload();
break;
case DownloadStatus.fetchingDownload:
// do nothing.
break;
case DownloadStatus.downloading:
onCancel();
break;
case DownloadStatus.downloaded:
onOpen();
break;
}
}
Now at the end of the process, you have a button that displays
different information based on whatever phase it is in: not
downloaded, seeking download, downloading phase, and downloaded
completely. The user may tap to initiate a download, stop an ongoing
download, and access a finished download by tapping.
Let’s see a full example of DownloadButton:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: ExampleDownloadButton(),
debugShowCheckedModeBanner: false,
),
);
}
@immutable
class ExampleDownloadButton extends StatefulWidget {
const ExampleDownloadButton();
@override
_ExampleDownloadButtonState createState() => _ExampleDownloadButtonState();
}
class _ExampleDownloadButtonState extends State<exampledownloadbutton> {
late final List<downloadcontroller> _downloadControllers;
@override
void initState() {
super.initState();
_downloadControllers = List<downloadcontroller>.generate(
10,
(index) => SimulatedDownloadController(onOpenDownload: () {
_openDownload(index);
}),
);
}
void _openDownload(int index) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Open PDF ${index + 1}'),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Download Button')),
body: ListView.separated(
itemCount: _downloadControllers.length,
separatorBuilder: (_, __) => const Divider(),
itemBuilder: _buildListItem,
),
);
}
Widget _buildListItem(BuildContext context, int index) {
final theme = Theme.of(context);
final downloadController = _downloadControllers[index];
return ListTile(
leading: const Icon(Icons.list_rounded),
title: Text(
'Pdf ${index + 1}',
overflow: TextOverflow.ellipsis,
style: theme.textTheme.headline6,
),
trailing: SizedBox(
width: 96,
child: AnimatedBuilder(
animation: downloadController,
builder: (context, child) {
return DownloadButton(
status: downloadController.downloadStatus,
downloadProgress: downloadController.progress,
onDownload: downloadController.startDownload,
onCancel: downloadController.stopDownload,
onOpen: downloadController.openDownload,
);
},
),
),
);
}
}
enum DownloadStatus {
notDownloaded,
fetchingDownload,
downloading,
downloaded,
}
abstract class DownloadController implements ChangeNotifier {
DownloadStatus get downloadStatus;
double get progress;
void startDownload();
void stopDownload();
void openDownload();
}
class SimulatedDownloadController extends DownloadController
with ChangeNotifier {
SimulatedDownloadController({
DownloadStatus downloadStatus = DownloadStatus.notDownloaded,
double progress = 0.0,
required VoidCallback onOpenDownload,
}) : _downloadStatus = downloadStatus,
_progress = progress,
_onOpenDownload = onOpenDownload;
DownloadStatus _downloadStatus;
@override
DownloadStatus get downloadStatus => _downloadStatus;
double _progress;
@override
double get progress => _progress;
final VoidCallback _onOpenDownload;
bool _isDownloading = false;
@override
void startDownload() {
if (downloadStatus == DownloadStatus.notDownloaded) {
_doSimulatedDownload();
}
}
@override
void stopDownload() {
if (_isDownloading) {
_isDownloading = false;
_downloadStatus = DownloadStatus.notDownloaded;
_progress = 0.0;
notifyListeners();
}
}
@override
void openDownload() {
if (downloadStatus == DownloadStatus.downloaded) {
_onOpenDownload();
}
}
Future<void> _doSimulatedDownload() async {
_isDownloading = true;
_downloadStatus = DownloadStatus.fetchingDownload;
notifyListeners();
// Wait a second to simulate fetch time.
await Future<void>.delayed(const Duration(seconds: 1));
// If the user chose to cancel the download, stop the simulation.
if (!_isDownloading) {
return;
}
// Shift to the downloading phase.
_downloadStatus = DownloadStatus.downloading;
notifyListeners();
const downloadProgressStops = [0.0, 0.15, 0.45, 0.8, 1.0];
for (final stop in downloadProgressStops) {
// Wait a second to simulate varying download speeds.
// await Future<void>.delayed(const Duration(seconds: 1));
if (!_isDownloading) {
return;
}
_progress = stop;
notifyListeners();
}
await Future<void>.delayed(const Duration(seconds: 1));
if (!_isDownloading) {
return;
}
_downloadStatus = DownloadStatus.downloaded;
_isDownloading = false;
notifyListeners();
}
}
@immutable
class DownloadButton extends StatelessWidget {
const DownloadButton({
required this.status,
this.downloadProgress = 0.0,
required this.onDownload,
required this.onCancel,
required this.onOpen,
this.transitionDuration = const Duration(milliseconds: 500),
});
final DownloadStatus status;
final double downloadProgress;
final VoidCallback onDownload;
final VoidCallback onCancel;
final VoidCallback onOpen;
final Duration transitionDuration;
bool get _isDownloading => status == DownloadStatus.downloading;
bool get _isFetching => status == DownloadStatus.fetchingDownload;
bool get _isDownloaded => status == DownloadStatus.downloaded;
void _onPressed() {
switch (status) {
case DownloadStatus.notDownloaded:
onDownload();
break;
case DownloadStatus.fetchingDownload:
// do nothing.
break;
case DownloadStatus.downloading:
onCancel();
break;
case DownloadStatus.downloaded:
onOpen();
break;
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _onPressed,
child: Stack(
children: [
ButtonShapeWidget(
transitionDuration: transitionDuration,
isDownloaded: _isDownloaded,
isDownloading: _isDownloading,
isFetching: _isFetching,
),
Positioned.fill(
child: AnimatedOpacity(
duration: transitionDuration,
opacity: _isDownloading || _isFetching ? 1.0 : 0.0,
curve: Curves.ease,
child: Stack(
alignment: Alignment.center,
children: [
ProgressIndicatorWidget(
downloadProgress: downloadProgress,
isDownloading: _isDownloading,
isFetching: _isFetching,
),
if (_isDownloading)
const Icon(
Icons.stop,
size: 14,
color: CupertinoColors.activeBlue,
),
],
),
),
),
],
),
);
}
}
@immutable
class ButtonShapeWidget extends StatelessWidget {
const ButtonShapeWidget({
key,
required this.isDownloading,
required this.isDownloaded,
required this.isFetching,
required this.transitionDuration,
});
final bool isDownloading;
final bool isDownloaded;
final bool isFetching;
final Duration transitionDuration;
@override
Widget build(BuildContext context) {
var shape = const ShapeDecoration(
shape: StadiumBorder(),
color: CupertinoColors.lightBackgroundGray,
);
if (isDownloading || isFetching) {
shape = ShapeDecoration(
shape: const CircleBorder(),
color: Colors.white.withOpacity(0),
);
}
return AnimatedContainer(
duration: transitionDuration,
curve: Curves.ease,
width: double.infinity,
decoration: shape,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: AnimatedOpacity(
duration: transitionDuration,
opacity: isDownloading || isFetching ? 0.0 : 1.0,
curve: Curves.ease,
child: Text(
isDownloaded ? 'OPEN' : 'GET',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button?.copyWith(
fontWeight: FontWeight.bold,
color: CupertinoColors.activeBlue,
),
),
),
),
);
}
}
@immutable
class ProgressIndicatorWidget extends StatelessWidget {
const ProgressIndicatorWidget({
key,
required this.downloadProgress,
required this.isDownloading,
required this.isFetching,
});
final double downloadProgress;
final bool isDownloading;
final bool isFetching;
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1,
child: TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: downloadProgress),
duration: const Duration(milliseconds: 200),
builder: (context, progress, child) {
return CircularProgressIndicator(
backgroundColor: isDownloading
? CupertinoColors.lightBackgroundGray
: Colors.white.withOpacity(0),
valueColor: AlwaysStoppedAnimation(isFetching
? CupertinoColors.lightBackgroundGray
: CupertinoColors.activeBlue),
strokeWidth: 2,
value: isFetching ? null : progress,
);
},
),
);
}
}</double></void></void></void></void></downloadcontroller></downloadcontroller></exampledownlo
adbutton>
Output
Conclusion
So far, we learned How to create download button in Flutter. We have
seen the 7 step process to create a download button. Thank you for
Reading the article. Hope you enjoying our content. Keep
visiting Flutter Agency for Flutter business app development solutions.
Source: https://flutteragency.com/create-download-button-flutter/

More Related Content

Similar to How to Create a Download Button in Flutter.pptx

How to add rich interactions to your prototype
How to add rich interactions to your prototypeHow to add rich interactions to your prototype
How to add rich interactions to your prototype
justinmind
 
VB.Net-Controls and events
VB.Net-Controls and eventsVB.Net-Controls and events
VB.Net-Controls and events
Prachi Sasankar
 
Session 5#
Session 5#Session 5#
Session 5#
Mohamed Samir
 
flutteragency-com-handling-events-and-user-input-in-flutter-.pdf
flutteragency-com-handling-events-and-user-input-in-flutter-.pdfflutteragency-com-handling-events-and-user-input-in-flutter-.pdf
flutteragency-com-handling-events-and-user-input-in-flutter-.pdf
Flutter Agency
 
Swingpre 150616004959-lva1-app6892
Swingpre 150616004959-lva1-app6892Swingpre 150616004959-lva1-app6892
Swingpre 150616004959-lva1-app6892
renuka gavli
 
Swing and AWT in java
Swing and AWT in javaSwing and AWT in java
Swing and AWT in java
Adil Mehmoood
 
A Guide to Creating a Great Custom Tailwind Sidebar
A Guide to Creating a Great Custom Tailwind SidebarA Guide to Creating a Great Custom Tailwind Sidebar
A Guide to Creating a Great Custom Tailwind Sidebar
RonDosh
 
How to draw dfd with multiple context levels
How to draw dfd with multiple context levelsHow to draw dfd with multiple context levels
How to draw dfd with multiple context levels
Curtis Tsang
 
Programming Without Coding Technology (PWCT) Getting Started - The Time Machine
Programming Without Coding Technology (PWCT)  Getting Started - The Time MachineProgramming Without Coding Technology (PWCT)  Getting Started - The Time Machine
Programming Without Coding Technology (PWCT) Getting Started - The Time Machine
Mahmoud Samir Fayed
 
Cis407 a ilab 1 web application development devry university
Cis407 a ilab 1 web application development devry universityCis407 a ilab 1 web application development devry university
Cis407 a ilab 1 web application development devry universitylhkslkdh89009
 
MAD mobile application development you can learn from here , we perform all c...
MAD mobile application development you can learn from here , we perform all c...MAD mobile application development you can learn from here , we perform all c...
MAD mobile application development you can learn from here , we perform all c...
harshalpatil183931
 
Flutter State Management Using GetX.pdf
Flutter State Management Using GetX.pdfFlutter State Management Using GetX.pdf
Flutter State Management Using GetX.pdf
Katy Slemon
 
Devices on the Web (2.0)
Devices on the Web (2.0)Devices on the Web (2.0)
Devices on the Web (2.0)
Gurpreet Singh
 
Cloud hub deployment
Cloud hub deploymentCloud hub deployment
Cloud hub deployment
sivachandra mandalapu
 
Migrating a large scale banking app to compose
Migrating a large scale banking app to composeMigrating a large scale banking app to compose
Migrating a large scale banking app to compose
Fatih Giris
 
A comprehensive guide on developing responsive and common react filter component
A comprehensive guide on developing responsive and common react filter componentA comprehensive guide on developing responsive and common react filter component
A comprehensive guide on developing responsive and common react filter component
Katy Slemon
 
Enhanced Task Details Page Released 2022
Enhanced Task Details Page Released 2022Enhanced Task Details Page Released 2022
Enhanced Task Details Page Released 2022
Orangescrum
 
Gui builder
Gui builderGui builder
Gui builderlearnt
 

Similar to How to Create a Download Button in Flutter.pptx (20)

How to add rich interactions to your prototype
How to add rich interactions to your prototypeHow to add rich interactions to your prototype
How to add rich interactions to your prototype
 
VB.Net-Controls and events
VB.Net-Controls and eventsVB.Net-Controls and events
VB.Net-Controls and events
 
Session 5#
Session 5#Session 5#
Session 5#
 
flutteragency-com-handling-events-and-user-input-in-flutter-.pdf
flutteragency-com-handling-events-and-user-input-in-flutter-.pdfflutteragency-com-handling-events-and-user-input-in-flutter-.pdf
flutteragency-com-handling-events-and-user-input-in-flutter-.pdf
 
Swingpre 150616004959-lva1-app6892
Swingpre 150616004959-lva1-app6892Swingpre 150616004959-lva1-app6892
Swingpre 150616004959-lva1-app6892
 
Swing and AWT in java
Swing and AWT in javaSwing and AWT in java
Swing and AWT in java
 
A Guide to Creating a Great Custom Tailwind Sidebar
A Guide to Creating a Great Custom Tailwind SidebarA Guide to Creating a Great Custom Tailwind Sidebar
A Guide to Creating a Great Custom Tailwind Sidebar
 
How to draw dfd with multiple context levels
How to draw dfd with multiple context levelsHow to draw dfd with multiple context levels
How to draw dfd with multiple context levels
 
Programming Without Coding Technology (PWCT) Getting Started - The Time Machine
Programming Without Coding Technology (PWCT)  Getting Started - The Time MachineProgramming Without Coding Technology (PWCT)  Getting Started - The Time Machine
Programming Without Coding Technology (PWCT) Getting Started - The Time Machine
 
Vb%20 tutorial
Vb%20 tutorialVb%20 tutorial
Vb%20 tutorial
 
Twitter trends
Twitter trendsTwitter trends
Twitter trends
 
Cis407 a ilab 1 web application development devry university
Cis407 a ilab 1 web application development devry universityCis407 a ilab 1 web application development devry university
Cis407 a ilab 1 web application development devry university
 
MAD mobile application development you can learn from here , we perform all c...
MAD mobile application development you can learn from here , we perform all c...MAD mobile application development you can learn from here , we perform all c...
MAD mobile application development you can learn from here , we perform all c...
 
Flutter State Management Using GetX.pdf
Flutter State Management Using GetX.pdfFlutter State Management Using GetX.pdf
Flutter State Management Using GetX.pdf
 
Devices on the Web (2.0)
Devices on the Web (2.0)Devices on the Web (2.0)
Devices on the Web (2.0)
 
Cloud hub deployment
Cloud hub deploymentCloud hub deployment
Cloud hub deployment
 
Migrating a large scale banking app to compose
Migrating a large scale banking app to composeMigrating a large scale banking app to compose
Migrating a large scale banking app to compose
 
A comprehensive guide on developing responsive and common react filter component
A comprehensive guide on developing responsive and common react filter componentA comprehensive guide on developing responsive and common react filter component
A comprehensive guide on developing responsive and common react filter component
 
Enhanced Task Details Page Released 2022
Enhanced Task Details Page Released 2022Enhanced Task Details Page Released 2022
Enhanced Task Details Page Released 2022
 
Gui builder
Gui builderGui builder
Gui builder
 

More from Flutter Agency

Flutter App Architecture with Riverpod: An Introduction
Flutter App Architecture with Riverpod: An IntroductionFlutter App Architecture with Riverpod: An Introduction
Flutter App Architecture with Riverpod: An Introduction
Flutter Agency
 
Key Steps To Follow For Google Play Store Closed Testing
Key Steps To Follow For Google Play Store Closed TestingKey Steps To Follow For Google Play Store Closed Testing
Key Steps To Follow For Google Play Store Closed Testing
Flutter Agency
 
Flutter for Web App Development: Exploring the Possibilities
Flutter for Web App Development: Exploring the PossibilitiesFlutter for Web App Development: Exploring the Possibilities
Flutter for Web App Development: Exploring the Possibilities
Flutter Agency
 
Use Of AI in Custom Application Development | Quick Guide
Use Of AI in Custom Application Development | Quick GuideUse Of AI in Custom Application Development | Quick Guide
Use Of AI in Custom Application Development | Quick Guide
Flutter Agency
 
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Flutter Agency
 
Use Firebase to Host Your Flutter App on the Web
Use Firebase to Host Your Flutter App on the WebUse Firebase to Host Your Flutter App on the Web
Use Firebase to Host Your Flutter App on the Web
Flutter Agency
 
Authentication Made Simple - Exploring QR Auto Login in Flutter.pdf
Authentication Made Simple - Exploring QR Auto Login in Flutter.pdfAuthentication Made Simple - Exploring QR Auto Login in Flutter.pdf
Authentication Made Simple - Exploring QR Auto Login in Flutter.pdf
Flutter Agency
 
User Enhancement With Animated Flutter Drawer
User Enhancement With Animated Flutter DrawerUser Enhancement With Animated Flutter Drawer
User Enhancement With Animated Flutter Drawer
Flutter Agency
 
Unit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Unit Testing in Flutter - From Workflow Essentials to Complex ScenariosUnit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Unit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Flutter Agency
 
Form Validation in Flutter with Laravel Form Validation Syntax
Form Validation in Flutter with Laravel Form Validation SyntaxForm Validation in Flutter with Laravel Form Validation Syntax
Form Validation in Flutter with Laravel Form Validation Syntax
Flutter Agency
 
How to Create Custom Shaders in Flutter?
How to Create Custom Shaders in Flutter?How to Create Custom Shaders in Flutter?
How to Create Custom Shaders in Flutter?
Flutter Agency
 
Benefits Of Hiring Flutter App Developers For Success
Benefits Of Hiring Flutter App Developers For SuccessBenefits Of Hiring Flutter App Developers For Success
Benefits Of Hiring Flutter App Developers For Success
Flutter Agency
 
12 Straightforward Steps to Build Your Video On-Demand App in 2024
12 Straightforward Steps to Build Your Video On-Demand App in 202412 Straightforward Steps to Build Your Video On-Demand App in 2024
12 Straightforward Steps to Build Your Video On-Demand App in 2024
Flutter Agency
 
Flutter's Advantages For Custom Application Development Services
Flutter's Advantages For Custom Application Development ServicesFlutter's Advantages For Custom Application Development Services
Flutter's Advantages For Custom Application Development Services
Flutter Agency
 
Hire Flutter Developers to Build Cross-Platform App Services - Stonesmentor
Hire Flutter Developers to Build Cross-Platform App Services - StonesmentorHire Flutter Developers to Build Cross-Platform App Services - Stonesmentor
Hire Flutter Developers to Build Cross-Platform App Services - Stonesmentor
Flutter Agency
 
A Guide For Recovering Your Failing App Project | Flutter Agency
A Guide For Recovering Your Failing App Project | Flutter AgencyA Guide For Recovering Your Failing App Project | Flutter Agency
A Guide For Recovering Your Failing App Project | Flutter Agency
Flutter Agency
 
Healthcare App-Development Company Fllutter Agency
Healthcare App-Development Company Fllutter AgencyHealthcare App-Development Company Fllutter Agency
Healthcare App-Development Company Fllutter Agency
Flutter Agency
 
Is Flutter Good for Web Development? | Flutter Agency
Is Flutter Good for Web Development? | Flutter AgencyIs Flutter Good for Web Development? | Flutter Agency
Is Flutter Good for Web Development? | Flutter Agency
Flutter Agency
 
Choosing App Development: Native, Hybrid, or Flutter Explained
Choosing App Development: Native, Hybrid, or Flutter ExplainedChoosing App Development: Native, Hybrid, or Flutter Explained
Choosing App Development: Native, Hybrid, or Flutter Explained
Flutter Agency
 
The Role of Digital Transformation in Healthcare - Flutter Agency.pdf
The Role of Digital Transformation in Healthcare - Flutter Agency.pdfThe Role of Digital Transformation in Healthcare - Flutter Agency.pdf
The Role of Digital Transformation in Healthcare - Flutter Agency.pdf
Flutter Agency
 

More from Flutter Agency (20)

Flutter App Architecture with Riverpod: An Introduction
Flutter App Architecture with Riverpod: An IntroductionFlutter App Architecture with Riverpod: An Introduction
Flutter App Architecture with Riverpod: An Introduction
 
Key Steps To Follow For Google Play Store Closed Testing
Key Steps To Follow For Google Play Store Closed TestingKey Steps To Follow For Google Play Store Closed Testing
Key Steps To Follow For Google Play Store Closed Testing
 
Flutter for Web App Development: Exploring the Possibilities
Flutter for Web App Development: Exploring the PossibilitiesFlutter for Web App Development: Exploring the Possibilities
Flutter for Web App Development: Exploring the Possibilities
 
Use Of AI in Custom Application Development | Quick Guide
Use Of AI in Custom Application Development | Quick GuideUse Of AI in Custom Application Development | Quick Guide
Use Of AI in Custom Application Development | Quick Guide
 
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
 
Use Firebase to Host Your Flutter App on the Web
Use Firebase to Host Your Flutter App on the WebUse Firebase to Host Your Flutter App on the Web
Use Firebase to Host Your Flutter App on the Web
 
Authentication Made Simple - Exploring QR Auto Login in Flutter.pdf
Authentication Made Simple - Exploring QR Auto Login in Flutter.pdfAuthentication Made Simple - Exploring QR Auto Login in Flutter.pdf
Authentication Made Simple - Exploring QR Auto Login in Flutter.pdf
 
User Enhancement With Animated Flutter Drawer
User Enhancement With Animated Flutter DrawerUser Enhancement With Animated Flutter Drawer
User Enhancement With Animated Flutter Drawer
 
Unit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Unit Testing in Flutter - From Workflow Essentials to Complex ScenariosUnit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Unit Testing in Flutter - From Workflow Essentials to Complex Scenarios
 
Form Validation in Flutter with Laravel Form Validation Syntax
Form Validation in Flutter with Laravel Form Validation SyntaxForm Validation in Flutter with Laravel Form Validation Syntax
Form Validation in Flutter with Laravel Form Validation Syntax
 
How to Create Custom Shaders in Flutter?
How to Create Custom Shaders in Flutter?How to Create Custom Shaders in Flutter?
How to Create Custom Shaders in Flutter?
 
Benefits Of Hiring Flutter App Developers For Success
Benefits Of Hiring Flutter App Developers For SuccessBenefits Of Hiring Flutter App Developers For Success
Benefits Of Hiring Flutter App Developers For Success
 
12 Straightforward Steps to Build Your Video On-Demand App in 2024
12 Straightforward Steps to Build Your Video On-Demand App in 202412 Straightforward Steps to Build Your Video On-Demand App in 2024
12 Straightforward Steps to Build Your Video On-Demand App in 2024
 
Flutter's Advantages For Custom Application Development Services
Flutter's Advantages For Custom Application Development ServicesFlutter's Advantages For Custom Application Development Services
Flutter's Advantages For Custom Application Development Services
 
Hire Flutter Developers to Build Cross-Platform App Services - Stonesmentor
Hire Flutter Developers to Build Cross-Platform App Services - StonesmentorHire Flutter Developers to Build Cross-Platform App Services - Stonesmentor
Hire Flutter Developers to Build Cross-Platform App Services - Stonesmentor
 
A Guide For Recovering Your Failing App Project | Flutter Agency
A Guide For Recovering Your Failing App Project | Flutter AgencyA Guide For Recovering Your Failing App Project | Flutter Agency
A Guide For Recovering Your Failing App Project | Flutter Agency
 
Healthcare App-Development Company Fllutter Agency
Healthcare App-Development Company Fllutter AgencyHealthcare App-Development Company Fllutter Agency
Healthcare App-Development Company Fllutter Agency
 
Is Flutter Good for Web Development? | Flutter Agency
Is Flutter Good for Web Development? | Flutter AgencyIs Flutter Good for Web Development? | Flutter Agency
Is Flutter Good for Web Development? | Flutter Agency
 
Choosing App Development: Native, Hybrid, or Flutter Explained
Choosing App Development: Native, Hybrid, or Flutter ExplainedChoosing App Development: Native, Hybrid, or Flutter Explained
Choosing App Development: Native, Hybrid, or Flutter Explained
 
The Role of Digital Transformation in Healthcare - Flutter Agency.pdf
The Role of Digital Transformation in Healthcare - Flutter Agency.pdfThe Role of Digital Transformation in Healthcare - Flutter Agency.pdf
The Role of Digital Transformation in Healthcare - Flutter Agency.pdf
 

Recently uploaded

Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfEnhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Jay Das
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 

Recently uploaded (20)

Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfEnhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 

How to Create a Download Button in Flutter.pptx

  • 1.
  • 2. How to Create a Download Button in Flutter? Apps are brimming with buttons that carry out long-running actions. A button, for example, could initiate a download, which initiates the download process, receives data over time, and ultimately grants access to the downloaded content. It’s useful to provide the user with the details of how a long-running procedure is progressing, and the button is a suitable spot to do so. This recipe will show you how to make a download button that changes visual states depending on the status of an app download. If you are having trouble implementing the solution, gets talented Flutter developers for hire from our company. Our developers are also experts in creating high-end mobile applications.
  • 3. • The steps involved in the process of creating a download button in the flutter development app are mentioned below: 1. Defining a new Stateful widget 2. Defining the possible visual states of the button 3. Display the shape of the button 4. Creating the display of the button’s text 5. Display a spinner while fetching the download 6. Display the progress percentage and a stop button while downloading 7. Add callbacks to button taps
  • 4. 1. Defining a new stateful widget The appearance of your button widget must alter over time. As a result, you’ll need to use a bespoke stateless widget to implement your button. Then, define a new stateless widget called DownloadButton. class DownloadButton extends StatelessWidget { const DownloadButton({ super.key, }); @override Widget build(BuildContext context) { // TODO: return const SizedBox(); } }
  • 5. 2. Defining the possible visual states of the button The current download status determines the visual display of the download button. After Defining the download’s possible states, update DownloadButton to accept a DownloadStatus and specify the duration for how long the button should fly from one visual state to the next. When designing a custom widget, you must select whether it receives all necessary information from its parent or if the Widget orchestrates the application’s activity internally. DownloadButton, for example, might get the existing DownloadStatus from its parent, or it may coordinate the download process within its State object.
  • 6. Rather than managing behavior within the Widget, the ideal solution for most widgets is to transfer relevant information into it from its parent. You assure increased utility for the Widget, simpler testing, and future modifications to application behavior by handing in all essential information. enum DownloadStatus { notDownloaded, fetchingDownload, downloading, downloaded, }
  • 7. 3. Display the shape of the button The form of the download button varies depending on the download state. During the notDownloaded and downloaded phases, the button shows a gray, rounded rectangle. During the fetchingDownload and downloading stages, the button shows a translucent circle. In the next step, Create an AnimatedContainer with a ShapeDecoration that shows a rounded rectangle or a circle based on the current DownloadStatus.
  • 8. Consider establishing the shape’s widget tree in a separate Stateless widget to keep the main construct() function simple while allowing for the modifications that will come later. Then, rather than constructing a function to return a widget, such as Widget _buildSomething(), always create a StatelessWidget or a StatefulWidget, which is faster. Now, the AnimatedContainer appears to be just a SizedBox child, but you don’t need to worry; we will resolve this state in another step.
  • 9. @immutable classButtonShapeWidget extends StatelessWidget { constButtonShapeWidget({ super.key, requiredthis.isDownloading, requiredthis.isDownloaded, requiredthis.isFetching, requiredthis.transitionDuration, }); final bool isDownloading; final bool isDownloaded; final bool isFetching; final Duration transitionDuration; @override Widget build(BuildContext context) { var shape = constShapeDecoration( shape: StadiumBorder(), color: CupertinoColors.lightBackgroundGray, );
  • 10. if (isDownloading || isFetching) { shape = ShapeDecoration( shape: constCircleBorder(), color: Colors.white.withOpacity(0.0), ); } return AnimatedContainer( duration: transitionDuration, curve: Curves.ease, width: double.infinity, decoration: shape, child: constSizedBox(), ); } }
  • 11. 4. Creating the display of the button’s text Different messages are displayed through the Download button in its different phases. The notDownloaded phase displays the GET option. The downloaded phases display the OPEN option for the users, while no text is displayed in the intermediate process. Add widgets to show text throughout each download step, and animate the opacity of the text between them. For example, in the button wrapper widget, make the text widget tree a child of the AnimatedContainer.
  • 12. return AnimatedContainer( duration: transitionDuration, curve: Curves.ease, width: double.infinity, decoration: shape, child: Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: AnimatedOpacity( duration: transitionDuration, opacity: isDownloading || isFetching ? 0.0 : 1.0, curve: Curves.ease, child: Text( isDownloaded ?'OPEN' : 'GET', textAlign: TextAlign.center, style: Theme.of(context).textTheme.button?.copyWith( fontWeight: FontWeight.bold, color: CupertinoColors.activBlue, ), ), ), ), );
  • 13. 5. Display a spinner while fetching the download The DownloadButton shows a radial spinner while fetchingDownload is in progress. This spinner transitions from notDownloaded to fetchingDownload. Install a radial spinner on top of the button form that fades in and out at appropriate intervals. The function Object() { [native code] } of the ButtonShapeWidget has been eliminated to focus on its build function and the Stack widget that we’ve created.
  • 14. @override Widget build(BuildContext context) { return GestureDetector( onTap: _onPressed, child: Stack( children: [ ButtonShapeWidget( transitionDuration: transitionDuration, isDownloaded: _isDownloaded, isDownloading: _isDownloading, isFetching: _isFetching, ), }
  • 15. Positioned.fill( child: AnimatedOpacity( duration: transitionDuration, opacity: _isDownloading || _isFetching ? 1.0 : 0.0, curve: Curves.ease, child: ProgressIndicatorWidget( downloadProgress: downloadProgress, isDownloading: _isDownloading, isFetching: _isFetching, ), ), ), ], ), ); }
  • 16. 6. Display the progress percentage and a stop button while downloading Following the retrieval, the downloading step is exactly that. The DownloadButton transforms the radial progress spinner with a rising radial progress bar during the downloading period. A stop button symbol is also displayed on the DownloadButton, allowing the user to halt an ongoing download. After adding an advancement property to the DownloadButton plugin, change the progress display to a radial toolbar during the downloading phase. Then, place a stop button icon in the center of the radial progress bar.
  • 17. @override Widget build(BuildContext context) { return GestureDetector( onTap: _onPressed, child: Stack( children: [ ButtonShapeWidget( transitionDuration: transitionDuration, isDownloaded: _isDownloaded, isDownloading: _isDownloading, isFetching: _isFetching, ), Positioned.fill( child: AnimatedOpacity( duration: transitionDuration, opacity: _isDownloading || _isFetching ? 1.0 : 0.0, curve: Curves.ease, child: Stack( alignment: Alignment.center,
  • 18. children: [ ProgressIndicatorWidget( downloadProgress: downloadProgress, isDownloading: _isDownloading, isFetching: _isFetching, ), if (_isDownloading) const Icon( Icons.stop, size: 14.0, color: CupertinoColors.activeBlue, ), ], ), ), ), ], ), ); }
  • 19. 7. Add callbacks to button taps The button behavior is the final thing that your DownloadButton requires. When the user clicks the button, it must do some action. Add callbacks for starting a download, canceling a download, and opening a download to the widget properties. Finally, use a GestureDetector widget to cover DownloadButton’s current widget tree and route the tap event to the relevant callback property.
  • 20. void _onPressed() { switch (status) { case DownloadStatus.notDownloaded: onDownload(); break; case DownloadStatus.fetchingDownload: // do nothing. break; case DownloadStatus.downloading: onCancel(); break; case DownloadStatus.downloaded: onOpen(); break; } }
  • 21. Now at the end of the process, you have a button that displays different information based on whatever phase it is in: not downloaded, seeking download, downloading phase, and downloaded completely. The user may tap to initiate a download, stop an ongoing download, and access a finished download by tapping. Let’s see a full example of DownloadButton:
  • 22. import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; void main() { runApp( const MaterialApp( home: ExampleDownloadButton(), debugShowCheckedModeBanner: false, ), ); } @immutable class ExampleDownloadButton extends StatefulWidget { const ExampleDownloadButton(); @override _ExampleDownloadButtonState createState() => _ExampleDownloadButtonState(); }
  • 23. class _ExampleDownloadButtonState extends State<exampledownloadbutton> { late final List<downloadcontroller> _downloadControllers; @override void initState() { super.initState(); _downloadControllers = List<downloadcontroller>.generate( 10, (index) => SimulatedDownloadController(onOpenDownload: () { _openDownload(index); }), ); } void _openDownload(int index) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Open PDF ${index + 1}'), ), ); }
  • 24. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Download Button')), body: ListView.separated( itemCount: _downloadControllers.length, separatorBuilder: (_, __) => const Divider(), itemBuilder: _buildListItem, ), ); } Widget _buildListItem(BuildContext context, int index) { final theme = Theme.of(context); final downloadController = _downloadControllers[index]; return ListTile( leading: const Icon(Icons.list_rounded), title: Text( 'Pdf ${index + 1}', overflow: TextOverflow.ellipsis, style: theme.textTheme.headline6, ),
  • 25. trailing: SizedBox( width: 96, child: AnimatedBuilder( animation: downloadController, builder: (context, child) { return DownloadButton( status: downloadController.downloadStatus, downloadProgress: downloadController.progress, onDownload: downloadController.startDownload, onCancel: downloadController.stopDownload, onOpen: downloadController.openDownload, ); }, ), ), ); } }
  • 26. enum DownloadStatus { notDownloaded, fetchingDownload, downloading, downloaded, } abstract class DownloadController implements ChangeNotifier { DownloadStatus get downloadStatus; double get progress; void startDownload(); void stopDownload(); void openDownload(); }
  • 27. class SimulatedDownloadController extends DownloadController with ChangeNotifier { SimulatedDownloadController({ DownloadStatus downloadStatus = DownloadStatus.notDownloaded, double progress = 0.0, required VoidCallback onOpenDownload, }) : _downloadStatus = downloadStatus, _progress = progress, _onOpenDownload = onOpenDownload; DownloadStatus _downloadStatus; @override DownloadStatus get downloadStatus => _downloadStatus; double _progress; @override double get progress => _progress; final VoidCallback _onOpenDownload; bool _isDownloading = false; @override void startDownload() { if (downloadStatus == DownloadStatus.notDownloaded) { _doSimulatedDownload(); } }
  • 28. @override void stopDownload() { if (_isDownloading) { _isDownloading = false; _downloadStatus = DownloadStatus.notDownloaded; _progress = 0.0; notifyListeners(); } } @override void openDownload() { if (downloadStatus == DownloadStatus.downloaded) { _onOpenDownload(); } }
  • 29. Future<void> _doSimulatedDownload() async { _isDownloading = true; _downloadStatus = DownloadStatus.fetchingDownload; notifyListeners(); // Wait a second to simulate fetch time. await Future<void>.delayed(const Duration(seconds: 1)); // If the user chose to cancel the download, stop the simulation. if (!_isDownloading) { return; } // Shift to the downloading phase. _downloadStatus = DownloadStatus.downloading; notifyListeners(); const downloadProgressStops = [0.0, 0.15, 0.45, 0.8, 1.0]; for (final stop in downloadProgressStops) { // Wait a second to simulate varying download speeds. // await Future<void>.delayed(const Duration(seconds: 1)); if (!_isDownloading) { return; }
  • 30. _progress = stop; notifyListeners(); } await Future<void>.delayed(const Duration(seconds: 1)); if (!_isDownloading) { return; } _downloadStatus = DownloadStatus.downloaded; _isDownloading = false; notifyListeners(); } } @immutable class DownloadButton extends StatelessWidget { const DownloadButton({ required this.status, this.downloadProgress = 0.0, required this.onDownload, required this.onCancel, required this.onOpen, this.transitionDuration = const Duration(milliseconds: 500), });
  • 31. final DownloadStatus status; final double downloadProgress; final VoidCallback onDownload; final VoidCallback onCancel; final VoidCallback onOpen; final Duration transitionDuration; bool get _isDownloading => status == DownloadStatus.downloading; bool get _isFetching => status == DownloadStatus.fetchingDownload; bool get _isDownloaded => status == DownloadStatus.downloaded; void _onPressed() { switch (status) { case DownloadStatus.notDownloaded: onDownload(); break; case DownloadStatus.fetchingDownload: // do nothing. break; case DownloadStatus.downloading: onCancel(); break; case DownloadStatus.downloaded: onOpen(); break; } }
  • 32. @override Widget build(BuildContext context) { return GestureDetector( onTap: _onPressed, child: Stack( children: [ ButtonShapeWidget( transitionDuration: transitionDuration, isDownloaded: _isDownloaded, isDownloading: _isDownloading, isFetching: _isFetching, ), Positioned.fill( child: AnimatedOpacity( duration: transitionDuration, opacity: _isDownloading || _isFetching ? 1.0 : 0.0, curve: Curves.ease, child: Stack( alignment: Alignment.center, children: [ ProgressIndicatorWidget( downloadProgress: downloadProgress, isDownloading: _isDownloading, isFetching: _isFetching, ),
  • 33. if (_isDownloading) const Icon( Icons.stop, size: 14, color: CupertinoColors.activeBlue, ), ], ), ), ), ], ), ); } }
  • 34. @immutable class ButtonShapeWidget extends StatelessWidget { const ButtonShapeWidget({ key, required this.isDownloading, required this.isDownloaded, required this.isFetching, required this.transitionDuration, }); final bool isDownloading; final bool isDownloaded; final bool isFetching; final Duration transitionDuration; @override Widget build(BuildContext context) { var shape = const ShapeDecoration( shape: StadiumBorder(), color: CupertinoColors.lightBackgroundGray, ); if (isDownloading || isFetching) { shape = ShapeDecoration( shape: const CircleBorder(), color: Colors.white.withOpacity(0), ); }
  • 35. return AnimatedContainer( duration: transitionDuration, curve: Curves.ease, width: double.infinity, decoration: shape, child: Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: AnimatedOpacity( duration: transitionDuration, opacity: isDownloading || isFetching ? 0.0 : 1.0, curve: Curves.ease, child: Text( isDownloaded ? 'OPEN' : 'GET', textAlign: TextAlign.center, style: Theme.of(context).textTheme.button?.copyWith( fontWeight: FontWeight.bold, color: CupertinoColors.activeBlue, ), ), ), ), ); } }
  • 36. @immutable class ProgressIndicatorWidget extends StatelessWidget { const ProgressIndicatorWidget({ key, required this.downloadProgress, required this.isDownloading, required this.isFetching, }); final double downloadProgress; final bool isDownloading; final bool isFetching; @override Widget build(BuildContext context) {
  • 37. return AspectRatio( aspectRatio: 1, child: TweenAnimationBuilder<double>( tween: Tween(begin: 0, end: downloadProgress), duration: const Duration(milliseconds: 200), builder: (context, progress, child) { return CircularProgressIndicator( backgroundColor: isDownloading ? CupertinoColors.lightBackgroundGray : Colors.white.withOpacity(0), valueColor: AlwaysStoppedAnimation(isFetching ? CupertinoColors.lightBackgroundGray : CupertinoColors.activeBlue), strokeWidth: 2, value: isFetching ? null : progress, ); }, ), ); } }</double></void></void></void></void></downloadcontroller></downloadcontroller></exampledownlo adbutton>
  • 39. Conclusion So far, we learned How to create download button in Flutter. We have seen the 7 step process to create a download button. Thank you for Reading the article. Hope you enjoying our content. Keep visiting Flutter Agency for Flutter business app development solutions. Source: https://flutteragency.com/create-download-button-flutter/