Procházet zdrojové kódy

[feat]1.增加申请权限使用说明弹窗

云天逵 před 7 měsíci
rodič
revize
e799138203
2 změnil soubory, kde provedl 170 přidání a 134 odebrání
  1. 117 92
      lib/dialog/permission_dialog.dart
  2. 53 42
      lib/utils/image_picker_util.dart

+ 117 - 92
lib/dialog/permission_dialog.dart

@@ -1,3 +1,5 @@
+import 'dart:async';
+
 import 'package:flutter/Material.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
@@ -8,113 +10,136 @@ import '../resource/colors.gen.dart';
 import '../utils/styles.dart';
 
 class PermissionDialog {
-  static void showRequestDialog(
-      String titleTxt, Widget desc, String sureTxt, String permissionDesc,
-      {Future<bool> Function()? sureClick}) {
+  static Future<bool> showRequestDialog(
+    String titleTxt,
+    Widget desc,
+    String sureTxt,
+    String permissionDesc, {
+    Future<bool> Function()? sureClick,
+
+  }) async {
     const tag = 'PermissionDialog';
+    final completer = Completer<bool>();
+
     SmartDialog.show(
-        tag: tag,
-        alignment: const Alignment(0, 0),
-        builder: (_) {
-          return Container(
-              width: 300.w,
-              decoration: BoxDecoration(
-                color: Colors.white,
-                borderRadius: BorderRadius.circular(12),
-              ),
-              child: Stack(
-                children: [
-                  Container(
-                    padding: EdgeInsets.symmetric(horizontal: 19.w),
-                    child: IntrinsicHeight(
-                      child: Column(
-                        children: [
-                          SizedBox(height: 20.h),
-                          Text(titleTxt,
+      tag: tag,
+      alignment: const Alignment(0, 0),
+      builder: (_) {
+        return Container(
+          width: 300.w,
+          decoration: BoxDecoration(
+            color: Colors.white,
+            borderRadius: BorderRadius.circular(12),
+          ),
+          child: Stack(
+            children: [
+              Container(
+                padding: EdgeInsets.symmetric(horizontal: 19.w),
+                child: IntrinsicHeight(
+                  child: Column(
+                    children: [
+                      SizedBox(height: 20.h),
+                      Text(
+                        titleTxt,
+                        style: TextStyle(
+                          fontWeight: FontWeight.bold,
+                          fontSize: 18.sp,
+                          color: Colors.black,
+                        ),
+                      ),
+                      SizedBox(height: 14.h),
+                      desc,
+                      SizedBox(height: 30.h),
+                      GestureDetector(
+                        onTap: () async {
+                          if (sureClick != null) {
+                            // 显示权限说明
+                            Get.snackbar(
+                              '权限请求',
+                              permissionDesc,
+                              animationDuration: Duration(milliseconds: 0),
+                              snackPosition: SnackPosition.TOP,
+                              backgroundColor: Colors.black.withOpacity(0.8),
+                              colorText: Colors.white,
+                              duration: null,
+                            );
+                            // 权限请求逻辑
+                            bool shouldDismiss = await sureClick();
+
+                            Get.closeAllSnackbars();
+
+                            if (shouldDismiss) {
+                              SmartDialog.dismiss(tag: tag);
+                              completer.complete(true);
+                            } else {
+                              // 保持弹窗,等待用户操作
+                              completer.complete(false);
+                            }
+                          } else {
+                            SmartDialog.dismiss(tag: tag);
+                            completer.complete(true);
+                          }
+                        },
+                        child: Container(
+                          decoration: Styles.getActivateButtonDecoration(50.r),
+                          width: 130.w,
+                          height: 40.w,
+                          child: Center(
+                            child: Text(
+                              sureTxt,
                               style: TextStyle(
-                                  fontWeight: FontWeight.bold,
-                                  fontSize: 18.sp,
-                                  color: Colors.black)),
-                          SizedBox(height: 14.h),
-                          desc,
-                          SizedBox(height: 30.h),
-                          GestureDetector(
-                            onTap: () async {
-                              if (sureClick != null) {
-                                Get.snackbar(
-                                  animationDuration: Duration(milliseconds: 0),
-                                  '权限请求',
-                                  permissionDesc,
-                                  snackPosition: SnackPosition.TOP,
-                                  backgroundColor:
-                                      Colors.black.withOpacity(0.8),
-                                  colorText: Colors.white,
-                                  duration:
-                                      null, // 设置 duration 为 null,使得 Snackbar 持久显示
-                                );
-                                bool shouldDismiss = await sureClick();
-                                // 显示一个Snackbar,提示用户权限请求的原因
-                                Get.closeAllSnackbars();
-                                if (shouldDismiss) {
-                                  SmartDialog.dismiss(tag: tag);
-                                }
-                                // close snackbar
-                              }
-                            },
-                            child: Container(
-                              decoration: Styles.getActivateButtonDecoration(50.r),
-                              width: 130.w,
-                              height: 40.w,
-                              child: Center(
-                                child: Text(sureTxt,
-                                    style: TextStyle(
-                                        fontSize: 16.sp, color: Colors.white)),
+                                fontSize: 16.sp,
+                                color: Colors.white,
                               ),
                             ),
                           ),
-                          SizedBox(height: 24.h),
-                        ],
+                        ),
                       ),
-                    ),
+                      SizedBox(height: 24.h),
+                    ],
                   ),
-                  Positioned(
-                    top: 17.w,
-                    right: 18.w,
-                    child: GestureDetector(
-                      onTap: () {
-                        SmartDialog.dismiss(tag: tag);
-                      },
-                      child:  Assets.images.iconCustomDialogClose.image(
-                        width: 24.w,
-                        height: 24.w,
-                      ),
-                    ),
-                  )
-                ],
-              ));
-        });
-  }
+                ),
+              ),
+              Positioned(
+                top: 17.w,
+                right: 18.w,
+                child: GestureDetector(
+                  onTap: () {
+                    SmartDialog.dismiss(tag: tag);
+                    completer.complete(false); // 用户主动关闭
+                  },
+                  child: Assets.images.iconCustomDialogClose.image(
+                    width: 24.w,
+                    height: 24.w,
+                  ),
+                ),
+              ),
+            ],
+          ),
+        );
+      },
+    );
 
+    return completer.future;
+  }
 
   static Widget buildStorageView() {
     return RichText(
       textAlign: TextAlign.center,
       text: TextSpan(
-          style: TextStyle(fontSize: 15.sp, color: ColorName.black80),
-          children: const <TextSpan>[
-            TextSpan(
-              text: '使用该功能App需要访问您设备权限',
-            ),
-            TextSpan(
-                text: '“照片和媒体”',
-                style: TextStyle(
-                    fontWeight: FontWeight.bold, color: ColorName.black90)),
-            TextSpan(
-              text: ',开启权限后,您即可上传图片并体验相关服务。',
+        style: TextStyle(fontSize: 15.sp, color: ColorName.black80),
+        children: const <TextSpan>[
+          TextSpan(text: '使用该功能App需要访问您设备权限'),
+          TextSpan(
+            text: '“照片和媒体”',
+            style: TextStyle(
+              fontWeight: FontWeight.bold,
+              color: ColorName.black90,
             ),
-          ]),
+          ),
+          TextSpan(text: ',开启权限后,您即可上传图片并体验相关服务。'),
+        ],
+      ),
     );
   }
-
-
 }

+ 53 - 42
lib/utils/image_picker_util.dart

@@ -10,11 +10,11 @@ import '../dialog/permission_dialog.dart';
 import '../resource/colors.gen.dart';
 import '../resource/string.gen.dart';
 import 'package:permission_handler/permission_handler.dart';
+
 /// 本地选择图片工具类
 class ImagePickerUtil {
   static final Color _themeColor = ColorName.colorBrand;
 
-
   /// 请求图片权限(适配 iOS / Android)
   static Future<bool> requestPermissionExtend() async {
     if (Platform.isAndroid) {
@@ -74,60 +74,74 @@ class ImagePickerUtil {
       return status.isPermanentlyDenied;
     }
   }
+
   /// 选择图片
   static Future<List<AssetEntity>?> pickImage(
-      BuildContext context, {
-        required int maxAssetsCount,
-        List<AssetEntity> selectedAssets = const [],
-      }) async {
-
+    BuildContext context, {
+    required int maxAssetsCount,
+    List<AssetEntity> selectedAssets = const [],
+  }) async {
     bool isAllow = await ImagePickerUtil.hasPermission();
     if (!isAllow) {
-
-      PermissionDialog.showRequestDialog(
+      bool shouldProceed = await PermissionDialog.showRequestDialog(
         StringName.permissionDialogTitle,
         PermissionDialog.buildStorageView(),
         StringName.permissionDialogAuthorize,
         "使用该功能App需要访问您设备“照片和媒体”权限,开启权限后,您可以上传图片使用该功能使用",
         sureClick: () async {
-          bool isGranted = await ImagePickerUtil.requestPermissionExtend();
-          if (isGranted) {
-            await pickImage(context, maxAssetsCount: maxAssetsCount, selectedAssets: selectedAssets);
-            return true;
-          } else {
-            if (await ImagePickerUtil.isPermissionPermanentlyDenied()) {
-              Future.delayed(const Duration(milliseconds: 400), () {
-                AppSettingUtil.jumpSystemAppSetting();
-              });
-            }
-            ToastUtil.show(StringName.pickerImagePermissionDeniedTip);
-            return false;
+          bool granted = await ImagePickerUtil.requestPermissionExtend();
+          if (!granted &&
+              await ImagePickerUtil.isPermissionPermanentlyDenied()) {
+            Future.delayed(const Duration(milliseconds: 400), () {
+              AppSettingUtil.jumpSystemAppSetting();
+            });
           }
+          return granted;
         },
       );
-      return null;
+      if (shouldProceed) {
+        return await pickImage(
+          context,
+          maxAssetsCount: maxAssetsCount,
+          selectedAssets: selectedAssets,
+        );
+      } else {
+        ToastUtil.show(StringName.pickerImagePermissionDeniedTip);
+        return null;
+      }
     }
     // 2. 权限已授权,打开选择器
     try {
       return await AssetPicker.pickAssets(
-        context,
-        pickerConfig: AssetPickerConfig(
-          maxAssets: maxAssetsCount,
-          selectedAssets: selectedAssets,
-          textDelegate: const CustomChineseDelegate(),
-          pickerTheme: AssetPicker.themeData(
-            _themeColor,
-            light: false,
-          ),
-          specialPickerType: SpecialPickerType.noPreview,
-          requestType: RequestType.image,
-          dragToSelect: false,
-          pathNameBuilder: (AssetPathEntity path) => switch (path) {
-            final p when p.isAll => StringName.recently,
-            _ => path.name,
-          },
-        ),
-      ) ??
+            context,
+            pickerConfig: AssetPickerConfig(
+              // 最大选择数量
+              maxAssets: maxAssetsCount,
+              // 已选择的图片列表
+              selectedAssets: selectedAssets,
+              // 自定义按钮文字
+              textDelegate: const CustomChineseDelegate(),
+              // 主题
+              pickerTheme: AssetPicker.themeData(
+                // 主题色
+                _themeColor,
+                // 深色默认
+                light: false,
+              ),
+              // 设置为不能预览的模式
+              specialPickerType: SpecialPickerType.noPreview,
+              // 只能选取图片类型
+              requestType: RequestType.image,
+              // 关闭拽托选择
+              dragToSelect: false,
+              // 实现最近相册的名字显示
+              pathNameBuilder:
+                  (AssetPathEntity path) => switch (path) {
+                    final p when p.isAll => StringName.recently,
+                    _ => path.name,
+                  },
+            ),
+          ) ??
           [];
     } catch (e) {
       if (e is StateError) {
@@ -143,7 +157,6 @@ class ImagePickerUtil {
     return null;
   }
 
-
   /// 跳转到图片预览
   static Future<List<AssetEntity>> goImagePreview(
     BuildContext context,
@@ -189,5 +202,3 @@ class CustomChineseDelegate extends AssetPickerTextDelegate {
   @override
   String get confirm => StringName.nextStep;
 }
-
-