flutter_download_button 1.0.2 copy "flutter_download_button: ^1.0.2" to clipboard
flutter_download_button: ^1.0.2 copied to clipboard

You can download any file and open file

πŸ“„ README.md #

Flutter Download Button #

A highly customizable download button widget for Flutter with progress indication, extensive styling options, and file management capabilities.

Version Flutter License

✨ Features #

  • 🎨 Fully Customizable - 30+ customization properties
  • πŸ“Š Real-time Progress - Animated download progress indication
  • πŸ”„ Pause/Resume - Support for canceling downloads
  • πŸ“ File Management - Built-in utilities for file operations
  • 🎯 Easy Integration - Simple controller pattern
  • πŸ“± Pre-built Components - Ready-to-use list item widgets
  • 🎭 Multiple Presets - Material, Cupertino, Minimal, and Rounded styles
  • πŸš€ Smooth Animations - Beautiful transitions between states

πŸ“¦ Installation #

Add this to your pubspec.yaml:

dependencies:
flutter_download_button: ^1.0.2

Then run:

flutter pub get

Android Setup #

Add in Manifest

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Go to Android/app/main/res

1. Create xml package
2. Create file_paths.xml file

Add this code in file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="." />
    <files-path name="files" path="." />
    <cache-path name="cache" path="." />
    <external-files-path name="external_files_path" path="." />
    <external-cache-path name="external_cache_path" path="." />
</paths>

iOS Setup #

Add in Info.plist

	<!-- FILE SHARING CONFIGURATION -->
	<key>UIFileSharingEnabled</key>
	<true/>

	<key>LSSupportsOpeningDocumentsInPlace</key>
	<true/>

	<key>NSPhotoLibraryUsageDescription</key>
	<string>We need access to save and view downloaded files</string>

	<!-- DOCUMENT TYPES -->
	<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeName</key>
			<string>PDF Document</string>
			<key>LSHandlerRank</key>
			<string>Alternate</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>com.adobe.pdf</string>
			</array>
		</dict>
		<dict>
			<key>CFBundleTypeName</key>
			<string>Image</string>
			<key>LSHandlerRank</key>
			<string>Alternate</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>public.image</string>
				<string>public.jpeg</string>
				<string>public.png</string>
			</array>
		</dict>
		<dict>
			<key>CFBundleTypeName</key>
			<string>Text Document</string>
			<key>LSHandlerRank</key>
			<string>Alternate</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>public.text</string>
				<string>public.plain-text</string>
			</array>
		</dict>
	</array>

πŸš€ Quick Start #

Create custom UI #

import 'package:flutter/material.dart';
import 'package:flutter_download_button/flutter_download_button.dart';

/// A customizable list item widget that includes a download button.
class CustomizableDownloadListItem extends StatelessWidget {
  /// Creates a new [CustomizableDownloadListItem].
  const CustomizableDownloadListItem({
    super.key,
    required this.title,
    required this.subtitle,
    required this.downloadController,
    this.leading,
    this.onTap,
    this.config = const DownloadButtonConfig(),
    this.titleStyle,
    this.subtitleStyle,
    this.buttonWidth = 96,
  });

  final String title;
  final String subtitle;
  final DownloadController downloadController;
  final Widget? leading;
  final VoidCallback? onTap;
  final DownloadButtonConfig config;
  final TextStyle? titleStyle;
  final TextStyle? subtitleStyle;
  final double buttonWidth;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return ListTile(
      leading: leading ?? const _DefaultIcon(),
      title: Text(
        title,
        overflow: TextOverflow.ellipsis,
        style: titleStyle ?? theme.textTheme.titleLarge,
      ),
      subtitle: Text(
        subtitle,
        overflow: TextOverflow.ellipsis,
        style: subtitleStyle ?? theme.textTheme.bodySmall,
      ),
      trailing: SizedBox(
        width: buttonWidth,
        child: AnimatedBuilder(
          animation: downloadController,
          builder: (context, child) {
            return CustomizableDownloadButton(
              status: downloadController.downloadStatus,
              downloadProgress: downloadController.progress,
              onDownload: downloadController.startDownload,
              onCancel: downloadController.stopDownload,
              onOpen: downloadController.openDownload,
              config: config,
            );
          },
        ),
      ),
      onTap: onTap,
    );
  }
}

class _DefaultIcon extends StatelessWidget {
  const _DefaultIcon();

  @override
  Widget build(BuildContext context) {
    return const AspectRatio(
      aspectRatio: 1,
      child: FittedBox(
        child: SizedBox(
          width: 80,
          height: 80,
          child: DecoratedBox(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.red, Colors.blue],
              ),
              borderRadius: BorderRadius.all(Radius.circular(20)),
            ),
            child: Center(
              child: Icon(
                Icons.file_download,
                color: Colors.white,
                size: 40,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

main.dart #

import 'package:flutter/material.dart';
import 'package:customizable_download_button/customizable_download_button.dart';

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late RealDownloadController _controller;

  @override
  void initState() {
    super.initState();
    _controller = RealDownloadController(
      fileName: 'sample.pdf',
      downloadUrl: 'https://example.com/file.pdf',
      onOpenDownload: () => DownloadService.openFile('sample.pdf'),
    );
    _controller.checkFileExists();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SizedBox(
          width: 120,
          child: AnimatedBuilder(
            animation: _controller,
            builder: (context, child) {
              return CustomizableDownloadButton(
                status: _controller.downloadStatus,
                downloadProgress: _controller.progress,
                onDownload: _controller.startDownload,
                onCancel: _controller.stopDownload,
                onOpen: _controller.openDownload,
                config: DownloadButtonConfig.material, // Use preset
              );
            },
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

🎨 Customization #

Using Presets #

// Material Design
CustomizableDownloadButton(
config: DownloadButtonConfig.material,
// ...
)

// iOS Cupertino
CustomizableDownloadButton(
config: DownloadButtonConfig.cupertino,
// ...
)

// Minimal
CustomizableDownloadButton(
config: DownloadButtonConfig.minimal,
// ...
)

// Rounded
CustomizableDownloadButton(
config: DownloadButtonConfig.rounded,
// ...
)

Custom Configuration #

CustomizableDownloadButton(
    config: const DownloadButtonConfig(
    downloadText: 'DOWNLOAD',
    openText: 'OPEN',
    backgroundColor: Color(0xFF9C27B0),
    foregroundColor: Colors.white,
    progressColor: Colors.white,
    downloadIcon: Icons.cloud_download,
    openIcon: Icons.folder_open,
    elevation: 4.0,
    borderRadius: BorderRadius.all(Radius.circular(20)),
    buttonPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 20),
    minWidth: 120.0,
),
    status: controller.downloadStatus,
    downloadProgress: controller.progress,
    onDownload: controller.startDownload,
    onCancel: controller.stopDownload,
    onOpen: controller.openDownload)

πŸ“‹ All Configuration Options #

Property Type Default Description
downloadText String 'GET' Text when not downloaded
openText String 'OPEN' Text when downloaded
backgroundColor Color Color(0xFFE5E5EA) Button background
foregroundColor Color Color(0xFF007AFF) Text/icon color
progressColor Color Color(0xFF007AFF) Progress color
progressBackgroundColor Color Color(0xFFE5E5EA) Progress background
fetchingColor Color Color(0xFFE5E5EA) Fetching state color
textStyle TextStyle? null Custom text style
downloadIcon IconData? null Download state icon
openIcon IconData? null Open state icon
stopIcon IconData Icons.stop Stop icon
stopIconSize double 14.0 Stop icon size
buttonShape ShapeBorder? null Custom button shape
progressShape ShapeBorder? null Custom progress shape
transitionDuration Duration 500ms Animation duration
progressStrokeWidth double 2.0 Progress thickness
buttonPadding EdgeInsets 6v, 12h Button padding
minWidth double 96.0 Minimum width
borderRadius BorderRadius? null Border radius
elevation double 0.0 Button elevation
showStopIcon bool true Show stop icon
allowCancel bool true Allow canceling

🎯 Examples #

Outlined Button #

CustomizableDownloadButton(
config: const DownloadButtonConfig(
backgroundColor: Colors.transparent,
foregroundColor: Color(0xFF2196F3),
progressColor: Color(0xFF2196F3),
buttonShape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
side: BorderSide(color: Color(0xFF2196F3), width: 2),
)),
// ...
)

Button with Icons #

CustomizableDownloadButton(
config: const DownloadButtonConfig(
downloadIcon: Icons.cloud_download_outlined,
openIcon: Icons.folder_open_outlined,
backgroundColor: Color(0xFF4CAF50),
foregroundColor: Colors.white),
// ...
)

List Item Usage #

CustomizableDownloadListItem(
title: 'Document.pdf',
subtitle: '2.5 MB',
downloadController: controller,
config: DownloadButtonConfig.material,
buttonWidth: 120)

πŸ› οΈ Services #

// Check if file exists
final exists = await DownloadService.fileExists('file.pdf');

// Get file path
final path = await DownloadService.getFilePath('file.pdf');

// Open file
final result = await DownloadService.openFile('file.pdf');

// Delete file
await DownloadService.deleteFile('file.pdf');

🌍 Platform Support #

  • βœ… Android
  • βœ… iOS
  • βœ… macOS
  • βœ… Windows
  • βœ… Linux
  • βœ… Web

βš™οΈ Platform Setup #

Android #

Add to AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

iOS #

Add to Info.plist:

<key>NSPhotoLibraryUsageDescription</key>
<string>Need to save files</string>

πŸ“š Documentation #

For complete documentation, visit pub.flutter-io.cn

🀝 Contributing #

Contributions welcome! Please open an issue or PR.

πŸ“„ License #

MIT License - see LICENSE file

πŸ’¬ Support #


---

## πŸš€ How to Use This Package

### Step 1: Create Project Structure
```bash
mkdir flutter_download_button
cd flutter_download_button
mkdir -p lib/src/{models,controllers,widgets,services}
mkdir -p example/lib

Step 2: Copy All Files #

Copy each file from above into its respective location.

Step 3: Initialize #

flutter pub get
cd example
flutter pub get

Step 4: Run Example #

cd example
flutter run

Step 5: Publish (Optional) #

dart pub publish --dry-run
dart pub publish

πŸ“± Usage in Your App #

# pubspec.yaml
dependencies:
flutter_download_button: ^1.0.2
import 'package:flutter_download_button/flutter_download_button.dart';

// Use any preset
CustomizableDownloadButton(
config: DownloadButtonConfig.material,
// or create your own custom config
)

βœ… This package includes: #

  • βœ… Full customization with 30+ properties
  • βœ… 4 built-in style presets
  • βœ… 8 example implementations
  • βœ… Complete documentation
  • βœ… Type-safe configuration
  • βœ… Ready to publish to pub.flutter-io.cn