diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..3fa60e5
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,12 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Debug",
+ "request": "launch",
+ "type": "dart",
+ "program": "example/lib/main.dart",
+ "flutterMode": "debug",
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c23472f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,8 @@
+{
+ "[dart]": {
+ "editor.formatOnSave": true
+ },
+ "editor.codeActionsOnSave": {
+ "source.organizeImports": "explicit"
+ }
+}
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..ceb6ab0
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,25 @@
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ rules:
+ always_use_package_imports: true
+ always_declare_return_types: true
+ avoid_print: true
+ prefer_is_empty: true
+ prefer_is_not_empty: true
+ prefer_is_not_operator: true
+ require_trailing_commas: true
+ unnecessary_overrides: false
+ avoid_function_literals_in_foreach_calls: false
+ depend_on_referenced_packages: false
+
+analyzer:
+ errors:
+ always_use_package_imports: error
+ always_declare_return_types: error
+ avoid_print: error
+ prefer_is_empty: error
+ prefer_is_not_empty: error
+ prefer_is_not_operator: error
+ require_trailing_commas: error
+ invalid_use_of_protected_member: ignore
\ No newline at end of file
diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index 9625e10..7c56964 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 12.0
diff --git a/example/ios/Podfile b/example/ios/Podfile
index 50bb0cf..6656b4d 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+# platform :ios, '12.0'
# source '源地址'
source 'https://github.com/CocoaPods/Specs.git'
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index 9e53bc2..beb4dc3 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -139,6 +139,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
74E1176F028703D33774BD4F /* [CP] Embed Pods Frameworks */,
+ 58D7E035431BBB5EEAC7DC10 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -155,7 +156,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -235,6 +236,23 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
+ 58D7E035431BBB5EEAC7DC10 /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
74E1176F028703D33774BD4F /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -342,7 +360,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -420,7 +438,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -469,7 +487,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index c87d15a..5e31d3d 100644
--- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
show(
- {required BuildContext context,
- String title = '温馨提示',
- String? content,
- bool barrierDismissible = true,
- Color? barrierColor = Colors.black54,
- bool? useSafeArea,
- bool? useRootNavigator,
- Widget? contentWidget,
- List options = const [DialogAction(text: '知道了')]}) {
+ static Future show({
+ required BuildContext context,
+ String title = '温馨提示',
+ String? content,
+ bool barrierDismissible = true,
+ Color? barrierColor = Colors.black54,
+ bool? useSafeArea,
+ bool? useRootNavigator,
+ Widget? contentWidget,
+ List options = const [DialogAction(text: '知道了')],
+ }) {
return showDialog(
- context: context,
- barrierDismissible: barrierDismissible,
- barrierColor: barrierColor,
- useSafeArea: useSafeArea ?? true,
- useRootNavigator: useRootNavigator ?? true,
- builder: (BuildContext context) => HDialogWidget(
- title: title,
- content: content,
- contentWidget: contentWidget,
- options: options,
- isSheetStyle: false,
- ));
+ context: context,
+ barrierDismissible: barrierDismissible,
+ barrierColor: barrierColor,
+ useSafeArea: useSafeArea ?? true,
+ useRootNavigator: useRootNavigator ?? true,
+ builder: (BuildContext context) => HDialogWidget(
+ title: title,
+ content: content,
+ contentWidget: contentWidget,
+ options: options,
+ isSheetStyle: false,
+ ),
+ );
}
}
@@ -40,12 +41,13 @@ class DialogAction {
final T? actionValue;
final VoidCallback? onPressed;
- const DialogAction(
- {this.text,
- this.type = ActionType.positive,
- this.child,
- this.actionValue,
- this.onPressed});
+ const DialogAction({
+ this.text,
+ this.type = ActionType.positive,
+ this.child,
+ this.actionValue,
+ this.onPressed,
+ });
}
enum ActionType { delete, positive, negative }
@@ -71,54 +73,60 @@ class HDialogWidget extends StatelessWidget {
final DialogAction? bottomSheetCancel;
final bool isSheetStyle;
- const HDialogWidget(
- {Key? key,
- this.title,
- this.content,
- this.contentWidget,
- this.options = const [],
- this.bottomSheetCancel,
- this.isSheetStyle = false})
- : super(key: key);
+ const HDialogWidget({
+ super.key,
+ this.title,
+ this.content,
+ this.contentWidget,
+ this.options = const [],
+ this.bottomSheetCancel,
+ this.isSheetStyle = false,
+ });
@override
Widget build(BuildContext context) {
if (Platform.isIOS) {
return createIOSDialog(
- content: content,
- contentWidget: contentWidget,
- title: title,
- context: context,
- options: options);
+ content: content,
+ contentWidget: contentWidget,
+ title: title,
+ context: context,
+ options: options,
+ );
} else {
return createAndroidDialog(
- content: content,
- contentWidget: contentWidget,
- title: title,
- context: context,
- options: options);
+ content: content,
+ contentWidget: contentWidget,
+ title: title,
+ context: context,
+ options: options,
+ );
}
}
- AlertDialog createAndroidDialog(
- {required BuildContext context,
- String? title,
- String? content,
- required List> options,
- Widget? contentWidget}) {
+ AlertDialog createAndroidDialog({
+ required BuildContext context,
+ String? title,
+ String? content,
+ required List> options,
+ Widget? contentWidget,
+ }) {
final actions = options.map((option) {
return CupertinoButton(
- onPressed: () {
- Navigator.pop(context, option.actionValue);
- if (option.onPressed != null) option.onPressed!();
- },
- child: option.child ??
- Text(option.text ?? '',
- style: TextStyle(color: _getActionColor(option.type))));
+ onPressed: () {
+ Navigator.pop(context, option.actionValue);
+ if (option.onPressed != null) option.onPressed!();
+ },
+ child: option.child ??
+ Text(
+ option.text ?? '',
+ style: TextStyle(color: _getActionColor(option.type)),
+ ),
+ );
}).toList();
final dialog = AlertDialog(
- title: title==null ? null : Text(title),
- content: contentWidget != null && content==null
+ title: title == null ? null : Text(title),
+ content: contentWidget != null && content == null
? contentWidget
: Text(content ?? ''),
actions: actions,
@@ -126,12 +134,13 @@ class HDialogWidget extends StatelessWidget {
return dialog;
}
- Widget createIOSDialog(
- {required BuildContext context,
- String? title,
- String? content,
- Widget? contentWidget,
- required List> options}) {
+ Widget createIOSDialog({
+ required BuildContext context,
+ String? title,
+ String? content,
+ Widget? contentWidget,
+ required List> options,
+ }) {
final actions = options.map((option) {
return CupertinoButton(
onPressed: () {
@@ -139,12 +148,14 @@ class HDialogWidget extends StatelessWidget {
if (option.onPressed != null) option.onPressed!();
},
child: option.child ??
- Text(option.text ?? '',
- style: TextStyle(color: _getActionColor(option.type))),
+ Text(
+ option.text ?? '',
+ style: TextStyle(color: _getActionColor(option.type)),
+ ),
);
}).toList();
return CupertinoAlertDialog(
- title: title==null ? null : Text(title),
+ title: title == null ? null : Text(title),
content: contentWidget != null && content == null
? contentWidget
: Text(content ?? ''),
@@ -152,43 +163,52 @@ class HDialogWidget extends StatelessWidget {
);
}
- Widget createIOSSheetDialog(
- {required BuildContext context,
- String? title,
- String? content,
- Widget? contentWidget,
- required List> options,
- DialogAction? bottomSheetCancel}) {
+ Widget createIOSSheetDialog({
+ required BuildContext context,
+ String? title,
+ String? content,
+ Widget? contentWidget,
+ required List> options,
+ DialogAction? bottomSheetCancel,
+ }) {
final actions = options.map((option) {
return CupertinoActionSheetAction(
- onPressed: () {
- Navigator.pop(context, option.actionValue);
- if (option.onPressed != null) option.onPressed!();
- },
- child: option.child ??
- Text(option.text ?? '',
- style: TextStyle(color: _getActionColor(option.type))));
+ onPressed: () {
+ Navigator.pop(context, option.actionValue);
+ if (option.onPressed != null) option.onPressed!();
+ },
+ child: option.child ??
+ Text(
+ option.text ?? '',
+ style: TextStyle(color: _getActionColor(option.type)),
+ ),
+ );
}).toList();
final cancelButton = bottomSheetCancel == null
? null
: CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(context, bottomSheetCancel.actionValue);
- if (bottomSheetCancel.onPressed != null)
+ if (bottomSheetCancel.onPressed != null) {
bottomSheetCancel.onPressed!();
+ }
},
isDefaultAction: true,
child: bottomSheetCancel.child ??
- Text(bottomSheetCancel.text ?? '',
- style: TextStyle(
- color: _getActionColor(bottomSheetCancel.type))),
+ Text(
+ bottomSheetCancel.text ?? '',
+ style: TextStyle(
+ color: _getActionColor(bottomSheetCancel.type),
+ ),
+ ),
);
return CupertinoActionSheet(
- title: title==null ? null : Text(title),
- message: contentWidget != null && content==null
- ? contentWidget
- : Text(content ?? ''),
- actions: actions,
- cancelButton: cancelButton);
+ title: title == null ? null : Text(title),
+ message: contentWidget != null && content == null
+ ? contentWidget
+ : Text(content ?? ''),
+ actions: actions,
+ cancelButton: cancelButton,
+ );
}
-}
\ No newline at end of file
+}
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 6c5c87d..01a8258 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,17 +1,18 @@
-import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:dio/dio.dart';
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
+import 'package:image_gallery_saver_example/utils.dart';
import 'package:path_provider/path_provider.dart';
-import 'utils.dart';
-
-void main() => runApp(MyApp());
+void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
@override
Widget build(BuildContext context) {
return MaterialApp(
@@ -19,18 +20,20 @@ class MyApp extends StatelessWidget {
theme: ThemeData(
primarySwatch: Colors.blue,
),
- home: MyHomePage(),
+ home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
+ const MyHomePage({super.key});
+
@override
- _MyHomePageState createState() => _MyHomePageState();
+ State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
- GlobalKey _globalKey = GlobalKey();
+ final GlobalKey _globalKey = GlobalKey();
@override
void initState() {
@@ -41,64 +44,65 @@ class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
- appBar: AppBar(
- title: Text("Save image to gallery"),
- ),
- body: Center(
- child: Column(
- children: [
- SizedBox(height: 15),
- RepaintBoundary(
- key: _globalKey,
- child: Container(
- alignment: Alignment.center,
- width: 300,
- height: 300,
- color: Colors.blue,
- ),
- ),
- Container(
- padding: EdgeInsets.only(top: 15),
- child: ElevatedButton(
- onPressed: _saveLocalImage,
- child: Text("Save Local Image"),
- ),
+ appBar: AppBar(
+ title: const Text("Save image to gallery"),
+ ),
+ body: Center(
+ child: Column(
+ children: [
+ const SizedBox(height: 15),
+ RepaintBoundary(
+ key: _globalKey,
+ child: Container(
+ alignment: Alignment.center,
width: 300,
- height: 44,
+ height: 300,
+ color: Colors.blue,
),
- Container(
- padding: EdgeInsets.only(top: 15),
- child: ElevatedButton(
- onPressed: _saveNetworkImage,
- child: Text("Save Network Image"),
- ),
- width: 300,
- height: 44,
+ ),
+ Container(
+ padding: const EdgeInsets.only(top: 15),
+ width: 300,
+ height: 44,
+ child: ElevatedButton(
+ onPressed: _saveLocalImage,
+ child: const Text("Save Local Image"),
),
- Container(
- padding: EdgeInsets.only(top: 15),
- child: ElevatedButton(
- onPressed: _saveNetworkGifFile,
- child: Text("Save Network Gif Image"),
- ),
- width: 300,
- height: 44,
+ ),
+ Container(
+ padding: const EdgeInsets.only(top: 15),
+ width: 300,
+ height: 44,
+ child: ElevatedButton(
+ onPressed: _saveNetworkImage,
+ child: const Text("Save Network Image"),
),
- Container(
- padding: EdgeInsets.only(top: 15),
- child: ElevatedButton(
- onPressed: _saveNetworkVideoFile,
- child: Text("Save Network Video"),
- ),
- width: 300,
- height: 44,
+ ),
+ Container(
+ padding: const EdgeInsets.only(top: 15),
+ width: 300,
+ height: 44,
+ child: ElevatedButton(
+ onPressed: _saveNetworkGifFile,
+ child: const Text("Save Network Gif Image"),
),
- ],
- ),
- ));
+ ),
+ Container(
+ padding: const EdgeInsets.only(top: 15),
+ width: 300,
+ height: 44,
+ child: ElevatedButton(
+ onPressed: _saveNetworkVideoFile,
+ child: const Text("Save Network Video"),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
}
- _saveLocalImage() async {
+ void _saveLocalImage() async {
RenderRepaintBoundary boundary =
_globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
@@ -107,45 +111,61 @@ class _MyHomePageState extends State {
if (byteData != null) {
final result =
await ImageGallerySaver.saveImage(byteData.buffer.asUint8List());
- print(result);
+ if (kDebugMode) {
+ print(result);
+ }
Utils.toast(result.toString());
}
}
- _saveNetworkImage() async {
+ void _saveNetworkImage() async {
var response = await Dio().get(
- "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=a62e824376d98d1069d40a31113eb807/838ba61ea8d3fd1fc9c7b6853a4e251f94ca5f46.jpg",
- options: Options(responseType: ResponseType.bytes));
+ "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=a62e824376d98d1069d40a31113eb807/838ba61ea8d3fd1fc9c7b6853a4e251f94ca5f46.jpg",
+ options: Options(responseType: ResponseType.bytes),
+ );
final result = await ImageGallerySaver.saveImage(
- Uint8List.fromList(response.data),
- quality: 60,
- name: "hello");
- print(result);
+ Uint8List.fromList(response.data),
+ quality: 60,
+ name: "hello",
+ );
+ if (kDebugMode) {
+ print(result);
+ }
Utils.toast("$result");
}
- _saveNetworkGifFile() async {
+ void _saveNetworkGifFile() async {
var appDocDir = await getTemporaryDirectory();
- String savePath = appDocDir.path + "/temp.gif";
+ String savePath = "${appDocDir.path}/temp.gif";
String fileUrl =
"https://hyjdoc.oss-cn-beijing.aliyuncs.com/hyj-doc-flutter-demo-run.gif";
await Dio().download(fileUrl, savePath);
final result =
await ImageGallerySaver.saveFile(savePath, isReturnPathOfIOS: true);
- print(result);
+ if (kDebugMode) {
+ print(result);
+ }
Utils.toast("$result");
}
- _saveNetworkVideoFile() async {
+ void _saveNetworkVideoFile() async {
var appDocDir = await getTemporaryDirectory();
- String savePath = appDocDir.path + "/temp.mp4";
+ String savePath = "${appDocDir.path}/temp.mp4";
String fileUrl =
"https://s3.cn-north-1.amazonaws.com.cn/mtab.kezaihui.com/video/ForBiggerBlazes.mp4";
- await Dio().download(fileUrl, savePath, onReceiveProgress: (count, total) {
- print((count / total * 100).toStringAsFixed(0) + "%");
- });
+ await Dio().download(
+ fileUrl,
+ savePath,
+ onReceiveProgress: (count, total) {
+ if (kDebugMode) {
+ print("${(count / total * 100).toStringAsFixed(0)}%");
+ }
+ },
+ );
final result = await ImageGallerySaver.saveFile(savePath);
- print(result);
+ if (kDebugMode) {
+ print(result);
+ }
Utils.toast("$result");
}
}
diff --git a/example/lib/utils.dart b/example/lib/utils.dart
index e22e5a6..07cefb9 100644
--- a/example/lib/utils.dart
+++ b/example/lib/utils.dart
@@ -2,10 +2,9 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
+import 'package:image_gallery_saver_example/dialog.dart';
import 'package:permission_handler/permission_handler.dart';
-import 'dialog.dart';
-
class Utils {
static void toast(String msg) {
Fluttertoast.showToast(
@@ -24,13 +23,13 @@ class PermissionUtil {
/// 安卓权限
static List androidPermissions = [
// 在这里添加需要的权限
- Permission.storage
+ Permission.storage,
];
/// ios权限
static List iosPermissions = [
// 在这里添加需要的权限
- Permission.storage
+ Permission.storage,
];
static Future