From a4e0788bd55c4345d4ad42d72f1bb43cb9ddb061 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Wed, 31 Mar 2021 17:45:35 +0900 Subject: [PATCH 01/11] =?UTF-8?q?1.=20=EB=8B=A5=ED=86=A1=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EA=B0=A4=EB=9F=AC=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=202.=20=EB=8B=A5=ED=86=A1=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80=203.=20statusbar,=20navbar=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EB=B3=80=EA=B2=BD=20disable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 - .../luck/pictureselector/MainActivity.java | 405 +-- .../pictureselector/style/PictureUtils.java | 140 + .../res/drawable/ic_back_white_normal.xml | 10 + app/src/main/res/drawable/ic_camera.xml | 14 + app/src/main/res/drawable/ic_check_normal.xml | 10 + .../main/res/drawable/ic_check_selected.xml | 10 + app/src/main/res/drawable/selector_check.xml | 6 + .../main/res/drawable/shape_circle_select.xml | 13 + app/src/main/res/values/colors.xml | 73 + app/src/main/res/values/strings.xml | 10 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- picture_library/src/main/AndroidManifest.xml | 73 +- .../luck/picture/lib/PictureBaseActivity.java | 28 +- .../picture/lib/PictureSelectionModel.java | 2906 +++++++++-------- .../lib/PictureSelectorDoctalkActivity.java | 2312 +++++++++++++ .../lib/adapter/PictureImageGridAdapter.java | 14 +- .../lib/config/PictureSelectionConfig.java | 1 + .../res/layout/picture_album_folder_item.xml | 18 +- .../src/main/res/layout/picture_doctalk.xml | 37 + .../src/main/res/layout/picture_title_bar.xml | 2 +- .../src/main/res/values-de-rDE/strings.xml | 64 - .../src/main/res/values-en/strings.xml | 64 - .../src/main/res/values-es-rES/string.xml | 64 - .../src/main/res/values-fr-rFR/strings.xml | 64 - .../src/main/res/values-ja-rJP/strings.xml | 63 - .../src/main/res/values-ko-rKR/strings.xml | 63 - .../src/main/res/values-vi-rVN/string.xml | 64 - .../src/main/res/values-zh-rTW/strings.xml | 63 - .../src/main/res/values-zh/strings.xml | 63 - .../src/main/res/values/strings.xml | 122 +- ucrop/src/main/res/values-de/strings.xml | 7 - ucrop/src/main/res/values-es-rES/string.xml | 7 - ucrop/src/main/res/values-fi/strings.xml | 8 - ucrop/src/main/res/values-fr/strings.xml | 6 - ucrop/src/main/res/values-it/strings.xml | 6 - ucrop/src/main/res/values-ja-rJP/strings.xml | 8 - ucrop/src/main/res/values-ko/strings.xml | 7 - ucrop/src/main/res/values-nl/strings.xml | 6 - ucrop/src/main/res/values-sk/strings.xml | 7 - ucrop/src/main/res/values-zh-rTW/strings.xml | 11 - ucrop/src/main/res/values-zh/strings.xml | 8 - ucrop/src/main/res/values/strings.xml | 23 +- 44 files changed, 4468 insertions(+), 2421 deletions(-) create mode 100644 app/src/main/java/com/luck/pictureselector/style/PictureUtils.java create mode 100644 app/src/main/res/drawable/ic_back_white_normal.xml create mode 100644 app/src/main/res/drawable/ic_camera.xml create mode 100644 app/src/main/res/drawable/ic_check_normal.xml create mode 100644 app/src/main/res/drawable/ic_check_selected.xml create mode 100644 app/src/main/res/drawable/selector_check.xml create mode 100644 app/src/main/res/drawable/shape_circle_select.xml create mode 100644 picture_library/src/main/java/com/luck/picture/lib/PictureSelectorDoctalkActivity.java create mode 100644 picture_library/src/main/res/layout/picture_doctalk.xml delete mode 100644 picture_library/src/main/res/values-de-rDE/strings.xml delete mode 100644 picture_library/src/main/res/values-en/strings.xml delete mode 100644 picture_library/src/main/res/values-es-rES/string.xml delete mode 100644 picture_library/src/main/res/values-fr-rFR/strings.xml delete mode 100644 picture_library/src/main/res/values-ja-rJP/strings.xml delete mode 100644 picture_library/src/main/res/values-ko-rKR/strings.xml delete mode 100644 picture_library/src/main/res/values-vi-rVN/string.xml delete mode 100644 picture_library/src/main/res/values-zh-rTW/strings.xml delete mode 100644 picture_library/src/main/res/values-zh/strings.xml delete mode 100755 ucrop/src/main/res/values-de/strings.xml delete mode 100644 ucrop/src/main/res/values-es-rES/string.xml delete mode 100755 ucrop/src/main/res/values-fi/strings.xml delete mode 100755 ucrop/src/main/res/values-fr/strings.xml delete mode 100755 ucrop/src/main/res/values-it/strings.xml delete mode 100755 ucrop/src/main/res/values-ja-rJP/strings.xml delete mode 100755 ucrop/src/main/res/values-ko/strings.xml delete mode 100755 ucrop/src/main/res/values-nl/strings.xml delete mode 100755 ucrop/src/main/res/values-sk/strings.xml delete mode 100755 ucrop/src/main/res/values-zh-rTW/strings.xml delete mode 100755 ucrop/src/main/res/values-zh/strings.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a56bc9054..cc71e6010 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,11 +6,8 @@ - - - diff --git a/app/src/main/java/com/luck/pictureselector/MainActivity.java b/app/src/main/java/com/luck/pictureselector/MainActivity.java index 7bcf9140f..509d0fee0 100644 --- a/app/src/main/java/com/luck/pictureselector/MainActivity.java +++ b/app/src/main/java/com/luck/pictureselector/MainActivity.java @@ -4,7 +4,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.Canvas; import android.graphics.Color; @@ -57,6 +56,7 @@ import com.luck.picture.lib.tools.ValueOf; import com.luck.pictureselector.adapter.GridImageAdapter; import com.luck.pictureselector.listener.DragListener; +import com.luck.pictureselector.style.PictureUtils; import java.io.File; import java.lang.ref.WeakReference; @@ -102,12 +102,210 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe private int animationMode = AnimationType.DEFAULT_ANIMATION; + private GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() { + @Override + public void onAddPicClick () { + boolean mode = cb_mode.isChecked(); + if (mode) { + + PictureSelector.create(MainActivity.this) + .openGallery(PictureMimeType.ofImage()) + .imageEngine(GlideEngine.createGlideEngine()) + .selectionMode(PictureConfig.MULTIPLE) + .isPageStrategy(true) + .setPictureUIStyle(PictureUtils.ofDoctalkStyle()) + .isCamera(true) + .isDoctalkStyle(true) + .maxSelectNum(3) + .minSelectNum(1) + .imageSpanCount(4) + .isEnableCrop(true) + .isPreviewImage(false) + .withAspectRatio(1, 1)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义 + .hideBottomControls(false) + .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 + .forResult(new MyResultCallback(mAdapter)); + + // // 进入相册 以下是例子:不需要的api可以不写 + // PictureSelector.create(MainActivity.this) + // .openGallery(chooseMode)// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio() + // .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 + // //.theme(themeId)// 主题样式设置 具体参考 values/styles 用法:R.style.picture.white.style v2.3.3后 建议使用setPictureStyle()动态方式 + // .setPictureUIStyle(mSelectorUIStyle) + // //.setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题 + // //.setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题 + // .setPictureWindowAnimationStyle(mWindowAnimationStyle)// 自定义相册启动退出动画 + // .isWeChatStyle(isWeChatStyle)// 是否开启微信图片选择风格 + // .isUseCustomCamera(cb_custom_camera.isChecked())// 是否使用自定义相机 + // .setLanguage(language)// 设置语言,默认中文 + // .isPageStrategy(cbPage.isChecked())// 是否开启分页策略 & 每页多少条;默认开启 + // .setRecyclerAnimationMode(animationMode)// 列表动画效果 + // .isWithVideoImage(true)// 图片和视频是否可以同选,只在ofAll模式下有效 + // .isMaxSelectEnabledMask(cbEnabledMask.isChecked())// 选择数到了最大阀值列表是否启用蒙层效果 + // //.isAutomaticTitleRecyclerTop(false)// 连续点击标题栏RecyclerView是否自动回到顶部,默认true + // //.loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用 + // //.setOutputCameraPath(createCustomCameraOutPath())// 自定义相机输出目录 + // //.setButtonFeatures(CustomCameraView.BUTTON_STATE_BOTH)// 设置自定义相机按钮状态 + // .maxSelectNum(maxSelectNum)// 最大图片选择数量 + // .minSelectNum(1)// 最小选择数量 + // .maxVideoSelectNum(1) // 视频最大选择数量 + // //.minVideoSelectNum(1)// 视频最小选择数量 + // //.closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 关闭在AndroidQ下获取图片或视频宽高相反自动转换 + // .imageSpanCount(4)// 每行显示个数 + // .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回 + // .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true + // .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认为false + // .isAndroidQTransform(false)// 是否需要处理Android Q 拷贝至应用沙盒的操作,只针对compress(false); && .isEnableCrop(false);有效,默认处理 + // .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)// 设置相册Activity方向,不设置默认使用系统 + // .isOriginalImageControl(cb_original.isChecked())// 是否显示原图控制按钮,如果设置为true则用户可以自由选择是否使用原图,压缩、裁剪功能将会失效 + // //.bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义视频播放回调控制,用户可以使用自己的视频播放界面 + // //.bindCustomPreviewCallback(new MyCustomPreviewInterfaceListener())// 自定义图片预览回调接口 + // //.bindCustomCameraInterfaceListener(new MyCustomCameraInterfaceListener())// 提供给用户的一些额外的自定义操作回调 + // //.cameraFileName(System.currentTimeMillis() +".jpg") // 重命名拍照文件名、如果是相册拍照则内部会自动拼上当前时间戳防止重复,注意这个只在使用相机时可以使用,如果使用相机又开启了压缩或裁剪 需要配合压缩和裁剪文件名api + // //.renameCompressFile(System.currentTimeMillis() +".jpg")// 重命名压缩文件名、 如果是多张压缩则内部会自动拼上当前时间戳防止重复 + // //.renameCropFileName(System.currentTimeMillis() + ".jpg")// 重命名裁剪文件名、 如果是多张裁剪则内部会自动拼上当前时间戳防止重复 + // .selectionMode(cb_choose_mode.isChecked() ? + // PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选 + // .isSingleDirectReturn(cb_single_back.isChecked())// 单选模式下是否直接返回,PictureConfig.SINGLE模式下有效 + // .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片 + // .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频 + // //.querySpecifiedFormatSuffix(PictureMimeType.ofJPEG())// 查询指定后缀格式资源 + // .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频 + // .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮 + // //.isMultipleSkipCrop(false)// 多图裁剪时是否支持跳过,默认支持 + // //.isMultipleRecyclerAnimation(false)// 多图裁剪底部列表显示动画效果 + // .isZoomAnim(true)// 图片列表点击 缩放效果 默认true + // //.imageFormat(PictureMimeType.PNG)// 拍照保存图片格式后缀,默认jpeg,Android Q使用PictureMimeType.PNG_Q + // .isEnableCrop(cb_crop.isChecked())// 是否裁剪 + // //.basicUCropConfig()//对外提供所有UCropOptions参数配制,但如果PictureSelector原本支持设置的还是会使用原有的设置 + // .isCompress(cb_compress.isChecked())// 是否压缩 + // //.compressQuality(80)// 图片压缩后输出质量 0~ 100 + // .synOrAsy(false)//同步true或异步false 压缩 默认同步 + // //.queryMaxFileSize(10)// 只查多少M以内的图片、视频、音频 单位M + // //.compressSavePath(getPath())//压缩图片保存地址 + // //.sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效 注:已废弃 + // //.glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度 注:已废弃 + // .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义 + // .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏,默认不显示 + // .isGif(cb_isGif.isChecked())// 是否显示gif图片 + // //.isWebp(false)// 是否显示webp图片,默认显示 + // //.isBmp(false)//是否显示bmp图片,默认显示 + // .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽 + // .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪 + // //.setCropDimmedColor(ContextCompat.getColor(getContext(), R.color.app_color_white))// 设置裁剪背景色值 + // //.setCircleDimmedBorderColor(ContextCompat.getColor(getApplicationContext(), R.color.app_color_white))// 设置圆形裁剪边框色值 + // //.setCircleStrokeWidth(3)// 设置圆形裁剪边框粗细 + // .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false + // .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false + // .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音 + // .selectionData(mAdapter.getData())// 是否传入已选图片 + // //.isDragFrame(false)// 是否可拖动裁剪框(固定) + // //.videoMinSecond(10)// 查询多少秒以内的视频 + // //.videoMaxSecond(15)// 查询多少秒以内的视频 + // //.recordVideoSecond(10)//录制视频秒数 默认60s + // //.isPreviewEggs(true)// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) + // //.cropCompressQuality(90)// 注:已废弃 改用cutOutQuality() + // .cutOutQuality(90)// 裁剪输出质量 默认100 + // .minimumCompressSize(100)// 小于多少kb的图片不压缩 + // //.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 + // //.cropImageWideHigh()// 裁剪宽高比,设置如果大于图片本身宽高则无效 + // //.rotateEnabled(false) // 裁剪是否可旋转图片 + // //.scaleEnabled(false)// 裁剪是否可放大缩小图片 + // //.videoQuality()// 视频录制质量 0 or 1 + // //.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code + // .forResult(new MyResultCallback(mAdapter)); + } + else { + // 单独拍照 + PictureSelector.create(MainActivity.this) + .openCamera(chooseMode)// 单独拍照,也可录像或也可音频 看你传入的类型是图片or视频 + .theme(themeId)// 主题样式设置 具体参考 values/styles + .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 + .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题 + .setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题 + .setPictureWindowAnimationStyle(mWindowAnimationStyle)// 自定义相册启动退出动画 + .maxSelectNum(maxSelectNum)// 最大图片选择数量 + .isUseCustomCamera(cb_custom_camera.isChecked())// 是否使用自定义相机 + //.setOutputCameraPath()// 自定义相机输出目录 + .minSelectNum(1)// 最小选择数量 + //.querySpecifiedFormatSuffix(PictureMimeType.ofPNG())// 查询指定后缀格式资源 + .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true + .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认false + .selectionMode(cb_choose_mode.isChecked() ? + PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选 + //.cameraFileName(System.currentTimeMillis() + ".jpg")// 使用相机时保存至本地的文件名称,注意这个只在拍照时可以使用 + //.renameCompressFile(System.currentTimeMillis() + ".jpg")// 重命名压缩文件名、 注意这个不要重复,只适用于单张图压缩使用 + //.renameCropFileName(System.currentTimeMillis() + ".jpg")// 重命名裁剪文件名、 注意这个不要重复,只适用于单张图裁剪使用 + .loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用 + .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片 + .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频 + .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频 + .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮 + .isEnableCrop(cb_crop.isChecked())// 是否裁剪 + //.basicUCropConfig()//对外提供所有UCropOptions参数配制,但如果PictureSelector原本支持设置的还是会使用原有的设置 + .isCompress(cb_compress.isChecked())// 是否压缩 + .compressQuality(60)// 图片压缩后输出质量 + .glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度 + .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义 + .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏,默认不显示 + .isGif(cb_isGif.isChecked())// 是否显示gif图片 + .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽 + .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪 + //.setCircleDimmedColor(ContextCompat.getColor(this, R.color.app_color_white))// 设置圆形裁剪背景色值 + //.setCircleDimmedBorderColor(ContextCompat.getColor(this, R.color.app_color_white))// 设置圆形裁剪边框色值 + //.setCircleStrokeWidth(3)// 设置圆形裁剪边框粗细 + .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false + .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false + .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音 + .selectionData(mAdapter.getData())// 是否传入已选图片 + //.isPreviewEggs(true)// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) + //.cropCompressQuality(90)// 废弃 改用cutOutQuality() + .cutOutQuality(90)// 裁剪输出质量 默认100 + .minimumCompressSize(100)// 小于100kb的图片不压缩 + //.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 + //.cropImageWideHigh()// 裁剪宽高比,设置如果大于图片本身宽高则无效 + //.rotateEnabled() // 裁剪是否可旋转图片 + //.scaleEnabled()// 裁剪是否可放大缩小图片 + //.videoQuality()// 视频录制质量 0 or 1 + //.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code + .forResult(new MyResultCallback(mAdapter)); + } + } + }; + + /** + * 重置 + */ + private void resetState () { + if (mDragListener != null) { + mDragListener.deleteState(false); + mDragListener.dragState(false); + } + isUpward = false; + } + + /** + * 清空缓存包括裁剪、压缩、AndroidQToPath所生成的文件,注意调用时机必须是处理完本身的业务逻辑后调用;非强制性 + */ + private void clearCache () { + // 清空图片缓存,包括裁剪、压缩后的图片 注意:必须要在上传完成后调用 必须要获取权限 + if (PermissionChecker.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + //PictureFileUtils.deleteCacheDirFile(this, PictureMimeType.ofImage()); + PictureFileUtils.deleteAllCacheDirFile(getContext()); + } + else { + PermissionChecker.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE); + } + } + @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { // 被回收 - } else { + } + else { clearCache(); } setContentView(R.layout.activity_main); @@ -210,18 +408,19 @@ protected void onCreate(Bundle savedInstanceState) { break; default: // 预览图片 可自定长按保存路径 -// PictureWindowAnimationStyle animationStyle = new PictureWindowAnimationStyle(); -// animationStyle.activityPreviewEnterAnimation = R.anim.picture_anim_up_in; -// animationStyle.activityPreviewExitAnimation = R.anim.picture_anim_down_out; - PictureSelector.create(MainActivity.this) - .themeStyle(R.style.picture_default_style) // xml设置主题 - .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题 - //.setPictureWindowAnimationStyle(animationStyle)// 自定义页面启动动画 - .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)// 设置相册Activity方向,不设置默认使用系统 - .isNotPreviewDownload(true)// 预览图片长按是否可以下载 - //.bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义播放回调控制,用户可以使用自己的视频播放界面 - .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 - .openExternalPreview(position, selectList); + // PictureWindowAnimationStyle animationStyle = new PictureWindowAnimationStyle(); + // animationStyle.activityPreviewEnterAnimation = R.anim.picture_anim_up_in; + // animationStyle.activityPreviewExitAnimation = R.anim.picture_anim_down_out; + // PictureSelector.create(MainActivity.this) + // .themeStyle(R.style.picture_default_style) // xml设置主题 + // .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题 + // //.setPictureWindowAnimationStyle(animationStyle)// 自定义页面启动动画 + // .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)// 设置相册Activity方向,不设置默认使用系统 + // .isNotPreviewDownload(true)// 预览图片长按是否可以下载 + // //.bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义播放回调控制,用户可以使用自己的视频播放界面 + // .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 + // .openExternalPreview(position, selectList); + break; } } @@ -397,182 +596,6 @@ public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView. BroadcastAction.ACTION_DELETE_PREVIEW_POSITION); } - /** - * 重置 - */ - private void resetState() { - if (mDragListener != null) { - mDragListener.deleteState(false); - mDragListener.dragState(false); - } - isUpward = false; - } - - /** - * 清空缓存包括裁剪、压缩、AndroidQToPath所生成的文件,注意调用时机必须是处理完本身的业务逻辑后调用;非强制性 - */ - private void clearCache() { - // 清空图片缓存,包括裁剪、压缩后的图片 注意:必须要在上传完成后调用 必须要获取权限 - if (PermissionChecker.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - //PictureFileUtils.deleteCacheDirFile(this, PictureMimeType.ofImage()); - PictureFileUtils.deleteAllCacheDirFile(getContext()); - } else { - PermissionChecker.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE); - } - } - - private GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() { - @Override - public void onAddPicClick() { - boolean mode = cb_mode.isChecked(); - if (mode) { - // 进入相册 以下是例子:不需要的api可以不写 - PictureSelector.create(MainActivity.this) - .openGallery(chooseMode)// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio() - .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 - //.theme(themeId)// 主题样式设置 具体参考 values/styles 用法:R.style.picture.white.style v2.3.3后 建议使用setPictureStyle()动态方式 - .setPictureUIStyle(mSelectorUIStyle) - //.setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题 - //.setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题 - .setPictureWindowAnimationStyle(mWindowAnimationStyle)// 自定义相册启动退出动画 - .isWeChatStyle(isWeChatStyle)// 是否开启微信图片选择风格 - .isUseCustomCamera(cb_custom_camera.isChecked())// 是否使用自定义相机 - .setLanguage(language)// 设置语言,默认中文 - .isPageStrategy(cbPage.isChecked())// 是否开启分页策略 & 每页多少条;默认开启 - .setRecyclerAnimationMode(animationMode)// 列表动画效果 - .isWithVideoImage(true)// 图片和视频是否可以同选,只在ofAll模式下有效 - .isMaxSelectEnabledMask(cbEnabledMask.isChecked())// 选择数到了最大阀值列表是否启用蒙层效果 - //.isAutomaticTitleRecyclerTop(false)// 连续点击标题栏RecyclerView是否自动回到顶部,默认true - //.loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用 - //.setOutputCameraPath(createCustomCameraOutPath())// 自定义相机输出目录 - //.setButtonFeatures(CustomCameraView.BUTTON_STATE_BOTH)// 设置自定义相机按钮状态 - .maxSelectNum(maxSelectNum)// 最大图片选择数量 - .minSelectNum(1)// 最小选择数量 - .maxVideoSelectNum(1) // 视频最大选择数量 - //.minVideoSelectNum(1)// 视频最小选择数量 - //.closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 关闭在AndroidQ下获取图片或视频宽高相反自动转换 - .imageSpanCount(4)// 每行显示个数 - .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回 - .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true - .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认为false - .isAndroidQTransform(false)// 是否需要处理Android Q 拷贝至应用沙盒的操作,只针对compress(false); && .isEnableCrop(false);有效,默认处理 - .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)// 设置相册Activity方向,不设置默认使用系统 - .isOriginalImageControl(cb_original.isChecked())// 是否显示原图控制按钮,如果设置为true则用户可以自由选择是否使用原图,压缩、裁剪功能将会失效 - //.bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义视频播放回调控制,用户可以使用自己的视频播放界面 - //.bindCustomPreviewCallback(new MyCustomPreviewInterfaceListener())// 自定义图片预览回调接口 - //.bindCustomCameraInterfaceListener(new MyCustomCameraInterfaceListener())// 提供给用户的一些额外的自定义操作回调 - //.cameraFileName(System.currentTimeMillis() +".jpg") // 重命名拍照文件名、如果是相册拍照则内部会自动拼上当前时间戳防止重复,注意这个只在使用相机时可以使用,如果使用相机又开启了压缩或裁剪 需要配合压缩和裁剪文件名api - //.renameCompressFile(System.currentTimeMillis() +".jpg")// 重命名压缩文件名、 如果是多张压缩则内部会自动拼上当前时间戳防止重复 - //.renameCropFileName(System.currentTimeMillis() + ".jpg")// 重命名裁剪文件名、 如果是多张裁剪则内部会自动拼上当前时间戳防止重复 - .selectionMode(cb_choose_mode.isChecked() ? - PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选 - .isSingleDirectReturn(cb_single_back.isChecked())// 单选模式下是否直接返回,PictureConfig.SINGLE模式下有效 - .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片 - .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频 - //.querySpecifiedFormatSuffix(PictureMimeType.ofJPEG())// 查询指定后缀格式资源 - .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频 - .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮 - //.isMultipleSkipCrop(false)// 多图裁剪时是否支持跳过,默认支持 - //.isMultipleRecyclerAnimation(false)// 多图裁剪底部列表显示动画效果 - .isZoomAnim(true)// 图片列表点击 缩放效果 默认true - //.imageFormat(PictureMimeType.PNG)// 拍照保存图片格式后缀,默认jpeg,Android Q使用PictureMimeType.PNG_Q - .isEnableCrop(cb_crop.isChecked())// 是否裁剪 - //.basicUCropConfig()//对外提供所有UCropOptions参数配制,但如果PictureSelector原本支持设置的还是会使用原有的设置 - .isCompress(cb_compress.isChecked())// 是否压缩 - //.compressQuality(80)// 图片压缩后输出质量 0~ 100 - .synOrAsy(false)//同步true或异步false 压缩 默认同步 - //.queryMaxFileSize(10)// 只查多少M以内的图片、视频、音频 单位M - //.compressSavePath(getPath())//压缩图片保存地址 - //.sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效 注:已废弃 - //.glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度 注:已废弃 - .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义 - .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏,默认不显示 - .isGif(cb_isGif.isChecked())// 是否显示gif图片 - //.isWebp(false)// 是否显示webp图片,默认显示 - //.isBmp(false)//是否显示bmp图片,默认显示 - .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽 - .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪 - //.setCropDimmedColor(ContextCompat.getColor(getContext(), R.color.app_color_white))// 设置裁剪背景色值 - //.setCircleDimmedBorderColor(ContextCompat.getColor(getApplicationContext(), R.color.app_color_white))// 设置圆形裁剪边框色值 - //.setCircleStrokeWidth(3)// 设置圆形裁剪边框粗细 - .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false - .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false - .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音 - .selectionData(mAdapter.getData())// 是否传入已选图片 - //.isDragFrame(false)// 是否可拖动裁剪框(固定) - //.videoMinSecond(10)// 查询多少秒以内的视频 - //.videoMaxSecond(15)// 查询多少秒以内的视频 - //.recordVideoSecond(10)//录制视频秒数 默认60s - //.isPreviewEggs(true)// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) - //.cropCompressQuality(90)// 注:已废弃 改用cutOutQuality() - .cutOutQuality(90)// 裁剪输出质量 默认100 - .minimumCompressSize(100)// 小于多少kb的图片不压缩 - //.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 - //.cropImageWideHigh()// 裁剪宽高比,设置如果大于图片本身宽高则无效 - //.rotateEnabled(false) // 裁剪是否可旋转图片 - //.scaleEnabled(false)// 裁剪是否可放大缩小图片 - //.videoQuality()// 视频录制质量 0 or 1 - //.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code - .forResult(new MyResultCallback(mAdapter)); - } else { - // 单独拍照 - PictureSelector.create(MainActivity.this) - .openCamera(chooseMode)// 单独拍照,也可录像或也可音频 看你传入的类型是图片or视频 - .theme(themeId)// 主题样式设置 具体参考 values/styles - .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项 - .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题 - .setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题 - .setPictureWindowAnimationStyle(mWindowAnimationStyle)// 自定义相册启动退出动画 - .maxSelectNum(maxSelectNum)// 最大图片选择数量 - .isUseCustomCamera(cb_custom_camera.isChecked())// 是否使用自定义相机 - //.setOutputCameraPath()// 自定义相机输出目录 - .minSelectNum(1)// 最小选择数量 - //.querySpecifiedFormatSuffix(PictureMimeType.ofPNG())// 查询指定后缀格式资源 - .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true - .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认false - .selectionMode(cb_choose_mode.isChecked() ? - PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选 - //.cameraFileName(System.currentTimeMillis() + ".jpg")// 使用相机时保存至本地的文件名称,注意这个只在拍照时可以使用 - //.renameCompressFile(System.currentTimeMillis() + ".jpg")// 重命名压缩文件名、 注意这个不要重复,只适用于单张图压缩使用 - //.renameCropFileName(System.currentTimeMillis() + ".jpg")// 重命名裁剪文件名、 注意这个不要重复,只适用于单张图裁剪使用 - .loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用 - .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片 - .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频 - .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频 - .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮 - .isEnableCrop(cb_crop.isChecked())// 是否裁剪 - //.basicUCropConfig()//对外提供所有UCropOptions参数配制,但如果PictureSelector原本支持设置的还是会使用原有的设置 - .isCompress(cb_compress.isChecked())// 是否压缩 - .compressQuality(60)// 图片压缩后输出质量 - .glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度 - .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义 - .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏,默认不显示 - .isGif(cb_isGif.isChecked())// 是否显示gif图片 - .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽 - .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪 - //.setCircleDimmedColor(ContextCompat.getColor(this, R.color.app_color_white))// 设置圆形裁剪背景色值 - //.setCircleDimmedBorderColor(ContextCompat.getColor(this, R.color.app_color_white))// 设置圆形裁剪边框色值 - //.setCircleStrokeWidth(3)// 设置圆形裁剪边框粗细 - .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false - .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false - .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音 - .selectionData(mAdapter.getData())// 是否传入已选图片 - //.isPreviewEggs(true)// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) - //.cropCompressQuality(90)// 废弃 改用cutOutQuality() - .cutOutQuality(90)// 裁剪输出质量 默认100 - .minimumCompressSize(100)// 小于100kb的图片不压缩 - //.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 - //.cropImageWideHigh()// 裁剪宽高比,设置如果大于图片本身宽高则无效 - //.rotateEnabled() // 裁剪是否可旋转图片 - //.scaleEnabled()// 裁剪是否可放大缩小图片 - //.videoQuality()// 视频录制质量 0 or 1 - //.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code - .forResult(new MyResultCallback(mAdapter)); - } - } - }; - /** * 创建自定义拍照输出目录 * diff --git a/app/src/main/java/com/luck/pictureselector/style/PictureUtils.java b/app/src/main/java/com/luck/pictureselector/style/PictureUtils.java new file mode 100644 index 000000000..a8f6770b9 --- /dev/null +++ b/app/src/main/java/com/luck/pictureselector/style/PictureUtils.java @@ -0,0 +1,140 @@ +package com.luck.pictureselector.style; + +import android.content.Context; +import android.graphics.Color; + +import androidx.core.content.ContextCompat; + +import com.luck.picture.lib.app.IApp; +import com.luck.picture.lib.app.PictureAppMaster; +import com.luck.picture.lib.style.PictureParameterStyle; +import com.luck.picture.lib.style.PictureSelectorUIStyle; +import com.luck.pictureselector.R; + +public class PictureUtils { + + public static PictureSelectorUIStyle ofDoctalkStyle () { + PictureSelectorUIStyle uiStyle = new PictureSelectorUIStyle(); + + IApp app = PictureAppMaster.getInstance().getApp(); + Context context = app.getAppContext(); + if (context != null) { + + uiStyle.picture_statusBarBackgroundColor = ContextCompat.getColor(context, R.color.colorAccentDark); + uiStyle.picture_container_backgroundColor = ContextCompat.getColor(context, R.color.background_white); + + // uiStyle.picture_navBarColor = ContextCompat.getColor(context, R.color.background_gray); + + uiStyle.picture_check_style = R.drawable.selector_check; + + uiStyle.picture_top_leftBack = R.drawable.ic_back_white_normal; + uiStyle.picture_top_titleRightTextColor = new int[]{ContextCompat.getColor(context, R.color.text_white), ContextCompat.getColor(context, R.color.text_white)}; + uiStyle.picture_top_titleRightTextSize = 15; + uiStyle.picture_top_titleTextSize = 19; + uiStyle.picture_top_titleArrowUpDrawable = R.drawable.picture_icon_arrow_up; + uiStyle.picture_top_titleArrowDownDrawable = R.drawable.picture_icon_arrow_down; + uiStyle.picture_top_titleTextColor = ContextCompat.getColor(context, R.color.text_white); + uiStyle.picture_top_titleBarBackgroundColor = ContextCompat.getColor(context, R.color.colorAccent); + + uiStyle.picture_album_textSize = 15; + uiStyle.picture_album_backgroundStyle = R.drawable.picture_item_select_bg; + uiStyle.picture_album_textColor = ContextCompat.getColor(context, R.color.text_black); + uiStyle.picture_album_checkDotStyle = R.drawable.shape_circle_select; + + uiStyle.picture_bottom_previewTextSize = 13; + uiStyle.picture_bottom_previewTextColor = new int[]{ContextCompat.getColor(context, R.color.text_gray), ContextCompat.getColor(context, R.color.text_black)}; + + uiStyle.picture_bottom_completeRedDotTextSize = 11; + uiStyle.picture_bottom_completeTextSize = 13; + uiStyle.picture_bottom_completeRedDotTextColor = ContextCompat.getColor(context, R.color.text_white); + uiStyle.picture_bottom_completeRedDotBackground = R.drawable.shape_circle_select; + uiStyle.picture_bottom_completeTextColor = new int[]{ContextCompat.getColor(context, R.color.text_gray), ContextCompat.getColor(context, R.color.text_black)}; + uiStyle.picture_bottom_barBackgroundColor = ContextCompat.getColor(context, R.color.background_white); + + uiStyle.picture_adapter_item_camera_backgroundColor = ContextCompat.getColor(context, R.color.background_gray); + uiStyle.picture_adapter_item_camera_textColor = ContextCompat.getColor(context, R.color.text_white); + uiStyle.picture_adapter_item_camera_textSize = 15; + uiStyle.picture_adapter_item_camera_textTopDrawable = R.drawable.ic_camera; + + uiStyle.picture_adapter_item_textSize = 13; + uiStyle.picture_adapter_item_textColor = ContextCompat.getColor(context, R.color.text_white); + uiStyle.picture_adapter_item_video_textLeftDrawable = R.drawable.picture_icon_video; + uiStyle.picture_adapter_item_audio_textLeftDrawable = R.drawable.picture_icon_audio; + + uiStyle.picture_bottom_originalPictureTextSize = 13; + uiStyle.picture_bottom_originalPictureCheckStyle = R.drawable.picture_original_wechat_checkbox; + uiStyle.picture_bottom_originalPictureTextColor = ContextCompat.getColor(context, R.color.text_white); + uiStyle.picture_bottom_previewNormalText = R.string.picture_preview_num; + uiStyle.picture_bottom_originalPictureText = R.string.picture_original_image; + uiStyle.picture_bottom_completeDefaultText = R.string.picture_please_select; + uiStyle.picture_bottom_completeNormalText = R.string.picture_completed; + uiStyle.picture_adapter_item_camera_text = R.string.picture_take_picture; + uiStyle.picture_top_titleRightDefaultText = R.string.picture_done; + uiStyle.picture_bottom_previewDefaultText = R.string.picture_preview; + + // 如果文本内容设置(%1$d/%2$d),请开启true + uiStyle.isCompleteReplaceNum = true; + } + return uiStyle; + } + + + private PictureParameterStyle getNumStyle () { + // 相册主题 + PictureParameterStyle pictureParameterStyle = new PictureParameterStyle(); + + IApp app = PictureAppMaster.getInstance().getApp(); + Context context = app.getAppContext(); + if (context != null) { + // 是否改变状态栏字体颜色(黑白切换) + pictureParameterStyle.isChangeStatusBarFontColor = false; + // 是否开启右下角已完成(0/9)风格 + pictureParameterStyle.isOpenCompletedNumStyle = false; + // 是否开启类似QQ相册带数字选择风格 + pictureParameterStyle.isOpenCheckNumStyle = true; + // 相册状态栏背景色 + pictureParameterStyle.pictureStatusBarColor = Color.parseColor("#7D7DFF"); + // 相册列表标题栏背景色 + pictureParameterStyle.pictureTitleBarBackgroundColor = Color.parseColor("#7D7DFF"); + // 相册列表标题栏右侧上拉箭头 + pictureParameterStyle.pictureTitleUpResId = R.drawable.picture_icon_arrow_up; + // 相册列表标题栏右侧下拉箭头 + pictureParameterStyle.pictureTitleDownResId = R.drawable.picture_icon_arrow_down; + // 相册文件夹列表选中圆点 + pictureParameterStyle.pictureFolderCheckedDotStyle = R.drawable.picture_orange_oval; + // 相册返回箭头 + pictureParameterStyle.pictureLeftBackIcon = R.drawable.picture_icon_back; + // 标题栏字体颜色 + pictureParameterStyle.pictureTitleTextColor = ContextCompat.getColor(context, R.color.app_color_white); + // 相册右侧取消按钮字体颜色 废弃 改用.pictureRightDefaultTextColor和.pictureRightDefaultTextColor + pictureParameterStyle.pictureCancelTextColor = ContextCompat.getColor(context, R.color.app_color_white); + // 选择相册目录背景样式 + pictureParameterStyle.pictureAlbumStyle = R.drawable.picture_new_item_select_bg; + // 相册列表勾选图片样式 + pictureParameterStyle.pictureCheckedStyle = R.drawable.picture_checkbox_num_selector; + // 相册列表底部背景色 + pictureParameterStyle.pictureBottomBgColor = ContextCompat.getColor(context, R.color.picture_color_fa); + // 已选数量圆点背景样式 + pictureParameterStyle.pictureCheckNumBgStyle = R.drawable.picture_num_oval_blue; + // 相册列表底下预览文字色值(预览按钮可点击时的色值) + pictureParameterStyle.picturePreviewTextColor = ContextCompat.getColor(context, R.color.picture_color_blue); + // 相册列表底下不可预览文字色值(预览按钮不可点击时的色值) + pictureParameterStyle.pictureUnPreviewTextColor = ContextCompat.getColor(context, R.color.app_color_blue); + // 相册列表已完成色值(已完成 可点击色值) + pictureParameterStyle.pictureCompleteTextColor = ContextCompat.getColor(context, R.color.app_color_blue); + // 相册列表未完成色值(请选择 不可点击色值) + pictureParameterStyle.pictureUnCompleteTextColor = ContextCompat.getColor(context, R.color.app_color_blue); + // 预览界面底部背景色 + pictureParameterStyle.picturePreviewBottomBgColor = ContextCompat.getColor(context, R.color.picture_color_fa); + // 原图按钮勾选样式 需设置.isOriginalImageControl(true); 才有效 + pictureParameterStyle.pictureOriginalControlStyle = R.drawable.picture_original_blue_checkbox; + // 原图文字颜色 需设置.isOriginalImageControl(true); 才有效 + pictureParameterStyle.pictureOriginalFontColor = ContextCompat.getColor(context, R.color.app_color_blue); + // 外部预览界面删除按钮样式 + pictureParameterStyle.pictureExternalPreviewDeleteStyle = R.drawable.picture_icon_delete; + // 外部预览界面是否显示删除按钮 + pictureParameterStyle.pictureExternalPreviewGonePreviewDelete = true; + } + return pictureParameterStyle; + } +} diff --git a/app/src/main/res/drawable/ic_back_white_normal.xml b/app/src/main/res/drawable/ic_back_white_normal.xml new file mode 100644 index 000000000..8c689c9a8 --- /dev/null +++ b/app/src/main/res/drawable/ic_back_white_normal.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_camera.xml b/app/src/main/res/drawable/ic_camera.xml new file mode 100644 index 000000000..9b87a0891 --- /dev/null +++ b/app/src/main/res/drawable/ic_camera.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_check_normal.xml b/app/src/main/res/drawable/ic_check_normal.xml new file mode 100644 index 000000000..171302d87 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_normal.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_selected.xml b/app/src/main/res/drawable/ic_check_selected.xml new file mode 100644 index 000000000..01b6802c9 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_selected.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/selector_check.xml b/app/src/main/res/drawable/selector_check.xml new file mode 100644 index 000000000..708693de2 --- /dev/null +++ b/app/src/main/res/drawable/selector_check.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_circle_select.xml b/app/src/main/res/drawable/shape_circle_select.xml new file mode 100644 index 000000000..352b4ce1f --- /dev/null +++ b/app/src/main/res/drawable/shape_circle_select.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7f8604d60..e21c09cf6 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -15,4 +15,77 @@ #9b9b9b #E0FF6100 #FF0000 + + + #13bb00 + #0d8200 + #13bb00 + #13bb00 + #13bb00 + + #ff5edb + #84b000 + #00cd20 + #00cbcd + #2046e7 + #b612ea + #f88e06 + #ffc200 + + #F0F0F0 + #000000 + #AAAAAA + #FF4500 + + #FFFFFF + #000000 + #4a4a4a + #7A7A7A + #AAAAAA + #3e4759 + #647188 + #FFFFFF + #798bac + + #3F4558 + #FFFFFF + #f0f0f0 + #000000 + #647188 + #7A7A7A + #4a4a4a + #AAAAAA + #3e4759 + #FF4500 + #ff002c + + #f0f0f0 + + #FF7E00 + + #FFFFFF + #f0f0f0 + #d4dbe8 + #C6CFDF + #DADADA + #8f9fbf + #000000 + #FF5C78 + + #4460a0 + #13bb00 + #13bb00 + + #249676 + + #F8F8F8 + #5A5A5A + #2C2C2C + #7A7A7A + + #80000000 + #CABBBBBB + #80f2798d + #88000000 + #BBFFFFFF diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 376e359b8..fea2156a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ - PictureSelector - 拖动到此处删除 - 松手即可删除 - 发送 - 发送(%1$d/%2$d) + PictureSelector + 삭제하려면 여기로 드래그 하세요 + 삭제하기 + 확인 + 확인(%1$d/%2$d) diff --git a/build.gradle b/build.gradle index e0fadaf8e..c89560e61 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.2' + classpath 'com.android.tools.build:gradle:4.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8d8029e39..f6d4cc062 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Nov 16 20:22:07 CST 2020 +#Tue Mar 30 14:33:22 KST 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/picture_library/src/main/AndroidManifest.xml b/picture_library/src/main/AndroidManifest.xml index babf7f7f0..98ce0d32e 100644 --- a/picture_library/src/main/AndroidManifest.xml +++ b/picture_library/src/main/AndroidManifest.xml @@ -20,43 +20,46 @@ - - - + + + - - - - + + + + + - - - - + + + + { - if (!isFinishing()) { - dialog.dismiss(); - } - }); - dialog.show(); + new AlertDialog.Builder(getContext()) + .setMessage(content) + .setPositiveButton(R.string.picture_know, (dialog, which) -> { + }) + .show(); } } @@ -807,7 +801,7 @@ protected void showPromptDialog(String content) { /** * sort * - * @param imageFolders + * @param imageFolders image folder list */ protected void sortFolder(List imageFolders) { Collections.sort(imageFolders, (lhs, rhs) -> { diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java index 40ccb9714..c718f5091 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java @@ -42,1427 +42,1487 @@ */ public class PictureSelectionModel { - private PictureSelectionConfig selectionConfig; - private PictureSelector selector; - - public PictureSelectionModel(PictureSelector selector, int chooseMode) { - this.selector = selector; - selectionConfig = PictureSelectionConfig.getCleanInstance(); - selectionConfig.chooseMode = chooseMode; - } - - public PictureSelectionModel(PictureSelector selector, int chooseMode, boolean camera) { - this.selector = selector; - selectionConfig = PictureSelectionConfig.getCleanInstance(); - selectionConfig.camera = camera; - selectionConfig.chooseMode = chooseMode; - } - - /** - * @param themeStyleId PictureSelector Theme style - * @return PictureSelectionModel - * Use {@link R.style#picture_default_style#picture_Sina_style#picture_white_style#picture_QQ_style#picture_WeChat_style} - */ - public PictureSelectionModel theme(@StyleRes int themeStyleId) { - selectionConfig.themeStyleId = themeStyleId; - return this; - } - - /** - * Setting PictureSelector UI Style - * - * @param uiStyle

- * {@link PictureSelectorUIStyle} - *

- * @return - */ - public PictureSelectionModel setPictureUIStyle(PictureSelectorUIStyle uiStyle) { - if (uiStyle != null) { - PictureSelectionConfig.uiStyle = uiStyle; - if (!selectionConfig.isWeChatStyle) { - selectionConfig.isWeChatStyle = PictureSelectionConfig.uiStyle.isNewSelectStyle; - } - } - return this; - } - - /** - * @param locale Language - * @return PictureSelectionModel - */ - public PictureSelectionModel setLanguage(int language) { - selectionConfig.language = language; - return this; - } - - /** - * Change the desired orientation of this activity. If the activity - * is currently in the foreground or otherwise impacting the screen - * orientation, the screen will immediately be changed (possibly causing - * the activity to be restarted). Otherwise, this will be used the next - * time the activity is visible. - * - * @param requestedOrientation An orientation constant as used in - * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}. - */ - public PictureSelectionModel setRequestedOrientation(int requestedOrientation) { - selectionConfig.requestedOrientation = requestedOrientation; - return this; - } - - /** - * @param engine Image Load the engine - * @return Use {@link .imageEngine()}. - */ - @Deprecated - public PictureSelectionModel loadImageEngine(ImageEngine engine) { - if (PictureSelectionConfig.imageEngine != engine) { - PictureSelectionConfig.imageEngine = engine; - } - return this; - } - - /** - * @param engine Image Load the engine - * @return - */ - public PictureSelectionModel imageEngine(ImageEngine engine) { - if (PictureSelectionConfig.imageEngine != engine) { - PictureSelectionConfig.imageEngine = engine; - } - return this; - } - - /** - * Only for Android version Q - *

- * 已废弃,没有存在的意义了,之前主要是为了解决在华为10系统上一直loading问题 - *

- * - * @param cacheResourcesEngine Image Cache - * @return - */ - @Deprecated - public PictureSelectionModel loadCacheResourcesCallback(CacheResourcesEngine cacheResourcesEngine) { - if (SdkVersionUtils.checkedAndroid_Q()) { - if (PictureSelectionConfig.cacheResourcesEngine != cacheResourcesEngine) { - PictureSelectionConfig.cacheResourcesEngine = new WeakReference<>(cacheResourcesEngine).get(); - } - } - return this; - } - - /** - * @param selectionMode PictureSelector Selection model and PictureConfig.MULTIPLE or PictureConfig.SINGLE - * @return - */ - public PictureSelectionModel selectionMode(int selectionMode) { - selectionConfig.selectionMode = selectionMode; - return this; - } - - /** - * @param isWeChatStyle Select style with or without WeChat enabled - * @return - */ - public PictureSelectionModel isWeChatStyle(boolean isWeChatStyle) { - selectionConfig.isWeChatStyle = isWeChatStyle; - return this; - } - - /** - * @param isUseCustomCamera Whether to use a custom camera - * @return - */ - public PictureSelectionModel isUseCustomCamera(boolean isUseCustomCamera) { - selectionConfig.isUseCustomCamera = Build.VERSION.SDK_INT > KITKAT && isUseCustomCamera; - return this; - } - - /** - * @param callback Provide video playback control,Users are free to customize the video display interface - * @return - */ - public PictureSelectionModel bindCustomPlayVideoCallback(OnVideoSelectedPlayCallback callback) { - PictureSelectionConfig.customVideoPlayCallback = new WeakReference<>(callback).get(); - return this; - } - - /** - * @param callback Custom preview callback function - * @return - */ - public PictureSelectionModel bindCustomPreviewCallback(OnCustomImagePreviewCallback callback) { - PictureSelectionConfig.onCustomImagePreviewCallback = new WeakReference<>(callback).get(); - return this; - } - - /** - * # The developer provides an additional callback interface to the user where the user can perform some custom actions - * {link 如果是自定义相机则必须使用.startActivityForResult(this,PictureConfig.REQUEST_CAMERA);方式启动否则PictureSelector处理不了相机后的回调} - * - * @param listener - * @return Use ${bindCustomCameraInterfaceListener} - */ - @Deprecated - public PictureSelectionModel bindPictureSelectorInterfaceListener(OnCustomCameraInterfaceListener listener) { - PictureSelectionConfig.onCustomCameraInterfaceListener = new WeakReference<>(listener).get(); - return this; - } - - /** - * # The developer provides an additional callback interface to the user where the user can perform some custom actions - * {link 如果是自定义相机则必须使用.startActivityForResult(this,PictureConfig.REQUEST_CAMERA);方式启动否则PictureSelector处理不了相机后的回调} - * - * @param listener - * @return - */ - public PictureSelectionModel bindCustomCameraInterfaceListener(OnCustomCameraInterfaceListener listener) { - PictureSelectionConfig.onCustomCameraInterfaceListener = new WeakReference<>(listener).get(); - return this; - } - - /** - * @param buttonFeatures Set the record button function - * # 具体参考 CustomCameraView.BUTTON_STATE_BOTH、BUTTON_STATE_ONLY_CAPTURE、BUTTON_STATE_ONLY_RECORDER - * @return - */ - public PictureSelectionModel setButtonFeatures(int buttonFeatures) { - selectionConfig.buttonFeatures = buttonFeatures; - return this; - } - - /** - * @param enableCrop Do you want to start cutting ? - * @return Use {link .isEnableCrop()} - */ - @Deprecated - public PictureSelectionModel enableCrop(boolean enableCrop) { - selectionConfig.enableCrop = enableCrop; - return this; - } - - /** - * @param enableCrop Do you want to start cutting ? - * @return - */ - public PictureSelectionModel isEnableCrop(boolean enableCrop) { - selectionConfig.enableCrop = enableCrop; - return this; - } - - /** - * @param uCropOptions UCrop parameter configuration is provided - * @return - */ - public PictureSelectionModel basicUCropConfig(UCropOptions uCropOptions) { - selectionConfig.uCropOptions = uCropOptions; - return this; - } - - /** - * @param isMultipleSkipCrop Whether multiple images can be skipped when cropping - * @return - */ - public PictureSelectionModel isMultipleSkipCrop(boolean isMultipleSkipCrop) { - selectionConfig.isMultipleSkipCrop = isMultipleSkipCrop; - return this; - } - - - /** - * @param enablePreviewAudio {@link use isEnablePreviewAudio} - * @return - */ - @Deprecated - public PictureSelectionModel enablePreviewAudio(boolean enablePreviewAudio) { - selectionConfig.enablePreviewAudio = enablePreviewAudio; - return this; - } - - /** - * @param enablePreviewAudio - * @return - */ - public PictureSelectionModel isEnablePreviewAudio(boolean enablePreviewAudio) { - selectionConfig.enablePreviewAudio = enablePreviewAudio; - return this; - } - - /** - * @param freeStyleCropEnabled Crop frame is move ? - * @return - */ - public PictureSelectionModel freeStyleCropEnabled(boolean freeStyleCropEnabled) { - selectionConfig.freeStyleCropEnabled = freeStyleCropEnabled; - return this; - } - - /** - * @param scaleEnabled Crop frame is zoom ? - * @return - */ - public PictureSelectionModel scaleEnabled(boolean scaleEnabled) { - selectionConfig.scaleEnabled = scaleEnabled; - return this; - } - - /** - * @param rotateEnabled Crop frame is rotate ? - * @return - */ - public PictureSelectionModel rotateEnabled(boolean rotateEnabled) { - selectionConfig.rotateEnabled = rotateEnabled; - return this; - } - - /** - * @param circleDimmedLayer Circular head cutting - * @return - */ - public PictureSelectionModel circleDimmedLayer(boolean circleDimmedLayer) { - selectionConfig.circleDimmedLayer = circleDimmedLayer; - return this; - } - - /** - * @param circleDimmedColor setCircleDimmedColor - * @return - */ - @Deprecated - public PictureSelectionModel setCircleDimmedColor(int circleDimmedColor) { - selectionConfig.circleDimmedColor = circleDimmedColor; - return this; - } - - /** - * @param dimmedColor - * @return - */ - public PictureSelectionModel setCropDimmedColor(int dimmedColor) { - selectionConfig.circleDimmedColor = dimmedColor; - return this; - } - - /** - * @param circleDimmedBorderColor setCircleDimmedBorderColor - * @return - */ - public PictureSelectionModel setCircleDimmedBorderColor(int circleDimmedBorderColor) { - selectionConfig.circleDimmedBorderColor = circleDimmedBorderColor; - return this; - } - - /** - * @param circleStrokeWidth setCircleStrokeWidth - * @return - */ - public PictureSelectionModel setCircleStrokeWidth(int circleStrokeWidth) { - selectionConfig.circleStrokeWidth = circleStrokeWidth; - return this; - } - - /** - * @param showCropFrame Whether to show crop frame - * @return - */ - public PictureSelectionModel showCropFrame(boolean showCropFrame) { - selectionConfig.showCropFrame = showCropFrame; - return this; - } - - /** - * @param showCropGrid Whether to show CropGrid - * @return - */ - public PictureSelectionModel showCropGrid(boolean showCropGrid) { - selectionConfig.showCropGrid = showCropGrid; - return this; - } - - /** - * @param hideBottomControls Whether is Clipping function bar - * 单选有效 - * @return - */ - public PictureSelectionModel hideBottomControls(boolean hideBottomControls) { - selectionConfig.hideBottomControls = hideBottomControls; - return this; - } - - /** - * @param aspect_ratio_x Crop Proportion x - * @param aspect_ratio_y Crop Proportion y - * @return - */ - public PictureSelectionModel withAspectRatio(int aspect_ratio_x, int aspect_ratio_y) { - selectionConfig.aspect_ratio_x = aspect_ratio_x; - selectionConfig.aspect_ratio_y = aspect_ratio_y; - return this; - } - - /** - * @param isWithVideoImage Whether the pictures and videos can be selected together - * @return - */ - public PictureSelectionModel isWithVideoImage(boolean isWithVideoImage) { - selectionConfig.isWithVideoImage = - selectionConfig.selectionMode != PictureConfig.SINGLE - && selectionConfig.chooseMode == PictureMimeType.ofAll() && isWithVideoImage; - return this; - } - - /** - * When the maximum number of choices is reached, does the list enable the mask effect - * - * @param isMaxSelectEnabledMask - * @return - */ - public PictureSelectionModel isMaxSelectEnabledMask(boolean isMaxSelectEnabledMask) { - selectionConfig.isMaxSelectEnabledMask = isMaxSelectEnabledMask; - return this; - } - - /** - * @param maxSelectNum PictureSelector max selection - * @return - */ - public PictureSelectionModel maxSelectNum(int maxSelectNum) { - selectionConfig.maxSelectNum = maxSelectNum; - return this; - } - - /** - * @param minSelectNum PictureSelector min selection - * @return - */ - public PictureSelectionModel minSelectNum(int minSelectNum) { - selectionConfig.minSelectNum = minSelectNum; - return this; - } - - /** - * @param maxVideoSelectNum PictureSelector video max selection - * @return - */ - public PictureSelectionModel maxVideoSelectNum(int maxVideoSelectNum) { - selectionConfig.maxVideoSelectNum = selectionConfig.chooseMode == PictureMimeType.ofVideo() ? 0 : maxVideoSelectNum; - return this; - } - - /** - * @param minVideoSelectNum PictureSelector video min selection - * @return - */ - public PictureSelectionModel minVideoSelectNum(int minVideoSelectNum) { - selectionConfig.minVideoSelectNum = minVideoSelectNum; - return this; - } - - /** - * Turn off Android Q to solve the problem that the width and height are reversed - * - * @param isChangeWH - * @return - */ - public PictureSelectionModel closeAndroidQChangeWH(boolean isChangeWH) { - selectionConfig.isAndroidQChangeWH = isChangeWH; - return this; - } - - /** - * Turn off Android Q to solve the problem that the width and height are reversed - * - * @param isChangeVideoWH - * @return - */ - public PictureSelectionModel closeAndroidQChangeVideoWH(boolean isChangeVideoWH) { - selectionConfig.isAndroidQChangeVideoWH = isChangeVideoWH; - return this; - } - - /** - * By clicking the title bar consecutively, RecyclerView automatically rolls back to the top - * - * @param isAutomaticTitleRecyclerTop - * @return - */ - public PictureSelectionModel isAutomaticTitleRecyclerTop(boolean isAutomaticTitleRecyclerTop) { - selectionConfig.isAutomaticTitleRecyclerTop = isAutomaticTitleRecyclerTop; - return this; - } - - - /** - * @param Select whether to return directly - * @return - */ - public PictureSelectionModel isSingleDirectReturn(boolean isSingleDirectReturn) { - selectionConfig.isSingleDirectReturn = selectionConfig.selectionMode - == PictureConfig.SINGLE && isSingleDirectReturn; - selectionConfig.isOriginalControl = (selectionConfig.selectionMode != PictureConfig.SINGLE || !isSingleDirectReturn) && selectionConfig.isOriginalControl; - return this; - } - - /** - * Whether to turn on paging mode - * - * @param isPageStrategy - * @param pageSize Maximum number of pages {@link PageSize is preferably no less than 20} - * @return - */ - public PictureSelectionModel isPageStrategy(boolean isPageStrategy, int pageSize) { - selectionConfig.isPageStrategy = isPageStrategy; - selectionConfig.pageSize = pageSize < PictureConfig.MIN_PAGE_SIZE ? PictureConfig.MAX_PAGE_SIZE : pageSize; - return this; - } - - /** - * Whether to turn on paging mode - * - * @param isPageStrategy - * @param pageSize Maximum number of pages {@link PageSize is preferably no less than 20} - * @param isFilterInvalidFile Whether to filter invalid files {@link Some of the query performance is consumed,Especially on the Q version} - * @return - */ - public PictureSelectionModel isPageStrategy(boolean isPageStrategy, int pageSize, boolean isFilterInvalidFile) { - selectionConfig.isPageStrategy = isPageStrategy; - selectionConfig.pageSize = pageSize < PictureConfig.MIN_PAGE_SIZE ? PictureConfig.MAX_PAGE_SIZE : pageSize; - selectionConfig.isFilterInvalidFile = isFilterInvalidFile; - return this; - } - - /** - * Whether to turn on paging mode - * - * @param isPageStrategy - * @return - */ - public PictureSelectionModel isPageStrategy(boolean isPageStrategy) { - selectionConfig.isPageStrategy = isPageStrategy; - return this; - } - - /** - * Whether to turn on paging mode - * - * @param isPageStrategy - * @param isFilterInvalidFile Whether to filter invalid files {@link Some of the query performance is consumed,Especially on the Q version} - * @return - */ - public PictureSelectionModel isPageStrategy(boolean isPageStrategy, boolean isFilterInvalidFile) { - selectionConfig.isPageStrategy = isPageStrategy; - selectionConfig.isFilterInvalidFile = isFilterInvalidFile; - return this; - } - - /** - * @param videoQuality video quality and 0 or 1 - * @return - */ - public PictureSelectionModel videoQuality(int videoQuality) { - selectionConfig.videoQuality = videoQuality; - return this; - } - - /** - *

- * if Android SDK >=Q Please use the video/mp4 or video/jpeg ... PictureMimeType.MP4_Q or PictureMimeType.PNG_Q - * else PictureMimeType.PNG or PictureMimeType.JPEG - *

- * - * @param suffixType PictureSelector media format - * @return - */ - public PictureSelectionModel imageFormat(String suffixType) { - if (SdkVersionUtils.checkedAndroid_Q() || SdkVersionUtils.checkedAndroid_R()) { - if (TextUtils.equals(suffixType, PictureMimeType.PNG)) { - suffixType = PictureMimeType.PNG_Q; - } - if (TextUtils.equals(suffixType, PictureMimeType.JPEG)) { - suffixType = PictureMimeType.JPEG_Q; - } - if (TextUtils.equals(suffixType, PictureMimeType.MP4)) { - suffixType = PictureMimeType.MP4_Q; - } - } - selectionConfig.suffixType = suffixType; - return this; - } - - - /** - * @param cropWidth crop width - * @param cropHeight crop height - * @return this - * @deprecated Crop image output width and height - * {@link cropImageWideHigh()} - */ - @Deprecated - public PictureSelectionModel cropWH(int cropWidth, int cropHeight) { - selectionConfig.cropWidth = cropWidth; - selectionConfig.cropHeight = cropHeight; - return this; - } - - /** - * @param cropWidth crop width - * @param cropHeight crop height - * @return this - */ - public PictureSelectionModel cropImageWideHigh(int cropWidth, int cropHeight) { - selectionConfig.cropWidth = cropWidth; - selectionConfig.cropHeight = cropHeight; - return this; - } - - /** - * @param videoMaxSecond selection video max second - * @return - */ - public PictureSelectionModel videoMaxSecond(int videoMaxSecond) { - selectionConfig.videoMaxSecond = (videoMaxSecond * 1000); - return this; - } - - /** - * @param videoMinSecond selection video min second - * @return - */ - public PictureSelectionModel videoMinSecond(int videoMinSecond) { - selectionConfig.videoMinSecond = videoMinSecond * 1000; - return this; - } - - - /** - * @param recordVideoSecond video record second - * @return - */ - public PictureSelectionModel recordVideoSecond(int recordVideoSecond) { - selectionConfig.recordVideoSecond = recordVideoSecond; - return this; - } - - /** - * @param recordVideoMinSecond video record second - * @return - */ - public PictureSelectionModel recordVideoMinSecond(int recordVideoMinSecond) { - selectionConfig.recordVideoMinSecond = recordVideoMinSecond; - return this; - } - - /** - * @param width glide width - * @param height glide height - * @return 2.2.9开始 Glide改为外部用户自己定义此方法没有意义了 - */ - @Deprecated - public PictureSelectionModel glideOverride(@IntRange(from = 100) int width, - @IntRange(from = 100) int height) { - selectionConfig.overrideWidth = width; - selectionConfig.overrideHeight = height; - return this; - } - - /** - * @param sizeMultiplier The multiplier to apply to the - * {@link com.bumptech.glide.request.target.Target}'s dimensions when - * loading the resource. - * @return 2.2.9开始Glide改为外部用户自己定义此方法没有意义了 - */ - @Deprecated - public PictureSelectionModel sizeMultiplier(@FloatRange(from = 0.1f) float sizeMultiplier) { - selectionConfig.sizeMultiplier = sizeMultiplier; - return this; - } - - /** - * @param imageSpanCount PictureSelector image span count - * @return - */ - public PictureSelectionModel imageSpanCount(int imageSpanCount) { - selectionConfig.imageSpanCount = imageSpanCount; - return this; - } - - /** - * @param Less than how many KB images are not compressed - * @return - */ - public PictureSelectionModel minimumCompressSize(int size) { - selectionConfig.minimumCompressSize = size; - return this; - } - - /** - * @param compressQuality crop compress quality default 90 - * @return 请使用 cutOutQuality();方法 - */ - @Deprecated - public PictureSelectionModel cropCompressQuality(int compressQuality) { - selectionConfig.cropCompressQuality = compressQuality; - return this; - } - - /** - * @param cutQuality crop compress quality default 90 - * @return - */ - public PictureSelectionModel cutOutQuality(int cutQuality) { - selectionConfig.cropCompressQuality = cutQuality; - return this; - } - - /** - * @param isCompress Whether to open compress - * @return Use {link .isCompress()} - */ - @Deprecated - public PictureSelectionModel compress(boolean isCompress) { - selectionConfig.isCompress = isCompress; - return this; - } - - /** - * @param isCompress Whether to open compress - * @return - */ - public PictureSelectionModel isCompress(boolean isCompress) { - selectionConfig.isCompress = isCompress; - return this; - } - - /** - * @param compressQuality Image compressed output quality - * @return - */ - public PictureSelectionModel compressQuality(int compressQuality) { - selectionConfig.compressQuality = compressQuality; - return this; - } - - /** - * @param returnEmpty No data can be returned - * @return - */ - public PictureSelectionModel isReturnEmpty(boolean returnEmpty) { - selectionConfig.returnEmpty = returnEmpty; - return this; - } - - /** - * @param synOrAsy Synchronous or asynchronous compression - * @return - */ - public PictureSelectionModel synOrAsy(boolean synOrAsy) { - selectionConfig.synOrAsy = synOrAsy; - return this; - } - - /** - * @param focusAlpha After compression, the transparent channel is retained - * @return - */ - public PictureSelectionModel compressFocusAlpha(boolean focusAlpha) { - selectionConfig.focusAlpha = focusAlpha; - return this; - } - - /** - * After recording with the system camera, does it support playing the video immediately using the system player - * - * @param isQuickCapture - * @return - */ - public PictureSelectionModel isQuickCapture(boolean isQuickCapture) { - selectionConfig.isQuickCapture = isQuickCapture; - return this; - } - - /** - * @param isOriginalControl Whether the original image is displayed - * @return - */ - public PictureSelectionModel isOriginalImageControl(boolean isOriginalControl) { - selectionConfig.isOriginalControl = !selectionConfig.camera - && selectionConfig.chooseMode != PictureMimeType.ofVideo() - && selectionConfig.chooseMode != PictureMimeType.ofAudio() && isOriginalControl; - return this; - } - - /** - * @param path save path - * @return - */ - public PictureSelectionModel compressSavePath(String path) { - selectionConfig.compressSavePath = path; - return this; - } - - /** - * Camera custom local file name - * # Such as xxx.png - * - * @param fileName - * @return - */ - public PictureSelectionModel cameraFileName(String fileName) { - selectionConfig.cameraFileName = fileName; - return this; - } - - /** - * crop custom local file name - * # Such as xxx.png - * - * @param renameCropFileName - * @return - */ - public PictureSelectionModel renameCropFileName(String renameCropFileName) { - selectionConfig.renameCropFileName = renameCropFileName; - return this; - } - - /** - * custom compress local file name - * # Such as xxx.png - * - * @param renameFile - * @return - */ - public PictureSelectionModel renameCompressFile(String renameFile) { - selectionConfig.renameCompressFileName = renameFile; - return this; - } - - /** - * @param zoomAnim Picture list zoom anim - * @return - */ - public PictureSelectionModel isZoomAnim(boolean zoomAnim) { - selectionConfig.zoomAnim = zoomAnim; - return this; - } - - /** - * @param previewEggs preview eggs It doesn't make much sense - * @return Use {link .isPreviewEggs()} - */ - @Deprecated - public PictureSelectionModel previewEggs(boolean previewEggs) { - selectionConfig.previewEggs = previewEggs; - return this; - } - - /** - * @param previewEggs preview eggs It doesn't make much sense - * @return - */ - public PictureSelectionModel isPreviewEggs(boolean previewEggs) { - selectionConfig.previewEggs = previewEggs; - return this; - } - - /** - * @param isCamera Whether to open camera button - * @return - */ - public PictureSelectionModel isCamera(boolean isCamera) { - selectionConfig.isCamera = isCamera; - return this; - } - - /** - * Extra used with {@link #Environment.getExternalStorageDirectory() + File.separator + "CustomCamera" + File.separator} to indicate that - * - * @param outPutCameraPath Camera save path 只支持Build.VERSION.SDK_INT < Build.VERSION_CODES.Q - * @return - */ - public PictureSelectionModel setOutputCameraPath(String outPutCameraPath) { - selectionConfig.outPutCameraPath = outPutCameraPath; - return this; - } - - - /** - * # file size The unit is M - * - * @param fileSize Filter file size - * @return - */ - public PictureSelectionModel queryMaxFileSize(float fileSize) { - selectionConfig.filterFileSize = fileSize; - return this; - } - - /** - * @param isGif Whether to open gif - * @return - */ - public PictureSelectionModel isGif(boolean isGif) { - selectionConfig.isGif = isGif; - return this; - } - - /** - * @param isWebp Whether to open .webp - * @return - */ - public PictureSelectionModel isWebp(boolean isWebp) { - selectionConfig.isWebp = isWebp; - return this; - } - - /** - * @param isBmp Whether to open .isBmp - * @return - */ - public PictureSelectionModel isBmp(boolean isBmp) { - selectionConfig.isWebp = isBmp; - return this; - } - - /** - * @param enablePreview Do you want to preview the picture? - * @return Use {link .isPreviewImage()} - */ - @Deprecated - public PictureSelectionModel previewImage(boolean enablePreview) { - selectionConfig.enablePreview = enablePreview; - return this; - } - - /** - * @param enablePreview Do you want to preview the picture? - * @return - */ - public PictureSelectionModel isPreviewImage(boolean enablePreview) { - selectionConfig.enablePreview = enablePreview; - return this; - } - - /** - * @param enPreviewVideo Do you want to preview the video? - * @return Use {link .isPreviewVideo()} - */ - @Deprecated - public PictureSelectionModel previewVideo(boolean enPreviewVideo) { - selectionConfig.enPreviewVideo = enPreviewVideo; - return this; - } - - /** - * @param enPreviewVideo Do you want to preview the video? - * @return - */ - public PictureSelectionModel isPreviewVideo(boolean enPreviewVideo) { - selectionConfig.enPreviewVideo = enPreviewVideo; - return this; - } - - /** - * @param isNotPreviewDownload Previews do not show downloads - * @return - */ - public PictureSelectionModel isNotPreviewDownload(boolean isNotPreviewDownload) { - selectionConfig.isNotPreviewDownload = isNotPreviewDownload; - return this; - } - - /** - * @param Specify get image format - * @return - */ - public PictureSelectionModel querySpecifiedFormatSuffix(String specifiedFormat) { - selectionConfig.specifiedFormat = specifiedFormat; - return this; - } - - /** - * @param openClickSound Whether to open click voice - * @return Use {link .isOpenClickSound()} - */ - @Deprecated - public PictureSelectionModel openClickSound(boolean openClickSound) { - selectionConfig.openClickSound = !selectionConfig.camera && openClickSound; - return this; - } - - /** - * @param isOpenClickSound Whether to open click voice - * @return - */ - public PictureSelectionModel isOpenClickSound(boolean openClickSound) { - selectionConfig.openClickSound = !selectionConfig.camera && openClickSound; - return this; - } - - /** - * 是否可拖动裁剪框(setFreeStyleCropEnabled 为true 有效) - */ - public PictureSelectionModel isDragFrame(boolean isDragFrame) { - selectionConfig.isDragFrame = isDragFrame; - return this; - } - - /** - * Whether the multi-graph clipping list is animated or not - * - * @param isAnimation - * @return - */ - public PictureSelectionModel isMultipleRecyclerAnimation(boolean isAnimation) { - selectionConfig.isMultipleRecyclerAnimation = isAnimation; - return this; - } - - - /** - * 设置摄像头方向(前后 默认后置) - */ - public PictureSelectionModel isCameraAroundState(boolean isCameraAroundState) { - selectionConfig.isCameraAroundState = isCameraAroundState; - return this; - } - - /** - * @param selectionMedia Select the selected picture set - * @return Use {link .selectionData()} - */ - @Deprecated - public PictureSelectionModel selectionMedia(List selectionMedia) { - if (selectionConfig.selectionMode == PictureConfig.SINGLE && selectionConfig.isSingleDirectReturn) { - selectionConfig.selectionMedias = null; - } else { - selectionConfig.selectionMedias = selectionMedia; - } - return this; - } - - /** - * @param selectionData Select the selected picture set - * @return - */ - public PictureSelectionModel selectionData(List selectionData) { - if (selectionConfig.selectionMode == PictureConfig.SINGLE && selectionConfig.isSingleDirectReturn) { - selectionConfig.selectionMedias = null; - } else { - selectionConfig.selectionMedias = selectionData; - } - return this; - } - - /** - * 是否改变状态栏字段颜色(黑白字体转换) - * #适合所有style使用 - * - * @param isChangeStatusBarFontColor - * @return - */ - @Deprecated - public PictureSelectionModel isChangeStatusBarFontColor(boolean isChangeStatusBarFontColor) { - selectionConfig.isChangeStatusBarFontColor = isChangeStatusBarFontColor; - return this; - } - - /** - * 选择图片样式0/9 - * #适合所有style使用 - * - * @param isOpenStyleNumComplete - * @return 使用setPictureStyle方法 - */ - @Deprecated - public PictureSelectionModel isOpenStyleNumComplete(boolean isOpenStyleNumComplete) { - selectionConfig.isOpenStyleNumComplete = isOpenStyleNumComplete; - return this; - } - - /** - * 是否开启数字选择模式 - * #适合qq style 样式使用 - * - * @param isOpenStyleCheckNumMode - * @return 使用setPictureStyle方法 - */ - @Deprecated - public PictureSelectionModel isOpenStyleCheckNumMode(boolean isOpenStyleCheckNumMode) { - selectionConfig.isOpenStyleCheckNumMode = isOpenStyleCheckNumMode; - return this; - } - - /** - * 设置标题栏背景色 - * - * @param color - * @return 使用setPictureStyle方法 - */ - @Deprecated - public PictureSelectionModel setTitleBarBackgroundColor(@ColorInt int color) { - selectionConfig.titleBarBackgroundColor = color; - return this; - } - - - /** - * 状态栏背景色 - * - * @param color - * @return 使用setPictureStyle方法 - */ - @Deprecated - public PictureSelectionModel setStatusBarColorPrimaryDark(@ColorInt int color) { - selectionConfig.pictureStatusBarColor = color; - return this; - } - - - /** - * 裁剪页面标题背景色 - * - * @param color - * @return 使用setPictureCropStyle方法 - */ - @Deprecated - public PictureSelectionModel setCropTitleBarBackgroundColor(@ColorInt int color) { - selectionConfig.cropTitleBarBackgroundColor = color; - return this; - } - - /** - * 裁剪页面状态栏背景色 - * - * @param color - * @return 使用setPictureCropStyle方法 - */ - @Deprecated - public PictureSelectionModel setCropStatusBarColorPrimaryDark(@ColorInt int color) { - selectionConfig.cropStatusBarColorPrimaryDark = color; - return this; - } - - /** - * 裁剪页面标题文字颜色 - * - * @param color - * @return 使用setPictureCropStyle方法 - */ - @Deprecated - public PictureSelectionModel setCropTitleColor(@ColorInt int color) { - selectionConfig.cropTitleColor = color; - return this; - } - - /** - * 设置相册标题右侧向上箭头图标 - * - * @param resId - * @return 使用setPictureStyle方法 - */ - @Deprecated - public PictureSelectionModel setUpArrowDrawable(int resId) { - selectionConfig.upResId = resId; - return this; - } - - /** - * 设置相册标题右侧向下箭头图标 - * - * @param resId - * @return 使用setPictureStyle方法 - */ - @Deprecated - public PictureSelectionModel setDownArrowDrawable(int resId) { - selectionConfig.downResId = resId; - return this; - } - - /** - * 动态设置裁剪主题样式 - * - * @param style 裁剪页主题 - *

{@link PictureSelectorUIStyle} - * @return - */ - @Deprecated - public PictureSelectionModel setPictureCropStyle(PictureCropParameterStyle style) { - if (style != null) { - PictureSelectionConfig.cropStyle = style; - } else { - PictureSelectionConfig.cropStyle = PictureCropParameterStyle.ofDefaultCropStyle(); - } - return this; - } - - /** - * 动态设置相册主题样式 - * - * @param style 主题 - *

{@link PictureSelectorUIStyle} - * @return - */ - @Deprecated - public PictureSelectionModel setPictureStyle(PictureParameterStyle style) { - if (style != null) { - PictureSelectionConfig.style = style; - if (!selectionConfig.isWeChatStyle) { - selectionConfig.isWeChatStyle = style.isNewSelectStyle; - } - } else { - PictureSelectionConfig.style = PictureParameterStyle.ofDefaultStyle(); - } - return this; - } - - /** - * Dynamically set the album to start and exit the animation - * - * @param style Activity Launch exit animation theme - * @return - */ - public PictureSelectionModel setPictureWindowAnimationStyle(PictureWindowAnimationStyle windowAnimationStyle) { - if (windowAnimationStyle != null) { - PictureSelectionConfig.windowAnimationStyle = windowAnimationStyle; - } else { - PictureSelectionConfig.windowAnimationStyle = PictureWindowAnimationStyle.ofDefaultWindowAnimationStyle(); - } - return this; - } - - /** - * Photo album list animation {} - * Use {@link AnimationType#ALPHA_IN_ANIMATION or SLIDE_IN_BOTTOM_ANIMATION} directly. - * - * @param animationMode - * @return - */ - public PictureSelectionModel setRecyclerAnimationMode(int animationMode) { - selectionConfig.animationMode = animationMode; - return this; - } - - /** - * # If you want to handle the Android Q path, if not, just return the uri, - * The getAndroidQToPath(); field will be empty - * - * @param isAndroidQTransform - * @return - */ - public PictureSelectionModel isAndroidQTransform(boolean isAndroidQTransform) { - selectionConfig.isAndroidQTransform = isAndroidQTransform; - return this; - } - - /** - * # 内部方法-要使用此方法时最好先咨询作者!!! - * - * @param isFallbackVersion 仅供特殊情况内部使用 如果某功能出错此开关可以回退至之前版本 - * @return - */ - public PictureSelectionModel isFallbackVersion(boolean isFallbackVersion) { - selectionConfig.isFallbackVersion = isFallbackVersion; - return this; - } - - /** - * # 内部方法-要使用此方法时最好先咨询作者!!! - * - * @param isFallbackVersion 仅供特殊情况内部使用 如果某功能出错此开关可以回退至之前版本 - * @return - */ - public PictureSelectionModel isFallbackVersion2(boolean isFallbackVersion) { - selectionConfig.isFallbackVersion2 = isFallbackVersion; - return this; - } - - /** - * # 内部方法-要使用此方法时最好先咨询作者!!! - * - * @param isFallbackVersion 仅供特殊情况内部使用 如果某功能出错此开关可以回退至之前版本 - * @return - */ - public PictureSelectionModel isFallbackVersion3(boolean isFallbackVersion) { - selectionConfig.isFallbackVersion3 = isFallbackVersion; - return this; - } - - /** - * Start to select media and wait for result. - * - * @param requestCode Identity of the request Activity or Fragment. - */ - public void forResult(int requestCode) { - if (!DoubleUtils.isFastDoubleClick()) { - Activity activity = selector.getActivity(); - if (activity == null || selectionConfig == null) { - return; - } - Intent intent; - if (selectionConfig.camera && selectionConfig.isUseCustomCamera) { - intent = new Intent(activity, PictureCustomCameraActivity.class); - } else { - intent = new Intent(activity, selectionConfig.camera - ? PictureSelectorCameraEmptyActivity.class : - selectionConfig.isWeChatStyle ? PictureSelectorWeChatStyleActivity.class - : PictureSelectorActivity.class); - } - selectionConfig.isCallbackMode = false; - Fragment fragment = selector.getFragment(); - if (fragment != null) { - fragment.startActivityForResult(intent, requestCode); - } else { - activity.startActivityForResult(intent, requestCode); - } - PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; - activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); - } - } - - /** - * # replace for setPictureWindowAnimationStyle(); - * Start to select media and wait for result. - *

- * # Use PictureWindowAnimationStyle to achieve animation effects - * - * @param requestCode Identity of the request Activity or Fragment. - */ - @Deprecated - public void forResult(int requestCode, int enterAnim, int exitAnim) { - if (!DoubleUtils.isFastDoubleClick()) { - Activity activity = selector.getActivity(); - if (activity == null) { - return; - } - Intent intent = new Intent(activity, selectionConfig != null && selectionConfig.camera - ? PictureSelectorCameraEmptyActivity.class : - selectionConfig.isWeChatStyle ? PictureSelectorWeChatStyleActivity.class : - PictureSelectorActivity.class); - selectionConfig.isCallbackMode = false; - Fragment fragment = selector.getFragment(); - if (fragment != null) { - fragment.startActivityForResult(intent, requestCode); - } else { - activity.startActivityForResult(intent, requestCode); - } - activity.overridePendingTransition(enterAnim, exitAnim); - } - } - - - /** - * Start to select media and wait for result. - * - * @param listener The resulting callback listens - */ - public void forResult(OnResultCallbackListener listener) { - if (!DoubleUtils.isFastDoubleClick()) { - Activity activity = selector.getActivity(); - if (activity == null || selectionConfig == null) { - return; - } - // 绑定回调监听 - PictureSelectionConfig.listener = new WeakReference<>(listener).get(); - selectionConfig.isCallbackMode = true; - Intent intent; - if (selectionConfig.camera && selectionConfig.isUseCustomCamera) { - intent = new Intent(activity, PictureCustomCameraActivity.class); - } else { - intent = new Intent(activity, selectionConfig.camera - ? PictureSelectorCameraEmptyActivity.class : - selectionConfig.isWeChatStyle ? PictureSelectorWeChatStyleActivity.class - : PictureSelectorActivity.class); - } - Fragment fragment = selector.getFragment(); - if (fragment != null) { - fragment.startActivity(intent); - } else { - activity.startActivity(intent); - } - PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; - activity.overridePendingTransition( - windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); - } - } - - /** - * Start to select media and wait for result. - * - * @param requestCode Identity of the request Activity or Fragment. - * @param listener The resulting callback listens - */ - public void forResult(int requestCode, OnResultCallbackListener listener) { - if (!DoubleUtils.isFastDoubleClick()) { - Activity activity = selector.getActivity(); - if (activity == null || selectionConfig == null) { - return; - } - // 绑定回调监听 - PictureSelectionConfig.listener = new WeakReference<>(listener).get(); - selectionConfig.isCallbackMode = true; - Intent intent; - if (selectionConfig.camera && selectionConfig.isUseCustomCamera) { - intent = new Intent(activity, PictureCustomCameraActivity.class); - } else { - intent = new Intent(activity, selectionConfig.camera - ? PictureSelectorCameraEmptyActivity.class : - selectionConfig.isWeChatStyle ? PictureSelectorWeChatStyleActivity.class - : PictureSelectorActivity.class); - } - Fragment fragment = selector.getFragment(); - if (fragment != null) { - fragment.startActivityForResult(intent, requestCode); - } else { - activity.startActivityForResult(intent, requestCode); - } - PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; - activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); - } - } - - /** - * 提供外部预览图片方法 - * - * @param position - * @param medias - */ - public void openExternalPreview(int position, List medias) { - if (selector != null) { - selector.externalPicturePreview(position, medias, PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation); - } else { - throw new NullPointerException("This PictureSelector is Null"); - } - } - - - /** - * 提供外部预览图片方法-带自定义下载保存路径 - * # 废弃 由于Android Q沙盒机制 此方法不在需要了 - * - * @param position - * @param medias - */ - @Deprecated - public void openExternalPreview(int position, String directory_path, List medias) { - if (selector != null) { - selector.externalPicturePreview(position, directory_path, medias, - PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation); - } else { - throw new NullPointerException("This PictureSelector is Null"); - } - } - - /** - * set preview video - * - * @param path - */ - public void externalPictureVideo(String path) { - if (selector != null) { - selector.externalPictureVideo(path); - } else { - throw new NullPointerException("This PictureSelector is Null"); - } - } + private PictureSelectionConfig selectionConfig; + private PictureSelector selector; + + public PictureSelectionModel (PictureSelector selector, int chooseMode) { + this.selector = selector; + selectionConfig = PictureSelectionConfig.getCleanInstance(); + selectionConfig.chooseMode = chooseMode; + } + + public PictureSelectionModel (PictureSelector selector, int chooseMode, boolean camera) { + this.selector = selector; + selectionConfig = PictureSelectionConfig.getCleanInstance(); + selectionConfig.camera = camera; + selectionConfig.chooseMode = chooseMode; + } + + /** + * @param themeStyleId PictureSelector Theme style + * @return PictureSelectionModel + * Use {@link R.style#picture_default_style#picture_Sina_style#picture_white_style#picture_QQ_style#picture_WeChat_style} + */ + public PictureSelectionModel theme (@StyleRes int themeStyleId) { + selectionConfig.themeStyleId = themeStyleId; + return this; + } + + /** + * Setting PictureSelector UI Style + * + * @param uiStyle

+ * {@link PictureSelectorUIStyle} + *

+ * @return + */ + public PictureSelectionModel setPictureUIStyle (PictureSelectorUIStyle uiStyle) { + if (uiStyle != null) { + PictureSelectionConfig.uiStyle = uiStyle; + if (!selectionConfig.isWeChatStyle) { + selectionConfig.isWeChatStyle = PictureSelectionConfig.uiStyle.isNewSelectStyle; + } + } + return this; + } + + /** + * @param locale Language + * @return PictureSelectionModel + */ + public PictureSelectionModel setLanguage (int language) { + selectionConfig.language = language; + return this; + } + + /** + * Change the desired orientation of this activity. If the activity + * is currently in the foreground or otherwise impacting the screen + * orientation, the screen will immediately be changed (possibly causing + * the activity to be restarted). Otherwise, this will be used the next + * time the activity is visible. + * + * @param requestedOrientation An orientation constant as used in + * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}. + */ + public PictureSelectionModel setRequestedOrientation (int requestedOrientation) { + selectionConfig.requestedOrientation = requestedOrientation; + return this; + } + + /** + * @param engine Image Load the engine + * @return Use {@link .imageEngine()}. + */ + @Deprecated + public PictureSelectionModel loadImageEngine (ImageEngine engine) { + if (PictureSelectionConfig.imageEngine != engine) { + PictureSelectionConfig.imageEngine = engine; + } + return this; + } + + /** + * @param engine Image Load the engine + * @return + */ + public PictureSelectionModel imageEngine (ImageEngine engine) { + if (PictureSelectionConfig.imageEngine != engine) { + PictureSelectionConfig.imageEngine = engine; + } + return this; + } + + /** + * Only for Android version Q + *

+ * 已废弃,没有存在的意义了,之前主要是为了解决在华为10系统上一直loading问题 + *

+ * + * @param cacheResourcesEngine Image Cache + * @return + */ + @Deprecated + public PictureSelectionModel loadCacheResourcesCallback (CacheResourcesEngine cacheResourcesEngine) { + if (SdkVersionUtils.checkedAndroid_Q()) { + if (PictureSelectionConfig.cacheResourcesEngine != cacheResourcesEngine) { + PictureSelectionConfig.cacheResourcesEngine = new WeakReference<>(cacheResourcesEngine).get(); + } + } + return this; + } + + /** + * @param selectionMode PictureSelector Selection model and PictureConfig.MULTIPLE or PictureConfig.SINGLE + * @return + */ + public PictureSelectionModel selectionMode (int selectionMode) { + selectionConfig.selectionMode = selectionMode; + return this; + } + + /** + * @param isWeChatStyle Select style with or without WeChat enabled + * @return + */ + public PictureSelectionModel isWeChatStyle (boolean isWeChatStyle) { + selectionConfig.isWeChatStyle = isWeChatStyle; + return this; + } + + /** + * @param isDoctalkStyle Select style with or without Doctalk enabled + * @return + */ + public PictureSelectionModel isDoctalkStyle (boolean isDoctalkStyle) { + selectionConfig.isDoctalkStyle = isDoctalkStyle; + return this; + } + + /** + * @param isUseCustomCamera Whether to use a custom camera + * @return + */ + public PictureSelectionModel isUseCustomCamera (boolean isUseCustomCamera) { + selectionConfig.isUseCustomCamera = Build.VERSION.SDK_INT > KITKAT && isUseCustomCamera; + return this; + } + + /** + * @param callback Provide video playback control,Users are free to customize the video display interface + * @return + */ + public PictureSelectionModel bindCustomPlayVideoCallback (OnVideoSelectedPlayCallback callback) { + PictureSelectionConfig.customVideoPlayCallback = new WeakReference<>(callback).get(); + return this; + } + + /** + * @param callback Custom preview callback function + * @return + */ + public PictureSelectionModel bindCustomPreviewCallback (OnCustomImagePreviewCallback callback) { + PictureSelectionConfig.onCustomImagePreviewCallback = new WeakReference<>(callback).get(); + return this; + } + + /** + * # The developer provides an additional callback interface to the user where the user can perform some custom actions + * {link 如果是自定义相机则必须使用.startActivityForResult(this,PictureConfig.REQUEST_CAMERA);方式启动否则PictureSelector处理不了相机后的回调} + * + * @param listener + * @return Use ${bindCustomCameraInterfaceListener} + */ + @Deprecated + public PictureSelectionModel bindPictureSelectorInterfaceListener (OnCustomCameraInterfaceListener listener) { + PictureSelectionConfig.onCustomCameraInterfaceListener = new WeakReference<>(listener).get(); + return this; + } + + /** + * # The developer provides an additional callback interface to the user where the user can perform some custom actions + * {link 如果是自定义相机则必须使用.startActivityForResult(this,PictureConfig.REQUEST_CAMERA);方式启动否则PictureSelector处理不了相机后的回调} + * + * @param listener + * @return + */ + public PictureSelectionModel bindCustomCameraInterfaceListener (OnCustomCameraInterfaceListener listener) { + PictureSelectionConfig.onCustomCameraInterfaceListener = new WeakReference<>(listener).get(); + return this; + } + + /** + * @param buttonFeatures Set the record button function + * # 具体参考 CustomCameraView.BUTTON_STATE_BOTH、BUTTON_STATE_ONLY_CAPTURE、BUTTON_STATE_ONLY_RECORDER + * @return + */ + public PictureSelectionModel setButtonFeatures (int buttonFeatures) { + selectionConfig.buttonFeatures = buttonFeatures; + return this; + } + + /** + * @param enableCrop Do you want to start cutting ? + * @return Use {link .isEnableCrop()} + */ + @Deprecated + public PictureSelectionModel enableCrop (boolean enableCrop) { + selectionConfig.enableCrop = enableCrop; + return this; + } + + /** + * @param enableCrop Do you want to start cutting ? + * @return + */ + public PictureSelectionModel isEnableCrop (boolean enableCrop) { + selectionConfig.enableCrop = enableCrop; + return this; + } + + /** + * @param uCropOptions UCrop parameter configuration is provided + * @return + */ + public PictureSelectionModel basicUCropConfig (UCropOptions uCropOptions) { + selectionConfig.uCropOptions = uCropOptions; + return this; + } + + /** + * @param isMultipleSkipCrop Whether multiple images can be skipped when cropping + * @return + */ + public PictureSelectionModel isMultipleSkipCrop (boolean isMultipleSkipCrop) { + selectionConfig.isMultipleSkipCrop = isMultipleSkipCrop; + return this; + } + + + /** + * @param enablePreviewAudio {@link use isEnablePreviewAudio} + * @return + */ + @Deprecated + public PictureSelectionModel enablePreviewAudio (boolean enablePreviewAudio) { + selectionConfig.enablePreviewAudio = enablePreviewAudio; + return this; + } + + /** + * @param enablePreviewAudio + * @return + */ + public PictureSelectionModel isEnablePreviewAudio (boolean enablePreviewAudio) { + selectionConfig.enablePreviewAudio = enablePreviewAudio; + return this; + } + + /** + * @param freeStyleCropEnabled Crop frame is move ? + * @return + */ + public PictureSelectionModel freeStyleCropEnabled (boolean freeStyleCropEnabled) { + selectionConfig.freeStyleCropEnabled = freeStyleCropEnabled; + return this; + } + + /** + * @param scaleEnabled Crop frame is zoom ? + * @return + */ + public PictureSelectionModel scaleEnabled (boolean scaleEnabled) { + selectionConfig.scaleEnabled = scaleEnabled; + return this; + } + + /** + * @param rotateEnabled Crop frame is rotate ? + * @return + */ + public PictureSelectionModel rotateEnabled (boolean rotateEnabled) { + selectionConfig.rotateEnabled = rotateEnabled; + return this; + } + + /** + * @param circleDimmedLayer Circular head cutting + * @return + */ + public PictureSelectionModel circleDimmedLayer (boolean circleDimmedLayer) { + selectionConfig.circleDimmedLayer = circleDimmedLayer; + return this; + } + + /** + * @param circleDimmedColor setCircleDimmedColor + * @return + */ + @Deprecated + public PictureSelectionModel setCircleDimmedColor (int circleDimmedColor) { + selectionConfig.circleDimmedColor = circleDimmedColor; + return this; + } + + /** + * @param dimmedColor + * @return + */ + public PictureSelectionModel setCropDimmedColor (int dimmedColor) { + selectionConfig.circleDimmedColor = dimmedColor; + return this; + } + + /** + * @param circleDimmedBorderColor setCircleDimmedBorderColor + * @return + */ + public PictureSelectionModel setCircleDimmedBorderColor (int circleDimmedBorderColor) { + selectionConfig.circleDimmedBorderColor = circleDimmedBorderColor; + return this; + } + + /** + * @param circleStrokeWidth setCircleStrokeWidth + * @return + */ + public PictureSelectionModel setCircleStrokeWidth (int circleStrokeWidth) { + selectionConfig.circleStrokeWidth = circleStrokeWidth; + return this; + } + + /** + * @param showCropFrame Whether to show crop frame + * @return + */ + public PictureSelectionModel showCropFrame (boolean showCropFrame) { + selectionConfig.showCropFrame = showCropFrame; + return this; + } + + /** + * @param showCropGrid Whether to show CropGrid + * @return + */ + public PictureSelectionModel showCropGrid (boolean showCropGrid) { + selectionConfig.showCropGrid = showCropGrid; + return this; + } + + /** + * @param hideBottomControls Whether is Clipping function bar + * 单选有效 + * @return + */ + public PictureSelectionModel hideBottomControls (boolean hideBottomControls) { + selectionConfig.hideBottomControls = hideBottomControls; + return this; + } + + /** + * @param aspect_ratio_x Crop Proportion x + * @param aspect_ratio_y Crop Proportion y + * @return + */ + public PictureSelectionModel withAspectRatio (int aspect_ratio_x, int aspect_ratio_y) { + selectionConfig.aspect_ratio_x = aspect_ratio_x; + selectionConfig.aspect_ratio_y = aspect_ratio_y; + return this; + } + + /** + * @param isWithVideoImage Whether the pictures and videos can be selected together + * @return + */ + public PictureSelectionModel isWithVideoImage (boolean isWithVideoImage) { + selectionConfig.isWithVideoImage = + selectionConfig.selectionMode != PictureConfig.SINGLE + && selectionConfig.chooseMode == PictureMimeType.ofAll() && isWithVideoImage; + return this; + } + + /** + * When the maximum number of choices is reached, does the list enable the mask effect + * + * @param isMaxSelectEnabledMask + * @return + */ + public PictureSelectionModel isMaxSelectEnabledMask (boolean isMaxSelectEnabledMask) { + selectionConfig.isMaxSelectEnabledMask = isMaxSelectEnabledMask; + return this; + } + + /** + * @param maxSelectNum PictureSelector max selection + * @return + */ + public PictureSelectionModel maxSelectNum (int maxSelectNum) { + selectionConfig.maxSelectNum = maxSelectNum; + return this; + } + + /** + * @param minSelectNum PictureSelector min selection + * @return + */ + public PictureSelectionModel minSelectNum (int minSelectNum) { + selectionConfig.minSelectNum = minSelectNum; + return this; + } + + /** + * @param maxVideoSelectNum PictureSelector video max selection + * @return + */ + public PictureSelectionModel maxVideoSelectNum (int maxVideoSelectNum) { + selectionConfig.maxVideoSelectNum = selectionConfig.chooseMode == PictureMimeType.ofVideo() ? 0 : maxVideoSelectNum; + return this; + } + + /** + * @param minVideoSelectNum PictureSelector video min selection + * @return + */ + public PictureSelectionModel minVideoSelectNum (int minVideoSelectNum) { + selectionConfig.minVideoSelectNum = minVideoSelectNum; + return this; + } + + /** + * Turn off Android Q to solve the problem that the width and height are reversed + * + * @param isChangeWH + * @return + */ + public PictureSelectionModel closeAndroidQChangeWH (boolean isChangeWH) { + selectionConfig.isAndroidQChangeWH = isChangeWH; + return this; + } + + /** + * Turn off Android Q to solve the problem that the width and height are reversed + * + * @param isChangeVideoWH + * @return + */ + public PictureSelectionModel closeAndroidQChangeVideoWH (boolean isChangeVideoWH) { + selectionConfig.isAndroidQChangeVideoWH = isChangeVideoWH; + return this; + } + + /** + * By clicking the title bar consecutively, RecyclerView automatically rolls back to the top + * + * @param isAutomaticTitleRecyclerTop + * @return + */ + public PictureSelectionModel isAutomaticTitleRecyclerTop (boolean isAutomaticTitleRecyclerTop) { + selectionConfig.isAutomaticTitleRecyclerTop = isAutomaticTitleRecyclerTop; + return this; + } + + + /** + * @param Select whether to return directly + * @return + */ + public PictureSelectionModel isSingleDirectReturn (boolean isSingleDirectReturn) { + selectionConfig.isSingleDirectReturn = selectionConfig.selectionMode + == PictureConfig.SINGLE && isSingleDirectReturn; + selectionConfig.isOriginalControl = (selectionConfig.selectionMode != PictureConfig.SINGLE || !isSingleDirectReturn) && selectionConfig.isOriginalControl; + return this; + } + + /** + * Whether to turn on paging mode + * + * @param isPageStrategy + * @param pageSize Maximum number of pages {@link PageSize is preferably no less than 20} + * @return + */ + public PictureSelectionModel isPageStrategy (boolean isPageStrategy, int pageSize) { + selectionConfig.isPageStrategy = isPageStrategy; + selectionConfig.pageSize = pageSize < PictureConfig.MIN_PAGE_SIZE ? PictureConfig.MAX_PAGE_SIZE : pageSize; + return this; + } + + /** + * Whether to turn on paging mode + * + * @param isPageStrategy + * @param pageSize Maximum number of pages {@link PageSize is preferably no less than 20} + * @param isFilterInvalidFile Whether to filter invalid files {@link Some of the query performance is consumed,Especially on the Q version} + * @return + */ + public PictureSelectionModel isPageStrategy (boolean isPageStrategy, int pageSize, boolean isFilterInvalidFile) { + selectionConfig.isPageStrategy = isPageStrategy; + selectionConfig.pageSize = pageSize < PictureConfig.MIN_PAGE_SIZE ? PictureConfig.MAX_PAGE_SIZE : pageSize; + selectionConfig.isFilterInvalidFile = isFilterInvalidFile; + return this; + } + + /** + * Whether to turn on paging mode + * + * @param isPageStrategy + * @return + */ + public PictureSelectionModel isPageStrategy (boolean isPageStrategy) { + selectionConfig.isPageStrategy = isPageStrategy; + return this; + } + + /** + * Whether to turn on paging mode + * + * @param isPageStrategy + * @param isFilterInvalidFile Whether to filter invalid files {@link Some of the query performance is consumed,Especially on the Q version} + * @return + */ + public PictureSelectionModel isPageStrategy (boolean isPageStrategy, boolean isFilterInvalidFile) { + selectionConfig.isPageStrategy = isPageStrategy; + selectionConfig.isFilterInvalidFile = isFilterInvalidFile; + return this; + } + + /** + * @param videoQuality video quality and 0 or 1 + * @return + */ + public PictureSelectionModel videoQuality (int videoQuality) { + selectionConfig.videoQuality = videoQuality; + return this; + } + + /** + *

+ * if Android SDK >=Q Please use the video/mp4 or video/jpeg ... PictureMimeType.MP4_Q or PictureMimeType.PNG_Q + * else PictureMimeType.PNG or PictureMimeType.JPEG + *

+ * + * @param suffixType PictureSelector media format + * @return + */ + public PictureSelectionModel imageFormat (String suffixType) { + if (SdkVersionUtils.checkedAndroid_Q() || SdkVersionUtils.checkedAndroid_R()) { + if (TextUtils.equals(suffixType, PictureMimeType.PNG)) { + suffixType = PictureMimeType.PNG_Q; + } + if (TextUtils.equals(suffixType, PictureMimeType.JPEG)) { + suffixType = PictureMimeType.JPEG_Q; + } + if (TextUtils.equals(suffixType, PictureMimeType.MP4)) { + suffixType = PictureMimeType.MP4_Q; + } + } + selectionConfig.suffixType = suffixType; + return this; + } + + + /** + * @param cropWidth crop width + * @param cropHeight crop height + * @return this + * @deprecated Crop image output width and height + * {@link cropImageWideHigh()} + */ + @Deprecated + public PictureSelectionModel cropWH (int cropWidth, int cropHeight) { + selectionConfig.cropWidth = cropWidth; + selectionConfig.cropHeight = cropHeight; + return this; + } + + /** + * @param cropWidth crop width + * @param cropHeight crop height + * @return this + */ + public PictureSelectionModel cropImageWideHigh (int cropWidth, int cropHeight) { + selectionConfig.cropWidth = cropWidth; + selectionConfig.cropHeight = cropHeight; + return this; + } + + /** + * @param videoMaxSecond selection video max second + * @return + */ + public PictureSelectionModel videoMaxSecond (int videoMaxSecond) { + selectionConfig.videoMaxSecond = (videoMaxSecond * 1000); + return this; + } + + /** + * @param videoMinSecond selection video min second + * @return + */ + public PictureSelectionModel videoMinSecond (int videoMinSecond) { + selectionConfig.videoMinSecond = videoMinSecond * 1000; + return this; + } + + + /** + * @param recordVideoSecond video record second + * @return + */ + public PictureSelectionModel recordVideoSecond (int recordVideoSecond) { + selectionConfig.recordVideoSecond = recordVideoSecond; + return this; + } + + /** + * @param recordVideoMinSecond video record second + * @return + */ + public PictureSelectionModel recordVideoMinSecond (int recordVideoMinSecond) { + selectionConfig.recordVideoMinSecond = recordVideoMinSecond; + return this; + } + + /** + * @param width glide width + * @param height glide height + * @return 2.2.9开始 Glide改为外部用户自己定义此方法没有意义了 + */ + @Deprecated + public PictureSelectionModel glideOverride (@IntRange(from = 100) int width, + @IntRange(from = 100) int height) { + selectionConfig.overrideWidth = width; + selectionConfig.overrideHeight = height; + return this; + } + + /** + * @param sizeMultiplier The multiplier to apply to the + * {@link com.bumptech.glide.request.target.Target}'s dimensions when + * loading the resource. + * @return 2.2.9开始Glide改为外部用户自己定义此方法没有意义了 + */ + @Deprecated + public PictureSelectionModel sizeMultiplier (@FloatRange(from = 0.1f) float sizeMultiplier) { + selectionConfig.sizeMultiplier = sizeMultiplier; + return this; + } + + /** + * @param imageSpanCount PictureSelector image span count + * @return + */ + public PictureSelectionModel imageSpanCount (int imageSpanCount) { + selectionConfig.imageSpanCount = imageSpanCount; + return this; + } + + /** + * @param Less than how many KB images are not compressed + * @return + */ + public PictureSelectionModel minimumCompressSize (int size) { + selectionConfig.minimumCompressSize = size; + return this; + } + + /** + * @param compressQuality crop compress quality default 90 + * @return 请使用 cutOutQuality();方法 + */ + @Deprecated + public PictureSelectionModel cropCompressQuality (int compressQuality) { + selectionConfig.cropCompressQuality = compressQuality; + return this; + } + + /** + * @param cutQuality crop compress quality default 90 + * @return + */ + public PictureSelectionModel cutOutQuality (int cutQuality) { + selectionConfig.cropCompressQuality = cutQuality; + return this; + } + + /** + * @param isCompress Whether to open compress + * @return Use {link .isCompress()} + */ + @Deprecated + public PictureSelectionModel compress (boolean isCompress) { + selectionConfig.isCompress = isCompress; + return this; + } + + /** + * @param isCompress Whether to open compress + * @return + */ + public PictureSelectionModel isCompress (boolean isCompress) { + selectionConfig.isCompress = isCompress; + return this; + } + + /** + * @param compressQuality Image compressed output quality + * @return + */ + public PictureSelectionModel compressQuality (int compressQuality) { + selectionConfig.compressQuality = compressQuality; + return this; + } + + /** + * @param returnEmpty No data can be returned + * @return + */ + public PictureSelectionModel isReturnEmpty (boolean returnEmpty) { + selectionConfig.returnEmpty = returnEmpty; + return this; + } + + /** + * @param synOrAsy Synchronous or asynchronous compression + * @return + */ + public PictureSelectionModel synOrAsy (boolean synOrAsy) { + selectionConfig.synOrAsy = synOrAsy; + return this; + } + + /** + * @param focusAlpha After compression, the transparent channel is retained + * @return + */ + public PictureSelectionModel compressFocusAlpha (boolean focusAlpha) { + selectionConfig.focusAlpha = focusAlpha; + return this; + } + + /** + * After recording with the system camera, does it support playing the video immediately using the system player + * + * @param isQuickCapture + * @return + */ + public PictureSelectionModel isQuickCapture (boolean isQuickCapture) { + selectionConfig.isQuickCapture = isQuickCapture; + return this; + } + + /** + * @param isOriginalControl Whether the original image is displayed + * @return + */ + public PictureSelectionModel isOriginalImageControl (boolean isOriginalControl) { + selectionConfig.isOriginalControl = !selectionConfig.camera + && selectionConfig.chooseMode != PictureMimeType.ofVideo() + && selectionConfig.chooseMode != PictureMimeType.ofAudio() && isOriginalControl; + return this; + } + + /** + * @param path save path + * @return + */ + public PictureSelectionModel compressSavePath (String path) { + selectionConfig.compressSavePath = path; + return this; + } + + /** + * Camera custom local file name + * # Such as xxx.png + * + * @param fileName + * @return + */ + public PictureSelectionModel cameraFileName (String fileName) { + selectionConfig.cameraFileName = fileName; + return this; + } + + /** + * crop custom local file name + * # Such as xxx.png + * + * @param renameCropFileName + * @return + */ + public PictureSelectionModel renameCropFileName (String renameCropFileName) { + selectionConfig.renameCropFileName = renameCropFileName; + return this; + } + + /** + * custom compress local file name + * # Such as xxx.png + * + * @param renameFile + * @return + */ + public PictureSelectionModel renameCompressFile (String renameFile) { + selectionConfig.renameCompressFileName = renameFile; + return this; + } + + /** + * @param zoomAnim Picture list zoom anim + * @return + */ + public PictureSelectionModel isZoomAnim (boolean zoomAnim) { + selectionConfig.zoomAnim = zoomAnim; + return this; + } + + /** + * @param previewEggs preview eggs It doesn't make much sense + * @return Use {link .isPreviewEggs()} + */ + @Deprecated + public PictureSelectionModel previewEggs (boolean previewEggs) { + selectionConfig.previewEggs = previewEggs; + return this; + } + + /** + * @param previewEggs preview eggs It doesn't make much sense + * @return + */ + public PictureSelectionModel isPreviewEggs (boolean previewEggs) { + selectionConfig.previewEggs = previewEggs; + return this; + } + + /** + * @param isCamera Whether to open camera button + * @return + */ + public PictureSelectionModel isCamera (boolean isCamera) { + selectionConfig.isCamera = isCamera; + return this; + } + + /** + * Extra used with {@link #Environment.getExternalStorageDirectory() + File.separator + "CustomCamera" + File.separator} to indicate that + * + * @param outPutCameraPath Camera save path 只支持Build.VERSION.SDK_INT < Build.VERSION_CODES.Q + * @return + */ + public PictureSelectionModel setOutputCameraPath (String outPutCameraPath) { + selectionConfig.outPutCameraPath = outPutCameraPath; + return this; + } + + + /** + * # file size The unit is M + * + * @param fileSize Filter file size + * @return + */ + public PictureSelectionModel queryMaxFileSize (float fileSize) { + selectionConfig.filterFileSize = fileSize; + return this; + } + + /** + * @param isGif Whether to open gif + * @return + */ + public PictureSelectionModel isGif (boolean isGif) { + selectionConfig.isGif = isGif; + return this; + } + + /** + * @param isWebp Whether to open .webp + * @return + */ + public PictureSelectionModel isWebp (boolean isWebp) { + selectionConfig.isWebp = isWebp; + return this; + } + + /** + * @param isBmp Whether to open .isBmp + * @return + */ + public PictureSelectionModel isBmp (boolean isBmp) { + selectionConfig.isWebp = isBmp; + return this; + } + + /** + * @param enablePreview Do you want to preview the picture? + * @return Use {link .isPreviewImage()} + */ + @Deprecated + public PictureSelectionModel previewImage (boolean enablePreview) { + selectionConfig.enablePreview = enablePreview; + return this; + } + + /** + * @param enablePreview Do you want to preview the picture? + * @return + */ + public PictureSelectionModel isPreviewImage (boolean enablePreview) { + selectionConfig.enablePreview = enablePreview; + return this; + } + + /** + * @param enPreviewVideo Do you want to preview the video? + * @return Use {link .isPreviewVideo()} + */ + @Deprecated + public PictureSelectionModel previewVideo (boolean enPreviewVideo) { + selectionConfig.enPreviewVideo = enPreviewVideo; + return this; + } + + /** + * @param enPreviewVideo Do you want to preview the video? + * @return + */ + public PictureSelectionModel isPreviewVideo (boolean enPreviewVideo) { + selectionConfig.enPreviewVideo = enPreviewVideo; + return this; + } + + /** + * @param isNotPreviewDownload Previews do not show downloads + * @return + */ + public PictureSelectionModel isNotPreviewDownload (boolean isNotPreviewDownload) { + selectionConfig.isNotPreviewDownload = isNotPreviewDownload; + return this; + } + + /** + * @param Specify get image format + * @return + */ + public PictureSelectionModel querySpecifiedFormatSuffix (String specifiedFormat) { + selectionConfig.specifiedFormat = specifiedFormat; + return this; + } + + /** + * @param openClickSound Whether to open click voice + * @return Use {link .isOpenClickSound()} + */ + @Deprecated + public PictureSelectionModel openClickSound (boolean openClickSound) { + selectionConfig.openClickSound = !selectionConfig.camera && openClickSound; + return this; + } + + /** + * @param isOpenClickSound Whether to open click voice + * @return + */ + public PictureSelectionModel isOpenClickSound (boolean openClickSound) { + selectionConfig.openClickSound = !selectionConfig.camera && openClickSound; + return this; + } + + /** + * 是否可拖动裁剪框(setFreeStyleCropEnabled 为true 有效) + */ + public PictureSelectionModel isDragFrame (boolean isDragFrame) { + selectionConfig.isDragFrame = isDragFrame; + return this; + } + + /** + * Whether the multi-graph clipping list is animated or not + * + * @param isAnimation + * @return + */ + public PictureSelectionModel isMultipleRecyclerAnimation (boolean isAnimation) { + selectionConfig.isMultipleRecyclerAnimation = isAnimation; + return this; + } + + + /** + * 设置摄像头方向(前后 默认后置) + */ + public PictureSelectionModel isCameraAroundState (boolean isCameraAroundState) { + selectionConfig.isCameraAroundState = isCameraAroundState; + return this; + } + + /** + * @param selectionMedia Select the selected picture set + * @return Use {link .selectionData()} + */ + @Deprecated + public PictureSelectionModel selectionMedia (List selectionMedia) { + if (selectionConfig.selectionMode == PictureConfig.SINGLE && selectionConfig.isSingleDirectReturn) { + selectionConfig.selectionMedias = null; + } + else { + selectionConfig.selectionMedias = selectionMedia; + } + return this; + } + + /** + * @param selectionData Select the selected picture set + * @return + */ + public PictureSelectionModel selectionData (List selectionData) { + if (selectionConfig.selectionMode == PictureConfig.SINGLE && selectionConfig.isSingleDirectReturn) { + selectionConfig.selectionMedias = null; + } + else { + selectionConfig.selectionMedias = selectionData; + } + return this; + } + + /** + * 是否改变状态栏字段颜色(黑白字体转换) + * #适合所有style使用 + * + * @param isChangeStatusBarFontColor + * @return + */ + @Deprecated + public PictureSelectionModel isChangeStatusBarFontColor (boolean isChangeStatusBarFontColor) { + selectionConfig.isChangeStatusBarFontColor = isChangeStatusBarFontColor; + return this; + } + + /** + * 选择图片样式0/9 + * #适合所有style使用 + * + * @param isOpenStyleNumComplete + * @return 使用setPictureStyle方法 + */ + @Deprecated + public PictureSelectionModel isOpenStyleNumComplete (boolean isOpenStyleNumComplete) { + selectionConfig.isOpenStyleNumComplete = isOpenStyleNumComplete; + return this; + } + + /** + * 是否开启数字选择模式 + * #适合qq style 样式使用 + * + * @param isOpenStyleCheckNumMode + * @return 使用setPictureStyle方法 + */ + @Deprecated + public PictureSelectionModel isOpenStyleCheckNumMode (boolean isOpenStyleCheckNumMode) { + selectionConfig.isOpenStyleCheckNumMode = isOpenStyleCheckNumMode; + return this; + } + + /** + * 设置标题栏背景色 + * + * @param color + * @return 使用setPictureStyle方法 + */ + @Deprecated + public PictureSelectionModel setTitleBarBackgroundColor (@ColorInt int color) { + selectionConfig.titleBarBackgroundColor = color; + return this; + } + + + /** + * 状态栏背景色 + * + * @param color + * @return 使用setPictureStyle方法 + */ + @Deprecated + public PictureSelectionModel setStatusBarColorPrimaryDark (@ColorInt int color) { + selectionConfig.pictureStatusBarColor = color; + return this; + } + + + /** + * 裁剪页面标题背景色 + * + * @param color + * @return 使用setPictureCropStyle方法 + */ + @Deprecated + public PictureSelectionModel setCropTitleBarBackgroundColor (@ColorInt int color) { + selectionConfig.cropTitleBarBackgroundColor = color; + return this; + } + + /** + * 裁剪页面状态栏背景色 + * + * @param color + * @return 使用setPictureCropStyle方法 + */ + @Deprecated + public PictureSelectionModel setCropStatusBarColorPrimaryDark (@ColorInt int color) { + selectionConfig.cropStatusBarColorPrimaryDark = color; + return this; + } + + /** + * 裁剪页面标题文字颜色 + * + * @param color + * @return 使用setPictureCropStyle方法 + */ + @Deprecated + public PictureSelectionModel setCropTitleColor (@ColorInt int color) { + selectionConfig.cropTitleColor = color; + return this; + } + + /** + * 设置相册标题右侧向上箭头图标 + * + * @param resId + * @return 使用setPictureStyle方法 + */ + @Deprecated + public PictureSelectionModel setUpArrowDrawable (int resId) { + selectionConfig.upResId = resId; + return this; + } + + /** + * 设置相册标题右侧向下箭头图标 + * + * @param resId + * @return 使用setPictureStyle方法 + */ + @Deprecated + public PictureSelectionModel setDownArrowDrawable (int resId) { + selectionConfig.downResId = resId; + return this; + } + + /** + * 动态设置裁剪主题样式 + * + * @param style 裁剪页主题 + *

{@link PictureSelectorUIStyle} + * @return + */ + @Deprecated + public PictureSelectionModel setPictureCropStyle (PictureCropParameterStyle style) { + if (style != null) { + PictureSelectionConfig.cropStyle = style; + } + else { + PictureSelectionConfig.cropStyle = PictureCropParameterStyle.ofDefaultCropStyle(); + } + return this; + } + + /** + * 动态设置相册主题样式 + * + * @param style 主题 + *

{@link PictureSelectorUIStyle} + * @return + */ + @Deprecated + public PictureSelectionModel setPictureStyle (PictureParameterStyle style) { + if (style != null) { + PictureSelectionConfig.style = style; + if (!selectionConfig.isWeChatStyle) { + selectionConfig.isWeChatStyle = style.isNewSelectStyle; + } + } + else { + PictureSelectionConfig.style = PictureParameterStyle.ofDefaultStyle(); + } + return this; + } + + /** + * Dynamically set the album to start and exit the animation + * + * @param style Activity Launch exit animation theme + * @return + */ + public PictureSelectionModel setPictureWindowAnimationStyle (PictureWindowAnimationStyle windowAnimationStyle) { + if (windowAnimationStyle != null) { + PictureSelectionConfig.windowAnimationStyle = windowAnimationStyle; + } + else { + PictureSelectionConfig.windowAnimationStyle = PictureWindowAnimationStyle.ofDefaultWindowAnimationStyle(); + } + return this; + } + + /** + * Photo album list animation {} + * Use {@link AnimationType#ALPHA_IN_ANIMATION or SLIDE_IN_BOTTOM_ANIMATION} directly. + * + * @param animationMode + * @return + */ + public PictureSelectionModel setRecyclerAnimationMode (int animationMode) { + selectionConfig.animationMode = animationMode; + return this; + } + + /** + * # If you want to handle the Android Q path, if not, just return the uri, + * The getAndroidQToPath(); field will be empty + * + * @param isAndroidQTransform + * @return + */ + public PictureSelectionModel isAndroidQTransform (boolean isAndroidQTransform) { + selectionConfig.isAndroidQTransform = isAndroidQTransform; + return this; + } + + /** + * # 内部方法-要使用此方法时最好先咨询作者!!! + * + * @param isFallbackVersion 仅供特殊情况内部使用 如果某功能出错此开关可以回退至之前版本 + * @return + */ + public PictureSelectionModel isFallbackVersion (boolean isFallbackVersion) { + selectionConfig.isFallbackVersion = isFallbackVersion; + return this; + } + + /** + * # 内部方法-要使用此方法时最好先咨询作者!!! + * + * @param isFallbackVersion 仅供特殊情况内部使用 如果某功能出错此开关可以回退至之前版本 + * @return + */ + public PictureSelectionModel isFallbackVersion2 (boolean isFallbackVersion) { + selectionConfig.isFallbackVersion2 = isFallbackVersion; + return this; + } + + /** + * # 内部方法-要使用此方法时最好先咨询作者!!! + * + * @param isFallbackVersion 仅供特殊情况内部使用 如果某功能出错此开关可以回退至之前版本 + * @return + */ + public PictureSelectionModel isFallbackVersion3 (boolean isFallbackVersion) { + selectionConfig.isFallbackVersion3 = isFallbackVersion; + return this; + } + + /** + * Start to select media and wait for result. + * + * @param requestCode Identity of the request Activity or Fragment. + */ + public void forResult (int requestCode) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null || selectionConfig == null) { + return; + } + Intent intent; + if (selectionConfig.camera && selectionConfig.isUseCustomCamera) { + intent = new Intent(activity, PictureCustomCameraActivity.class); + } + else { + if (selectionConfig.camera) { + intent = new Intent(activity, PictureSelectorCameraEmptyActivity.class); + } + else if (selectionConfig.isWeChatStyle) { + intent = new Intent(activity, PictureSelectorWeChatStyleActivity.class); + } + else if (selectionConfig.isDoctalkStyle) { + intent = new Intent(activity, PictureSelectorDoctalkActivity.class); + } + else { + intent = new Intent(activity, PictureSelectorActivity.class); + } + } + selectionConfig.isCallbackMode = false; + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivityForResult(intent, requestCode); + } + else { + activity.startActivityForResult(intent, requestCode); + } + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + + /** + * # replace for setPictureWindowAnimationStyle(); + * Start to select media and wait for result. + *

+ * # Use PictureWindowAnimationStyle to achieve animation effects + * + * @param requestCode Identity of the request Activity or Fragment. + */ + @Deprecated + public void forResult (int requestCode, int enterAnim, int exitAnim) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null) { + return; + } + Intent intent; + if (selectionConfig.camera) { + intent = new Intent(activity, PictureSelectorCameraEmptyActivity.class); + } + else if (selectionConfig.isWeChatStyle) { + intent = new Intent(activity, PictureSelectorWeChatStyleActivity.class); + } + else if (selectionConfig.isDoctalkStyle) { + intent = new Intent(activity, PictureSelectorDoctalkActivity.class); + } + else { + intent = new Intent(activity, PictureSelectorActivity.class); + } + + selectionConfig.isCallbackMode = false; + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivityForResult(intent, requestCode); + } + else { + activity.startActivityForResult(intent, requestCode); + } + activity.overridePendingTransition(enterAnim, exitAnim); + } + } + + + /** + * Start to select media and wait for result. + * + * @param listener The resulting callback listens + */ + public void forResult (OnResultCallbackListener listener) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null || selectionConfig == null) { + return; + } + // 绑定回调监听 + PictureSelectionConfig.listener = new WeakReference<>(listener).get(); + selectionConfig.isCallbackMode = true; + Intent intent; + if (selectionConfig.camera && selectionConfig.isUseCustomCamera) { + intent = new Intent(activity, PictureCustomCameraActivity.class); + } + else { + + if (selectionConfig.camera) { + intent = new Intent(activity, PictureSelectorCameraEmptyActivity.class); + } + else if (selectionConfig.isWeChatStyle) { + intent = new Intent(activity, PictureSelectorWeChatStyleActivity.class); + } + else if (selectionConfig.isDoctalkStyle) { + intent = new Intent(activity, PictureSelectorDoctalkActivity.class); + } + else { + intent = new Intent(activity, PictureSelectorActivity.class); + } + } + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivity(intent); + } + else { + activity.startActivity(intent); + } + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition( + windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + + /** + * Start to select media and wait for result. + * + * @param requestCode Identity of the request Activity or Fragment. + * @param listener The resulting callback listens + */ + public void forResult (int requestCode, OnResultCallbackListener listener) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null || selectionConfig == null) { + return; + } + // 绑定回调监听 + PictureSelectionConfig.listener = new WeakReference<>(listener).get(); + selectionConfig.isCallbackMode = true; + Intent intent; + if (selectionConfig.camera && selectionConfig.isUseCustomCamera) { + intent = new Intent(activity, PictureCustomCameraActivity.class); + } + else { + + if (selectionConfig.camera) { + intent = new Intent(activity, PictureSelectorCameraEmptyActivity.class); + } + else if (selectionConfig.isWeChatStyle) { + intent = new Intent(activity, PictureSelectorWeChatStyleActivity.class); + } + else if (selectionConfig.isDoctalkStyle) { + intent = new Intent(activity, PictureSelectorDoctalkActivity.class); + } + else { + intent = new Intent(activity, PictureSelectorActivity.class); + } + } + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivityForResult(intent, requestCode); + } + else { + activity.startActivityForResult(intent, requestCode); + } + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + + /** + * 提供外部预览图片方法 + * + * @param position + * @param medias + */ + public void openExternalPreview (int position, List medias) { + if (selector != null) { + selector.externalPicturePreview(position, medias, PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation); + } + else { + throw new NullPointerException("This PictureSelector is Null"); + } + } + + + /** + * 提供外部预览图片方法-带自定义下载保存路径 + * # 废弃 由于Android Q沙盒机制 此方法不在需要了 + * + * @param position + * @param medias + */ + @Deprecated + public void openExternalPreview (int position, String directory_path, List medias) { + if (selector != null) { + selector.externalPicturePreview(position, directory_path, medias, + PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation); + } + else { + throw new NullPointerException("This PictureSelector is Null"); + } + } + + /** + * set preview video + * + * @param path + */ + public void externalPictureVideo (String path) { + if (selector != null) { + selector.externalPictureVideo(path); + } + else { + throw new NullPointerException("This PictureSelector is Null"); + } + } } diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectorDoctalkActivity.java b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectorDoctalkActivity.java new file mode 100644 index 000000000..8321c4b91 --- /dev/null +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectorDoctalkActivity.java @@ -0,0 +1,2312 @@ +package com.luck.picture.lib; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Parcelable; +import android.os.SystemClock; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; + +import com.luck.picture.lib.adapter.PictureImageGridAdapter; +import com.luck.picture.lib.animators.AlphaInAnimationAdapter; +import com.luck.picture.lib.animators.AnimationType; +import com.luck.picture.lib.animators.SlideInBottomAnimationAdapter; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.config.PictureSelectionConfig; +import com.luck.picture.lib.decoration.GridSpacingItemDecoration; +import com.luck.picture.lib.dialog.PhotoItemSelectedDialog; +import com.luck.picture.lib.dialog.PictureCustomDialog; +import com.luck.picture.lib.entity.LocalMedia; +import com.luck.picture.lib.entity.LocalMediaFolder; +import com.luck.picture.lib.listener.OnAlbumItemClickListener; +import com.luck.picture.lib.listener.OnItemClickListener; +import com.luck.picture.lib.listener.OnPhotoSelectChangedListener; +import com.luck.picture.lib.listener.OnQueryDataResultListener; +import com.luck.picture.lib.listener.OnRecyclerViewPreloadMoreListener; +import com.luck.picture.lib.manager.UCropManager; +import com.luck.picture.lib.model.LocalMediaLoader; +import com.luck.picture.lib.model.LocalMediaPageLoader; +import com.luck.picture.lib.observable.ImagesObservable; +import com.luck.picture.lib.permissions.PermissionChecker; +import com.luck.picture.lib.style.PictureWindowAnimationStyle; +import com.luck.picture.lib.thread.PictureThreadUtils; +import com.luck.picture.lib.tools.AttrsUtils; +import com.luck.picture.lib.tools.BitmapUtils; +import com.luck.picture.lib.tools.DateUtils; +import com.luck.picture.lib.tools.DoubleUtils; +import com.luck.picture.lib.tools.JumpUtils; +import com.luck.picture.lib.tools.MediaUtils; +import com.luck.picture.lib.tools.PictureFileUtils; +import com.luck.picture.lib.tools.ScreenUtils; +import com.luck.picture.lib.tools.SdkVersionUtils; +import com.luck.picture.lib.tools.StringUtils; +import com.luck.picture.lib.tools.ToastUtils; +import com.luck.picture.lib.tools.ValueOf; +import com.luck.picture.lib.widget.FolderPopWindow; +import com.luck.picture.lib.widget.RecyclerPreloadView; +import com.yalantis.ucrop.UCrop; +import com.yalantis.ucrop.model.CutInfo; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * @author:JGPak + * @data:2021.03.31 + * @describe: PictureSelectorActivity + */ +public class PictureSelectorDoctalkActivity extends PictureBaseActivity implements View.OnClickListener, OnAlbumItemClickListener, OnPhotoSelectChangedListener, OnItemClickListener, OnRecyclerViewPreloadMoreListener { + + private static final String TAG = PictureSelectorDoctalkActivity.class.getSimpleName(); + + // 상단 왼쪽 뒤로가기 버튼 + protected ImageView mIvPictureLeftBack; + // 폴더 접이 화살표 + protected ImageView mIvArrow; + // 상단 타이틀바 레이아웃 + protected View mTitleBar; + // 상단 타이틀 클릭 이펙트 + protected View viewClickMask; + // 상단 타이틀 텍스트 + protected TextView mTvPictureTitle; + // 상단 타이틀 오른쪽 버튼 + protected TextView mTvPictureRight; + + // 오디오 플레이 버튼 + protected TextView mTvPlayPause; + // 오디오 멈춤 버튼 + protected TextView mTvStop; + // 오디오 종료 버튼 + protected TextView mTvQuit; + // 오디오 상태 정보 + protected TextView mTvMusicStatus; + // 오디오 총 시간 길이 + protected TextView mTvMusicTotal; + // 오디오 현재 시간위치 + protected TextView mTvMusicTime; + // 오디오 재생 플레이어 + protected MediaPlayer mediaPlayer; + // 오디오 SeekBar + protected SeekBar musicSeekBar; + public Runnable mRunnable = new Runnable() { + @Override + public void run () { + try { + if (mediaPlayer != null) { + mTvMusicTime.setText(DateUtils.formatDurationTime(mediaPlayer.getCurrentPosition())); + musicSeekBar.setProgress(mediaPlayer.getCurrentPosition()); + musicSeekBar.setMax(mediaPlayer.getDuration()); + mTvMusicTotal.setText(DateUtils.formatDurationTime(mediaPlayer.getDuration())); + if (mHandler != null) { + mHandler.postDelayed(mRunnable, 200); + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + }; + // 오디오 재생 여부 + protected boolean isPlayAudio = false; + // 리스트뷰 + protected RecyclerPreloadView mRecyclerView; + // 아답터 + protected PictureImageGridAdapter mAdapter; + // 미디어가 없을 때 표시 + protected TextView mTvEmpty; + // 폴더 팝업 + protected FolderPopWindow folderWindow; + // 애니메이션 정의 + protected Animation animation = null; + // 애니메이션 시작 여부 + protected boolean isStartAnimation = false; + // 커스텀 다이얼로그 팝업 + protected PictureCustomDialog audioDialog; + // 이전 선택 이미지 사이즈 + protected int oldCurrentListSize; + // 해당 화면 진입해서 초기화 여부 + protected boolean isEnterSetting; + // 최상위 이동 인터벌 처리 + private long intervalClickTime = 0; + // 해당 폴더안에 이미지 갯수 + private int allFolderSize; + // 카메라 수 + private int mOpenCameraCount; + + @Override + protected void onCreate (Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + allFolderSize = savedInstanceState.getInt(PictureConfig.EXTRA_ALL_FOLDER_SIZE); + oldCurrentListSize = savedInstanceState.getInt(PictureConfig.EXTRA_OLD_CURRENT_LIST_SIZE, 0); + List cacheData = PictureSelector.obtainSelectorList(savedInstanceState); + selectionMedias = cacheData != null ? cacheData : selectionMedias; + if (mAdapter != null) { + isStartAnimation = true; + mAdapter.bindSelectData(selectionMedias); + } + } + } + + @Override + protected void onResume () { + super.onResume(); + if (isEnterSetting) { + if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && + PermissionChecker.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + + if (mAdapter.isDataEmpty()) { + readLocalMedia(); + } + } + else { + showPermissionsDialog(false, getString(R.string.picture_jurisdiction)); + } + isEnterSetting = false; + } + } + + @Override + public int getResourceId () { + return R.layout.picture_doctalk; + } + + @Override + protected void initWidgets () { + super.initWidgets(); + container = findViewById(R.id.container); + mTitleBar = findViewById(R.id.titleBar); + mIvPictureLeftBack = findViewById(R.id.pictureLeftBack); + mTvPictureTitle = findViewById(R.id.picture_title); + mTvPictureRight = findViewById(R.id.picture_right); + mIvArrow = findViewById(R.id.ivArrow); + viewClickMask = findViewById(R.id.viewClickMask); + mRecyclerView = findViewById(R.id.picture_recycler); + mTvEmpty = findViewById(R.id.tv_empty); + isNumComplete(numComplete); + if (!numComplete) { + animation = AnimationUtils.loadAnimation(this, R.anim.picture_anim_modal_in); + } + if (config.isAutomaticTitleRecyclerTop) { + mTitleBar.setOnClickListener(this); + } + mIvPictureLeftBack.setOnClickListener(this); + mTvPictureRight.setOnClickListener(this); + viewClickMask.setOnClickListener(this); + mTvPictureTitle.setOnClickListener(this); + mIvArrow.setOnClickListener(this); + //noinspection deprecation + String title = config.chooseMode == PictureMimeType.ofAudio() ? getString(R.string.picture_all_audio) : getString(R.string.picture_camera_roll); + mTvPictureTitle.setText(title); + mTvPictureTitle.setTag(R.id.view_tag, -1); + folderWindow = new FolderPopWindow(this); + folderWindow.setArrowImageView(mIvArrow); + folderWindow.setOnAlbumItemClickListener(this); + mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(config.imageSpanCount <= 0 ? PictureConfig.DEFAULT_SPAN_COUNT : config.imageSpanCount, ScreenUtils.dip2px(this, 2), false)); + mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), config.imageSpanCount <= 0 ? PictureConfig.DEFAULT_SPAN_COUNT : config.imageSpanCount)); + if (!config.isPageStrategy) { + mRecyclerView.setHasFixedSize(true); + } + else { + mRecyclerView.setReachBottomRow(RecyclerPreloadView.BOTTOM_PRELOAD); + mRecyclerView.setOnRecyclerViewPreloadListener(PictureSelectorDoctalkActivity.this); + } + RecyclerView.ItemAnimator itemAnimator = mRecyclerView.getItemAnimator(); + if (itemAnimator != null) { + ((SimpleItemAnimator) itemAnimator).setSupportsChangeAnimations(false); + mRecyclerView.setItemAnimator(null); + } + loadAllMediaData(); + //noinspection deprecation + mTvEmpty.setText(config.chooseMode == PictureMimeType.ofAudio() ? getString(R.string.picture_audio_empty) : getString(R.string.picture_empty)); + StringUtils.tempTextFont(mTvEmpty, config.chooseMode); + mAdapter = new PictureImageGridAdapter(getContext(), config); + mAdapter.setOnPhotoSelectChangedListener(this); + + switch (config.animationMode) { + case AnimationType.ALPHA_IN_ANIMATION: + mRecyclerView.setAdapter(new AlphaInAnimationAdapter(mAdapter)); + break; + case AnimationType.SLIDE_IN_BOTTOM_ANIMATION: + mRecyclerView.setAdapter(new SlideInBottomAnimationAdapter(mAdapter)); + break; + default: + mRecyclerView.setAdapter(mAdapter); + break; + } + } + + @Override + public void onRecyclerViewPreloadMore () { + loadMoreData(); + } + + /** + * getPageLimit + * # If the user clicks to take a photo and returns, the Limit should be adjusted dynamically + * + * @return + */ + private int getPageLimit () { + int bucketId = ValueOf.toInt(mTvPictureTitle.getTag(R.id.view_tag)); + if (bucketId == -1) { + int limit = mOpenCameraCount > 0 ? config.pageSize - mOpenCameraCount : config.pageSize; + mOpenCameraCount = 0; + return limit; + } + return config.pageSize; + } + + /** + * load more data + */ + private void loadMoreData () { + if (mAdapter != null) { + if (isHasMore) { + mPage++; + long bucketId = ValueOf.toLong(mTvPictureTitle.getTag(R.id.view_tag)); + LocalMediaPageLoader.getInstance(getContext()).loadPageMediaData(bucketId, mPage, getPageLimit(), + (OnQueryDataResultListener) (result, currentPage, isHasMore) -> { + if (!isFinishing()) { + this.isHasMore = isHasMore; + if (isHasMore) { + hideDataNull(); + int size = result.size(); + if (size > 0) { + int positionStart = mAdapter.getSize(); + mAdapter.getData().addAll(result); + int itemCount = mAdapter.getItemCount(); + mAdapter.notifyItemRangeChanged(positionStart, itemCount); + } + else { + onRecyclerViewPreloadMore(); + } + if (size < PictureConfig.MIN_PAGE_SIZE) { + mRecyclerView.onScrolled(mRecyclerView.getScrollX(), mRecyclerView.getScrollY()); + } + } + else { + boolean isEmpty = mAdapter.isDataEmpty(); + if (isEmpty) { + showDataNull(bucketId == -1 ? getString(R.string.picture_empty) : getString(R.string.picture_data_null), R.drawable.picture_icon_no_data); + } + } + } + }); + } + } + } + + /** + * load All Data + */ + private void loadAllMediaData () { + if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && + PermissionChecker.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + + readLocalMedia(); + } + else { + PermissionChecker.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE); + } + } + + @Override + public void initPictureSelectorStyle () { + if (PictureSelectionConfig.uiStyle != null) { + if (PictureSelectionConfig.uiStyle.picture_top_titleArrowDownDrawable != 0) { + Drawable drawable = ContextCompat.getDrawable(this, PictureSelectionConfig.uiStyle.picture_top_titleArrowDownDrawable); + mIvArrow.setImageDrawable(drawable); + } + + if (PictureSelectionConfig.uiStyle.picture_top_titleTextColor != 0) { + mTvPictureTitle.setTextColor(PictureSelectionConfig.uiStyle.picture_top_titleTextColor); + } + if (PictureSelectionConfig.uiStyle.picture_top_titleTextSize != 0) { + mTvPictureTitle.setTextSize(PictureSelectionConfig.uiStyle.picture_top_titleTextSize); + } + if (PictureSelectionConfig.uiStyle.picture_top_titleRightTextColor.length > 0) { + ColorStateList colorStateList = AttrsUtils.getColorStateList(PictureSelectionConfig.uiStyle.picture_top_titleRightTextColor); + if (colorStateList != null) { + mTvPictureRight.setTextColor(colorStateList); + } + } + if (PictureSelectionConfig.uiStyle.picture_top_titleRightTextSize != 0) { + mTvPictureRight.setTextSize(PictureSelectionConfig.uiStyle.picture_top_titleRightTextSize); + } + if (PictureSelectionConfig.uiStyle.picture_top_leftBack != 0) { + mIvPictureLeftBack.setImageResource(PictureSelectionConfig.uiStyle.picture_top_leftBack); + } + + if (PictureSelectionConfig.uiStyle.picture_container_backgroundColor != 0) { + container.setBackgroundColor(PictureSelectionConfig.uiStyle.picture_container_backgroundColor); + } + if (PictureSelectionConfig.uiStyle.picture_top_titleRightDefaultText != 0) { + mTvPictureRight.setText(PictureSelectionConfig.uiStyle.picture_top_titleRightDefaultText); + } + + if (PictureSelectionConfig.uiStyle.picture_top_titleArrowLeftPadding != 0) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvArrow.getLayoutParams(); + params.leftMargin = PictureSelectionConfig.uiStyle.picture_top_titleArrowLeftPadding; + } + + if (PictureSelectionConfig.uiStyle.picture_top_titleBarHeight > 0) { + ViewGroup.LayoutParams params = mTitleBar.getLayoutParams(); + params.height = PictureSelectionConfig.uiStyle.picture_top_titleBarHeight; + } + } + else if (PictureSelectionConfig.style != null) { + if (PictureSelectionConfig.style.pictureTitleDownResId != 0) { + Drawable drawable = ContextCompat.getDrawable(this, PictureSelectionConfig.style.pictureTitleDownResId); + mIvArrow.setImageDrawable(drawable); + } + if (PictureSelectionConfig.style.pictureTitleTextColor != 0) { + mTvPictureTitle.setTextColor(PictureSelectionConfig.style.pictureTitleTextColor); + } + if (PictureSelectionConfig.style.pictureTitleTextSize != 0) { + mTvPictureTitle.setTextSize(PictureSelectionConfig.style.pictureTitleTextSize); + } + + if (PictureSelectionConfig.style.pictureRightDefaultTextColor != 0) { + mTvPictureRight.setTextColor(PictureSelectionConfig.style.pictureRightDefaultTextColor); + } + else { + //noinspection deprecation + if (PictureSelectionConfig.style.pictureCancelTextColor != 0) { + //noinspection deprecation + mTvPictureRight.setTextColor(PictureSelectionConfig.style.pictureCancelTextColor); + } + } + if (PictureSelectionConfig.style.pictureRightTextSize != 0) { + mTvPictureRight.setTextSize(PictureSelectionConfig.style.pictureRightTextSize); + } + + if (PictureSelectionConfig.style.pictureLeftBackIcon != 0) { + mIvPictureLeftBack.setImageResource(PictureSelectionConfig.style.pictureLeftBackIcon); + } + if (PictureSelectionConfig.style.pictureContainerBackgroundColor != 0) { + container.setBackgroundColor(PictureSelectionConfig.style.pictureContainerBackgroundColor); + } + if (!TextUtils.isEmpty(PictureSelectionConfig.style.pictureRightDefaultText)) { + mTvPictureRight.setText(PictureSelectionConfig.style.pictureRightDefaultText); + } + + if (PictureSelectionConfig.style.pictureTitleRightArrowLeftPadding != 0) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvArrow.getLayoutParams(); + params.leftMargin = PictureSelectionConfig.style.pictureTitleRightArrowLeftPadding; + } + + if (PictureSelectionConfig.style.pictureTitleBarHeight > 0) { + ViewGroup.LayoutParams params = mTitleBar.getLayoutParams(); + params.height = PictureSelectionConfig.style.pictureTitleBarHeight; + } + } + else { + int titleColor = AttrsUtils.getTypeValueColor(getContext(), R.attr.picture_title_textColor); + if (titleColor != 0) { + mTvPictureTitle.setTextColor(titleColor); + } + int rightTitleColor = AttrsUtils.getTypeValueColor(getContext(), R.attr.picture_right_textColor); + if (rightTitleColor != 0) { + mTvPictureRight.setTextColor(rightTitleColor); + } + int containerBackgroundColor = AttrsUtils.getTypeValueColor(getContext(), R.attr.picture_container_backgroundColor); + if (containerBackgroundColor != 0) { + container.setBackgroundColor(containerBackgroundColor); + } + Drawable leftDrawable = AttrsUtils.getTypeValueDrawable(getContext(), R.attr.picture_leftBack_icon, R.drawable.picture_icon_back); + mIvPictureLeftBack.setImageDrawable(leftDrawable); + + //noinspection deprecation + if (config.downResId != 0) { + //noinspection deprecation + Drawable drawable = ContextCompat.getDrawable(this, config.downResId); + mIvArrow.setImageDrawable(drawable); + } + else { + Drawable downDrawable = AttrsUtils.getTypeValueDrawable(getContext(), R.attr.picture_arrow_down_icon, R.drawable.picture_icon_arrow_down); + mIvArrow.setImageDrawable(downDrawable); + } + int pictureTitleRightArrowLeftPadding = AttrsUtils.getTypeValueSizeForInt(getContext(), R.attr.picture_titleRightArrow_LeftPadding); + if (pictureTitleRightArrowLeftPadding != 0) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvArrow.getLayoutParams(); + params.leftMargin = pictureTitleRightArrowLeftPadding; + } + + int titleBarHeight = AttrsUtils.getTypeValueSizeForInt(getContext(), R.attr.picture_titleBar_height); + if (titleBarHeight > 0) { + ViewGroup.LayoutParams params = mTitleBar.getLayoutParams(); + params.height = titleBarHeight; + } + } + mTitleBar.setBackgroundColor(colorPrimary); + mAdapter.bindSelectData(selectionMedias); + } + + @Override + protected void onSaveInstanceState (@NotNull Bundle outState) { + super.onSaveInstanceState(outState); + if (mAdapter != null) { + // Save the number of pictures or videos in the current list + outState.putInt(PictureConfig.EXTRA_OLD_CURRENT_LIST_SIZE, mAdapter.getSize()); + // Save the number of Camera film and Camera folder files + int size = folderWindow.getFolderData().size(); + if (size > 0) { + outState.putInt(PictureConfig.EXTRA_ALL_FOLDER_SIZE, folderWindow.getFolder(0).getImageNum()); + } + if (mAdapter.getSelectedData() != null) { + List selectedImages = mAdapter.getSelectedData(); + PictureSelector.saveSelectorList(outState, selectedImages); + } + } + } + + /** + * none number style + */ + private void isNumComplete (boolean numComplete) { + if (numComplete) { + initCompleteText(0); + } + } + + /** + * init Text + */ + @Override + protected void initCompleteText (int startCount) { + if (config.selectionMode == PictureConfig.SINGLE) { + if (startCount <= 0) { + mTvPictureRight.setText(getString(R.string.picture_cancel)); + } + else { + mTvPictureRight.setText(getString(R.string.picture_done)); + } + } + else { + if (startCount <= 0) { + mTvPictureRight.setText(getString(R.string.picture_cancel)); + } + else { + mTvPictureRight.setText(getString(R.string.picture_done_count, startCount)); + } + } + } + + /** + * get LocalMedia s + */ + protected void readLocalMedia () { + showPleaseDialog(); + if (config.isPageStrategy) { + LocalMediaPageLoader.getInstance(getContext()).loadAllMedia( + (data, currentPage, isHasMore) -> { + if (!isFinishing()) { + this.isHasMore = true; + initPageModel(data); + synchronousCover(); + } + }); + } + else { + PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask>() { + + @Override + public List doInBackground () { + //noinspection deprecation + return new LocalMediaLoader(getContext()).loadAllMedia(); + } + + @Override + public void onSuccess (List folders) { + initStandardModel(folders); + } + }); + } + } + + /** + * Page Model + * + * @param folders folders + */ + private void initPageModel (List folders) { + if (folders != null) { + folderWindow.bindFolder(folders); + mPage = 1; + LocalMediaFolder folder = folderWindow.getFolder(0); + mTvPictureTitle.setTag(R.id.view_count_tag, folder != null ? folder.getImageNum() : 0); + mTvPictureTitle.setTag(R.id.view_index_tag, 0); + long bucketId = folder != null ? folder.getBucketId() : -1; + mRecyclerView.setEnabledLoadMore(true); + LocalMediaPageLoader.getInstance(getContext()).loadPageMediaData(bucketId, mPage, + (data, currentPage, isHasMore) -> { + if (!isFinishing()) { + dismissDialog(); + if (mAdapter != null) { + this.isHasMore = true; + // IsHasMore being true means that there's still data, but data being 0 might be a filter that's turned on and that doesn't happen to fit on the whole page + if (isHasMore && data.size() == 0) { + onRecyclerViewPreloadMore(); + return; + } + int currentSize = mAdapter.getSize(); + int resultSize = data.size(); + oldCurrentListSize = oldCurrentListSize + currentSize; + if (resultSize >= currentSize) { + // This situation is mainly caused by the use of camera memory, the Activity is recycled + if (currentSize > 0 && currentSize < resultSize && oldCurrentListSize != resultSize) { + if (isLocalMediaSame(data.get(0))) { + mAdapter.bindData(data); + } + else { + mAdapter.getData().addAll(data); + } + } + else { + mAdapter.bindData(data); + } + } + boolean isEmpty = mAdapter.isDataEmpty(); + if (isEmpty) { + showDataNull(getString(R.string.picture_empty), R.drawable.picture_icon_no_data); + } + else { + hideDataNull(); + } + + } + } + }); + } + else { + showDataNull(getString(R.string.picture_data_exception), R.drawable.picture_icon_data_error); + dismissDialog(); + } + } + + /** + * ofAll Page Model Synchronous cover + */ + private void synchronousCover () { + if (config.chooseMode == PictureMimeType.ofAll()) { + PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask() { + + @Override + public Boolean doInBackground () { + int size = folderWindow.getFolderData().size(); + for (int i = 0; i < size; i++) { + LocalMediaFolder mediaFolder = folderWindow.getFolder(i); + if (mediaFolder == null) { + continue; + } + String firstCover = LocalMediaPageLoader + .getInstance(getContext()).getFirstCover(mediaFolder.getBucketId()); + mediaFolder.setFirstImagePath(firstCover); + } + return true; + } + + @Override + public void onSuccess (Boolean result) { + // TODO Synchronous Success + } + }); + } + } + + /** + * Standard Model + * + * @param folders folders + */ + private void initStandardModel (List folders) { + if (folders != null) { + if (folders.size() > 0) { + folderWindow.bindFolder(folders); + LocalMediaFolder folder = folders.get(0); + folder.setChecked(true); + mTvPictureTitle.setTag(R.id.view_count_tag, folder.getImageNum()); + List result = folder.getData(); + if (mAdapter != null) { + int currentSize = mAdapter.getSize(); + int resultSize = result.size(); + oldCurrentListSize = oldCurrentListSize + currentSize; + if (resultSize >= currentSize) { + // This situation is mainly caused by the use of camera memory, the Activity is recycled + if (currentSize > 0 && currentSize < resultSize && oldCurrentListSize != resultSize) { + mAdapter.getData().addAll(result); + LocalMedia media = mAdapter.getData().get(0); + folder.setFirstImagePath(media.getPath()); + folder.getData().add(0, media); + folder.setCheckedNum(1); + folder.setImageNum(folder.getImageNum() + 1); + updateMediaFolder(folderWindow.getFolderData(), media); + } + else { + mAdapter.bindData(result); + } + } + boolean isEmpty = mAdapter.isDataEmpty(); + if (isEmpty) { + showDataNull(getString(R.string.picture_empty), R.drawable.picture_icon_no_data); + } + else { + hideDataNull(); + } + } + } + else { + showDataNull(getString(R.string.picture_empty), R.drawable.picture_icon_no_data); + } + } + else { + showDataNull(getString(R.string.picture_data_exception), R.drawable.picture_icon_data_error); + } + dismissDialog(); + } + + /** + * isSame + * + * @param newMedia new media + * @return same media true/false + */ + private boolean isLocalMediaSame (LocalMedia newMedia) { + LocalMedia oldMedia = mAdapter.getItem(0); + if (oldMedia == null || newMedia == null) { + return false; + } + if (oldMedia.getPath().equals(newMedia.getPath())) { + return true; + } + // if Content:// type,determines whether the suffix id is consistent, mainly to solve the following two types of problems + // content://media/external/images/media/5844 + // content://media/external/file/5844 + if (PictureMimeType.isContent(newMedia.getPath()) + && PictureMimeType.isContent(oldMedia.getPath())) { + if (!TextUtils.isEmpty(newMedia.getPath()) && !TextUtils.isEmpty(oldMedia.getPath())) { + String newId = newMedia.getPath().substring(newMedia.getPath().lastIndexOf("/") + 1); + String oldId = oldMedia.getPath().substring(oldMedia.getPath().lastIndexOf("/") + 1); + return newId.equals(oldId); + } + } + return false; + } + + /** + * Open Camera + */ + public void startCamera () { + if (!DoubleUtils.isFastDoubleClick()) { + if (PictureSelectionConfig.onCustomCameraInterfaceListener != null) { + if (config.chooseMode == PictureConfig.TYPE_ALL) { + PhotoItemSelectedDialog selectedDialog = PhotoItemSelectedDialog.newInstance(); + selectedDialog.setOnItemClickListener(this); + selectedDialog.show(getSupportFragmentManager(), "PhotoItemSelectedDialog"); + } + else { + PictureSelectionConfig.onCustomCameraInterfaceListener.onCameraClick(getContext(), config, config.chooseMode); + config.cameraMimeType = config.chooseMode; + } + return; + } + if (config.isUseCustomCamera) { + startCustomCamera(); + return; + } + switch (config.chooseMode) { + case PictureConfig.TYPE_ALL: + PhotoItemSelectedDialog selectedDialog = PhotoItemSelectedDialog.newInstance(); + selectedDialog.setOnItemClickListener(this); + selectedDialog.show(getSupportFragmentManager(), "PhotoItemSelectedDialog"); + break; + case PictureConfig.TYPE_IMAGE: + startOpenCamera(); + break; + case PictureConfig.TYPE_VIDEO: + startOpenCameraVideo(); + break; + case PictureConfig.TYPE_AUDIO: + startOpenCameraAudio(); + break; + default: + break; + } + } + } + + /** + * Open Custom Camera + */ + private void startCustomCamera () { + if (PermissionChecker.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)) { + Intent intent = new Intent(this, PictureCustomCameraActivity.class); + startActivityForResult(intent, PictureConfig.REQUEST_CAMERA); + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + else { + PermissionChecker + .requestPermissions(this, + new String[]{Manifest.permission.RECORD_AUDIO}, PictureConfig.APPLY_RECORD_AUDIO_PERMISSIONS_CODE); + } + } + + @Override + public void onClick (View v) { + int id = v.getId(); + if (id == R.id.pictureLeftBack) { + if (folderWindow != null && folderWindow.isShowing()) { + folderWindow.dismiss(); + } + else { + onBackPressed(); + } + } + else if (id == R.id.picture_title || id == R.id.ivArrow || id == R.id.viewClickMask) { + if (folderWindow.isShowing()) { + folderWindow.dismiss(); + } + else { + if (!folderWindow.isEmpty()) { + folderWindow.showAsDropDown(mTitleBar); + if (!config.isSingleDirectReturn) { + List selectedImages = mAdapter.getSelectedData(); + folderWindow.updateFolderCheckStatus(selectedImages); + } + } + } + } + else if (id == R.id.picture_id_preview) { + onPreview(); + } + else if (id == R.id.picture_right) { + if (mAdapter.getSelectedSize() <= 0) { + if (folderWindow != null && folderWindow.isShowing()) { + folderWindow.dismiss(); + } + else { + onBackPressed(); + } + } + else { + onComplete(); + } + } + else if (id == R.id.titleBar) { + if (config.isAutomaticTitleRecyclerTop) { + int intervalTime = 500; + if (SystemClock.uptimeMillis() - intervalClickTime < intervalTime) { + if (mAdapter.getItemCount() > 0) { + mRecyclerView.scrollToPosition(0); + } + } + else { + intervalClickTime = SystemClock.uptimeMillis(); + } + } + } + } + + /** + * Preview + */ + private void onPreview () { + List selectedData = mAdapter.getSelectedData(); + List medias = new ArrayList<>(); + int size = selectedData.size(); + for (int i = 0; i < size; i++) { + LocalMedia media = selectedData.get(i); + medias.add(media); + } + if (PictureSelectionConfig.onCustomImagePreviewCallback != null) { + //noinspection unchecked + PictureSelectionConfig.onCustomImagePreviewCallback.onCustomPreviewCallback(getContext(), selectedData, 0); + return; + } + Bundle bundle = new Bundle(); + bundle.putParcelableArrayList(PictureConfig.EXTRA_PREVIEW_SELECT_LIST, (ArrayList) medias); + bundle.putParcelableArrayList(PictureConfig.EXTRA_SELECT_LIST, (ArrayList) selectedData); + bundle.putBoolean(PictureConfig.EXTRA_BOTTOM_PREVIEW, true); + bundle.putBoolean(PictureConfig.EXTRA_CHANGE_ORIGINAL, config.isCheckOriginalImage); + bundle.putBoolean(PictureConfig.EXTRA_SHOW_CAMERA, mAdapter.isShowCamera()); + bundle.putString(PictureConfig.EXTRA_IS_CURRENT_DIRECTORY, mTvPictureTitle.getText().toString()); + JumpUtils.startPicturePreviewActivity(getContext(), config.isWeChatStyle, bundle, + config.selectionMode == PictureConfig.SINGLE ? UCrop.REQUEST_CROP : UCrop.REQUEST_MULTI_CROP); + + overridePendingTransition(PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation, + R.anim.picture_anim_fade_in); + } + + /** + * Complete + */ + private void onComplete () { + List result = mAdapter.getSelectedData(); + int size = result.size(); + LocalMedia image = result.size() > 0 ? result.get(0) : null; + String mimeType = image != null ? image.getMimeType() : ""; + boolean isHasImage = PictureMimeType.isHasImage(mimeType); + if (config.isWithVideoImage) { + int videoSize = 0; + int imageSize = 0; + for (int i = 0; i < size; i++) { + LocalMedia media = result.get(i); + if (PictureMimeType.isHasVideo(media.getMimeType())) { + videoSize++; + } + else { + imageSize++; + } + } + if (config.selectionMode == PictureConfig.MULTIPLE) { + if (config.minSelectNum > 0) { + if (imageSize < config.minSelectNum) { + showPromptDialog(getString(R.string.picture_min_img_num, config.minSelectNum)); + return; + } + } + if (config.minVideoSelectNum > 0) { + if (videoSize < config.minVideoSelectNum) { + showPromptDialog(getString(R.string.picture_min_video_num, config.minVideoSelectNum)); + return; + } + } + } + } + else { + if (config.selectionMode == PictureConfig.MULTIPLE) { + if (PictureMimeType.isHasImage(mimeType) && config.minSelectNum > 0 && size < config.minSelectNum) { + String str = getString(R.string.picture_min_img_num, config.minSelectNum); + showPromptDialog(str); + return; + } + if (PictureMimeType.isHasVideo(mimeType) && config.minVideoSelectNum > 0 && size < config.minVideoSelectNum) { + String str = getString(R.string.picture_min_video_num, config.minVideoSelectNum); + showPromptDialog(str); + return; + } + } + } + + if (config.returnEmpty && size == 0) { + if (config.selectionMode == PictureConfig.MULTIPLE) { + if (config.minSelectNum > 0 && size < config.minSelectNum) { + String str = getString(R.string.picture_min_img_num, config.minSelectNum); + showPromptDialog(str); + return; + } + if (config.minVideoSelectNum > 0 && size < config.minVideoSelectNum) { + String str = getString(R.string.picture_min_video_num, config.minVideoSelectNum); + showPromptDialog(str); + return; + } + } + if (PictureSelectionConfig.listener != null) { + //noinspection unchecked + PictureSelectionConfig.listener.onResult(result); + } + else { + Intent intent = PictureSelector.putIntentResult(result); + setResult(RESULT_OK, intent); + } + exit(); + return; + } + if (config.isCheckOriginalImage) { + onResult(result); + return; + } + if (config.chooseMode == PictureMimeType.ofAll() && config.isWithVideoImage) { + bothMimeTypeWith(isHasImage, result); + } + else { + separateMimeTypeWith(isHasImage, result); + } + } + + /** + * They are different types of processing + * + * @param isHasImage has image + * @param images image list + */ + private void bothMimeTypeWith (boolean isHasImage, List images) { + LocalMedia image = images.size() > 0 ? images.get(0) : null; + if (image == null) { + return; + } + if (config.enableCrop) { + if (config.selectionMode == PictureConfig.SINGLE && isHasImage) { + config.originalPath = image.getPath(); + UCropManager.ofCrop(this, config.originalPath, image.getMimeType()); + } + else { + ArrayList cuts = new ArrayList<>(); + int count = images.size(); + int imageNum = 0; + for (int i = 0; i < count; i++) { + LocalMedia media = images.get(i); + if (media == null + || TextUtils.isEmpty(media.getPath())) { + continue; + } + if (PictureMimeType.isHasImage(media.getMimeType())) { + imageNum++; + } + CutInfo cutInfo = new CutInfo(); + cutInfo.setId(media.getId()); + cutInfo.setPath(media.getPath()); + cutInfo.setImageWidth(media.getWidth()); + cutInfo.setImageHeight(media.getHeight()); + cutInfo.setMimeType(media.getMimeType()); + cutInfo.setDuration(media.getDuration()); + cutInfo.setRealPath(media.getRealPath()); + cuts.add(cutInfo); + } + if (imageNum <= 0) { + onResult(images); + } + else { + UCropManager.ofCrop(this, cuts); + } + } + } + else if (config.isCompress) { + int size = images.size(); + int imageNum = 0; + for (int i = 0; i < size; i++) { + LocalMedia media = images.get(i); + if (PictureMimeType.isHasImage(media.getMimeType())) { + imageNum++; + break; + } + } + if (imageNum <= 0) { + onResult(images); + } + else { + compressImage(images); + } + } + else { + onResult(images); + } + } + + /** + * Same type of image or video processing logic + * + * @param isHasImage has image + * @param images image list + */ + private void separateMimeTypeWith (boolean isHasImage, List images) { + LocalMedia image = images.size() > 0 ? images.get(0) : null; + if (image == null) { + return; + } + if (config.enableCrop && isHasImage) { + if (config.selectionMode == PictureConfig.SINGLE) { + config.originalPath = image.getPath(); + UCropManager.ofCrop(this, config.originalPath, image.getMimeType()); + } + else { + ArrayList cuts = new ArrayList<>(); + int count = images.size(); + for (int i = 0; i < count; i++) { + LocalMedia media = images.get(i); + if (media == null + || TextUtils.isEmpty(media.getPath())) { + continue; + } + CutInfo cutInfo = new CutInfo(); + cutInfo.setId(media.getId()); + cutInfo.setPath(media.getPath()); + cutInfo.setImageWidth(media.getWidth()); + cutInfo.setImageHeight(media.getHeight()); + cutInfo.setMimeType(media.getMimeType()); + cutInfo.setDuration(media.getDuration()); + cutInfo.setRealPath(media.getRealPath()); + cuts.add(cutInfo); + } + UCropManager.ofCrop(this, cuts); + } + } + else if (config.isCompress + && isHasImage) { + compressImage(images); + } + else { + onResult(images); + } + } + + /** + * Play Audio + * + * @param path path + */ + private void AudioDialog (final String path) { + if (!isFinishing()) { + audioDialog = new PictureCustomDialog(getContext(), R.layout.picture_audio_dialog); + if (audioDialog.getWindow() != null) { + audioDialog.getWindow().setWindowAnimations(R.style.Picture_Theme_Dialog_AudioStyle); + } + mTvMusicStatus = audioDialog.findViewById(R.id.tv_musicStatus); + mTvMusicTime = audioDialog.findViewById(R.id.tv_musicTime); + musicSeekBar = audioDialog.findViewById(R.id.musicSeekBar); + mTvMusicTotal = audioDialog.findViewById(R.id.tv_musicTotal); + mTvPlayPause = audioDialog.findViewById(R.id.tv_PlayPause); + mTvStop = audioDialog.findViewById(R.id.tv_Stop); + mTvQuit = audioDialog.findViewById(R.id.tv_Quit); + if (mHandler != null) { + mHandler.postDelayed(() -> initPlayer(path), 30); + } + mTvPlayPause.setOnClickListener(new AudioOnClick(path)); + mTvStop.setOnClickListener(new AudioOnClick(path)); + mTvQuit.setOnClickListener(new AudioOnClick(path)); + musicSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + mediaPlayer.seekTo(progress); + } + } + + @Override + public void onStartTrackingTouch (SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch (SeekBar seekBar) { + } + }); + audioDialog.setOnDismissListener(dialog -> { + if (mHandler != null) { + mHandler.removeCallbacks(mRunnable); + } + new Handler().postDelayed(() -> stop(path), 30); + try { + if (audioDialog != null + && audioDialog.isShowing()) { + audioDialog.dismiss(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + }); + if (mHandler != null) { + mHandler.post(mRunnable); + } + audioDialog.show(); + } + } + + /** + * init Player + * + * @param path path + */ + private void initPlayer (String path) { + mediaPlayer = new MediaPlayer(); + try { + mediaPlayer.setDataSource(path); + mediaPlayer.prepare(); + mediaPlayer.setLooping(true); + playAudio(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Play Audio + */ + private void playAudio () { + if (mediaPlayer != null) { + musicSeekBar.setProgress(mediaPlayer.getCurrentPosition()); + musicSeekBar.setMax(mediaPlayer.getDuration()); + } + String ppStr = mTvPlayPause.getText().toString(); + if (ppStr.equals(getString(R.string.picture_play_audio))) { + mTvPlayPause.setText(getString(R.string.picture_pause_audio)); + mTvMusicStatus.setText(getString(R.string.picture_play_audio)); + } + else { + mTvPlayPause.setText(getString(R.string.picture_play_audio)); + mTvMusicStatus.setText(getString(R.string.picture_pause_audio)); + } + playOrPause(); + if (!isPlayAudio) { + if (mHandler != null) { + mHandler.post(mRunnable); + } + isPlayAudio = true; + } + } + + /** + * Audio Stop + * + * @param path path + */ + public void stop (String path) { + if (mediaPlayer != null) { + try { + mediaPlayer.stop(); + mediaPlayer.reset(); + mediaPlayer.setDataSource(path); + mediaPlayer.prepare(); + mediaPlayer.seekTo(0); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Audio Pause + */ + public void playOrPause () { + try { + if (mediaPlayer != null) { + if (mediaPlayer.isPlaying()) { + mediaPlayer.pause(); + } + else { + mediaPlayer.start(); + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onItemClick (int position, boolean isCameraFolder, long bucketId, String + folderName, List data) { + boolean camera = config.isCamera && isCameraFolder; + mAdapter.setShowCamera(camera); + mTvPictureTitle.setText(folderName); + long currentBucketId = ValueOf.toLong(mTvPictureTitle.getTag(R.id.view_tag)); + mTvPictureTitle.setTag(R.id.view_count_tag, folderWindow.getFolder(position) != null + ? folderWindow.getFolder(position).getImageNum() : 0); + if (config.isPageStrategy) { + if (currentBucketId != bucketId) { + setLastCacheFolderData(); + boolean isCurrentCacheFolderData = isCurrentCacheFolderData(position); + if (!isCurrentCacheFolderData) { + mPage = 1; + showPleaseDialog(); + LocalMediaPageLoader.getInstance(getContext()).loadPageMediaData(bucketId, mPage, + (result, currentPage, isHasMore) -> { + this.isHasMore = isHasMore; + if (!isFinishing()) { + if (result.size() == 0) { + mAdapter.clear(); + } + mAdapter.bindData(result); + mRecyclerView.onScrolled(0, 0); + mRecyclerView.smoothScrollToPosition(0); + dismissDialog(); + } + }); + } + } + } + else { + mAdapter.bindData(data); + mRecyclerView.smoothScrollToPosition(0); + } + mTvPictureTitle.setTag(R.id.view_tag, bucketId); + folderWindow.dismiss(); + } + + /** + * Before switching directories, set the current directory cache + */ + private void setLastCacheFolderData () { + int oldPosition = ValueOf.toInt(mTvPictureTitle.getTag(R.id.view_index_tag)); + LocalMediaFolder lastFolder = folderWindow.getFolder(oldPosition); + lastFolder.setData(mAdapter.getData()); + lastFolder.setCurrentDataPage(mPage); + lastFolder.setHasMore(isHasMore); + } + + /** + * Does the current album have a cache + * + * @param position position + */ + private boolean isCurrentCacheFolderData (int position) { + mTvPictureTitle.setTag(R.id.view_index_tag, position); + LocalMediaFolder currentFolder = folderWindow.getFolder(position); + if (currentFolder != null + && currentFolder.getData() != null + && currentFolder.getData().size() > 0) { + mAdapter.bindData(currentFolder.getData()); + mPage = currentFolder.getCurrentDataPage(); + isHasMore = currentFolder.isHasMore(); + mRecyclerView.smoothScrollToPosition(0); + + return true; + } + return false; + } + + @Override + public void onTakePhoto () { + // Check the permissions + if (PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA)) { + if (PermissionChecker + .checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && + PermissionChecker + .checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + startCamera(); + } + else { + PermissionChecker.requestPermissions(this, new String[]{ + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE}, PictureConfig.APPLY_CAMERA_STORAGE_PERMISSIONS_CODE); + } + } + else { + PermissionChecker + .requestPermissions(this, + new String[]{Manifest.permission.CAMERA}, PictureConfig.APPLY_CAMERA_PERMISSIONS_CODE); + } + } + + @Override + public void onChange (List selectData) { + changeImageNumber(selectData); + } + + @Override + public void onPictureClick (LocalMedia media, int position) { + if (config.selectionMode == PictureConfig.SINGLE && config.isSingleDirectReturn) { + List list = new ArrayList<>(); + list.add(media); + if (config.enableCrop && PictureMimeType.isHasImage(media.getMimeType()) && !config.isCheckOriginalImage) { + mAdapter.bindSelectData(list); + UCropManager.ofCrop(this, media.getPath(), media.getMimeType()); + } + else { + handlerResult(list); + } + } + else { + List data = mAdapter.getData(); + startPreview(data, position); + } + } + + /** + * preview image and video + * + * @param previewData preview data + * @param position position + */ + public void startPreview (List previewData, int position) { + LocalMedia media = previewData.get(position); + String mimeType = media.getMimeType(); + Bundle bundle = new Bundle(); + List result = new ArrayList<>(); + if (PictureMimeType.isHasVideo(mimeType)) { + // video + if (config.selectionMode == PictureConfig.SINGLE && !config.enPreviewVideo) { + result.add(media); + onResult(result); + } + else { + if (PictureSelectionConfig.customVideoPlayCallback != null) { + PictureSelectionConfig.customVideoPlayCallback.startPlayVideo(media); + } + else { + bundle.putParcelable(PictureConfig.EXTRA_MEDIA_KEY, media); + JumpUtils.startPictureVideoPlayActivity(getContext(), bundle, PictureConfig.PREVIEW_VIDEO_CODE); + } + } + } + else if (PictureMimeType.isHasAudio(mimeType)) { + // audio + if (config.selectionMode == PictureConfig.SINGLE) { + result.add(media); + onResult(result); + } + else { + AudioDialog(media.getRealPath()); + } + } + else { + // image + if (PictureSelectionConfig.onCustomImagePreviewCallback != null) { + PictureSelectionConfig.onCustomImagePreviewCallback.onCustomPreviewCallback(getContext(), previewData, position); + return; + } + List selectedData = mAdapter.getSelectedData(); + ImagesObservable.getInstance().savePreviewMediaData(new ArrayList<>(previewData)); + bundle.putParcelableArrayList(PictureConfig.EXTRA_SELECT_LIST, (ArrayList) selectedData); + bundle.putInt(PictureConfig.EXTRA_POSITION, position); + bundle.putBoolean(PictureConfig.EXTRA_CHANGE_ORIGINAL, config.isCheckOriginalImage); + bundle.putBoolean(PictureConfig.EXTRA_SHOW_CAMERA, mAdapter.isShowCamera()); + bundle.putLong(PictureConfig.EXTRA_BUCKET_ID, ValueOf.toLong(mTvPictureTitle.getTag(R.id.view_tag))); + bundle.putInt(PictureConfig.EXTRA_PAGE, mPage); + bundle.putParcelable(PictureConfig.EXTRA_CONFIG, config); + bundle.putInt(PictureConfig.EXTRA_DATA_COUNT, ValueOf.toInt(mTvPictureTitle.getTag(R.id.view_count_tag))); + bundle.putString(PictureConfig.EXTRA_IS_CURRENT_DIRECTORY, mTvPictureTitle.getText().toString()); + JumpUtils.startPicturePreviewActivity(getContext(), config.isWeChatStyle, bundle, + config.selectionMode == PictureConfig.SINGLE ? UCrop.REQUEST_CROP : UCrop.REQUEST_MULTI_CROP); + overridePendingTransition(PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation, R.anim.picture_anim_fade_in); + } + } + + /** + * change image selector state + * + * @param selectData + */ + protected void changeImageNumber (List selectData) { + initCompleteText(selectData.size()); + } + + @Override + protected void onActivityResult (int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + switch (requestCode) { + case PictureConfig.PREVIEW_VIDEO_CODE: + if (data != null) { + List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); + if (list != null && list.size() > 0) { + onResult(list); + } + } + break; + case UCrop.REQUEST_CROP: + singleCropHandleResult(data); + break; + case UCrop.REQUEST_MULTI_CROP: + multiCropHandleResult(data); + break; + case PictureConfig.REQUEST_CAMERA: + dispatchHandleCamera(data); + break; + default: + break; + } + } + else if (resultCode == RESULT_CANCELED) { + previewCallback(data); + } + else if (resultCode == UCrop.RESULT_ERROR) { + if (data != null) { + Throwable throwable = (Throwable) data.getSerializableExtra(UCrop.EXTRA_ERROR); + if (throwable != null) { + ToastUtils.s(getContext(), throwable.getMessage()); + } + } + } + } + + /** + * Preview interface callback processing + * + * @param data data + */ + private void previewCallback (Intent data) { + if (data == null) { + return; + } + List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); + if (mAdapter != null && list != null) { + boolean isCompleteOrSelected = data.getBooleanExtra(PictureConfig.EXTRA_COMPLETE_SELECTED, false); + if (isCompleteOrSelected) { + onChangeData(list); + if (config.isWithVideoImage) { + int size = list.size(); + int imageSize = 0; + for (int i = 0; i < size; i++) { + LocalMedia media = list.get(i); + if (PictureMimeType.isHasImage(media.getMimeType())) { + imageSize++; + break; + } + } + if (imageSize <= 0 || !config.isCompress || config.isCheckOriginalImage) { + onResult(list); + } + else { + compressImage(list); + } + } + else { + // Determine if the resource is of the same type + String mimeType = list.size() > 0 ? list.get(0).getMimeType() : ""; + if (config.isCompress && PictureMimeType.isHasImage(mimeType) + && !config.isCheckOriginalImage) { + compressImage(list); + } + else { + onResult(list); + } + } + } + else { + // Resources are selected on the preview page + isStartAnimation = true; + } + mAdapter.bindSelectData(list); + mAdapter.notifyDataSetChanged(); + } + } + + /** + * Preview the callback + * + * @param list list + */ + protected void onChangeData (List list) { + + } + + /** + * singleDirectReturn + * + * @param mimeType mimeType + */ + private void singleDirectReturnCameraHandleResult (String mimeType) { + boolean isHasImage = PictureMimeType.isHasImage(mimeType); + if (config.enableCrop && isHasImage) { + config.originalPath = config.cameraPath; + UCropManager.ofCrop(this, config.originalPath, mimeType); + } + else if (config.isCompress && isHasImage) { + List selectedImages = mAdapter.getSelectedData(); + compressImage(selectedImages); + } + else { + onResult(mAdapter.getSelectedData()); + } + } + + /** + * Camera Handle + * + * @param intent intent + */ + private void dispatchHandleCamera (Intent intent) { + // If PictureSelectionConfig is not empty, synchronize it + PictureSelectionConfig selectionConfig = intent != null ? intent.getParcelableExtra(PictureConfig.EXTRA_CONFIG) : null; + if (selectionConfig != null) { + config = selectionConfig; + } + //noinspection deprecation + boolean isAudio = config.chooseMode == PictureMimeType.ofAudio(); + config.cameraPath = isAudio ? getAudioPath(intent) : config.cameraPath; + if (TextUtils.isEmpty(config.cameraPath)) { + return; + } + showPleaseDialog(); + PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask() { + + @Override + public LocalMedia doInBackground () { + LocalMedia media = new LocalMedia(); + String mimeType = isAudio ? PictureMimeType.MIME_TYPE_AUDIO : ""; + long duration = 0; + if (!isAudio) { + if (PictureMimeType.isContent(config.cameraPath)) { + // content: Processing rules + String path = PictureFileUtils.getPath(getContext(), Uri.parse(config.cameraPath)); + if (path != null && !TextUtils.isEmpty(path)) { + File cameraFile = new File(path); + mimeType = PictureMimeType.getMimeType(config.cameraMimeType); + media.setSize(cameraFile.length()); + media.setFileName(cameraFile.getName()); + } + if (PictureMimeType.isHasImage(mimeType)) { + int[] newSize = MediaUtils.getImageSizeForUrlToAndroidQ(getContext(), config.cameraPath); + media.setWidth(newSize[0]); + media.setHeight(newSize[1]); + } + else if (PictureMimeType.isHasVideo(mimeType)) { + MediaUtils.getVideoSizeForUri(getContext(), Uri.parse(config.cameraPath), media); + duration = MediaUtils.extractDuration(getContext(), SdkVersionUtils.checkedAndroid_Q(), config.cameraPath); + } + int lastIndexOf = config.cameraPath.lastIndexOf("/") + 1; + media.setId(lastIndexOf > 0 ? ValueOf.toLong(config.cameraPath.substring(lastIndexOf)) : -1); + media.setRealPath(path); + // Custom photo has been in the application sandbox into the file + String mediaPath = intent != null ? intent.getStringExtra(PictureConfig.EXTRA_MEDIA_PATH) : null; + media.setAndroidQToPath(mediaPath); + } + else { + File cameraFile = new File(config.cameraPath); + mimeType = PictureMimeType.getMimeType(config.cameraMimeType); + media.setSize(cameraFile.length()); + media.setFileName(cameraFile.getName()); + if (PictureMimeType.isHasImage(mimeType)) { + int degree = PictureFileUtils.readPictureDegree(getContext(), config.cameraPath); + BitmapUtils.rotateImage(degree, config.cameraPath); + int[] newSize = MediaUtils.getImageSizeForUrl(config.cameraPath); + media.setWidth(newSize[0]); + media.setHeight(newSize[1]); + } + else if (PictureMimeType.isHasVideo(mimeType)) { + int[] newSize = MediaUtils.getVideoSizeForUrl(config.cameraPath); + duration = MediaUtils.extractDuration(getContext(), SdkVersionUtils.checkedAndroid_Q(), config.cameraPath); + media.setWidth(newSize[0]); + media.setHeight(newSize[1]); + } + // Taking a photo generates a temporary id + media.setId(System.currentTimeMillis()); + } + media.setPath(config.cameraPath); + media.setDuration(duration); + media.setMimeType(mimeType); + if (SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isHasVideo(media.getMimeType())) { + media.setParentFolderName(Environment.DIRECTORY_MOVIES); + } + else { + media.setParentFolderName(PictureMimeType.CAMERA); + } + media.setChooseModel(config.chooseMode); + long bucketId = MediaUtils.getCameraFirstBucketId(getContext()); + media.setBucketId(bucketId); + // The width and height of the image are reversed if there is rotation information + MediaUtils.setOrientationSynchronous(getContext(), media, config.isAndroidQChangeWH, config.isAndroidQChangeVideoWH); + } + return media; + } + + @Override + public void onSuccess (LocalMedia result) { + dismissDialog(); + // Refresh the system library + if (!SdkVersionUtils.checkedAndroid_Q()) { + if (config.isFallbackVersion3) { + new PictureMediaScannerConnection(getContext(), config.cameraPath); + } + else { + sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(config.cameraPath)))); + } + } + // add data Adapter + notifyAdapterData(result); + // Solve some phone using Camera, DCIM will produce repetitive problems + if (!SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isHasImage(result.getMimeType())) { + int lastImageId = MediaUtils.getDCIMLastImageId(getContext()); + if (lastImageId != -1) { + MediaUtils.removeMedia(getContext(), lastImageId); + } + } + } + }); + + } + + /** + * Update Adapter Data + * + * @param media media + */ + private void notifyAdapterData (LocalMedia media) { + if (mAdapter != null) { + boolean isAddSameImp = isAddSameImp(folderWindow.getFolder(0) != null ? folderWindow.getFolder(0).getImageNum() : 0); + if (!isAddSameImp) { + mAdapter.getData().add(0, media); + mOpenCameraCount++; + } + if (checkVideoLegitimacy(media)) { + if (config.selectionMode == PictureConfig.SINGLE) { + dispatchHandleSingle(media); + } + else { + dispatchHandleMultiple(media); + } + } + mAdapter.notifyItemInserted(config.isCamera ? 1 : 0); + mAdapter.notifyItemRangeChanged(config.isCamera ? 1 : 0, mAdapter.getSize()); + // Solve the problem that some mobile phones do not refresh the system library timely after using Camera + if (config.isPageStrategy) { + manualSaveFolderForPageModel(media); + } + else { + manualSaveFolder(media); + } + mTvEmpty.setVisibility(mAdapter.getSize() > 0 || config.isSingleDirectReturn ? View.GONE : View.VISIBLE); + // update all count + if (folderWindow.getFolder(0) != null) { + mTvPictureTitle.setTag(R.id.view_count_tag, folderWindow.getFolder(0).getImageNum()); + } + allFolderSize = 0; + } + } + + /** + * After using Camera, MultiSelect mode handles the logic + * + * @param media media + */ + private void dispatchHandleMultiple (LocalMedia media) { + List selectedData = mAdapter.getSelectedData(); + int count = selectedData.size(); + String oldMimeType = count > 0 ? selectedData.get(0).getMimeType() : ""; + boolean mimeTypeSame = PictureMimeType.isMimeTypeSame(oldMimeType, media.getMimeType()); + if (config.isWithVideoImage) { + int videoSize = 0; + for (int i = 0; i < count; i++) { + LocalMedia item = selectedData.get(i); + if (PictureMimeType.isHasVideo(item.getMimeType())) { + videoSize++; + } + } + if (PictureMimeType.isHasVideo(media.getMimeType())) { + if (config.maxVideoSelectNum <= 0) { + showPromptDialog(getString(R.string.picture_rule)); + } + else { + if (videoSize >= config.maxVideoSelectNum) { + showPromptDialog(getString(R.string.picture_message_max_num, config.maxVideoSelectNum)); + } + else { + selectedData.add(0, media); + mAdapter.bindSelectData(selectedData); + } + } + } + else { + if (selectedData.size() < config.maxSelectNum) { + selectedData.add(0, media); + mAdapter.bindSelectData(selectedData); + } + else { + showPromptDialog(StringUtils.getMsg(getContext(), media.getMimeType(), config.maxSelectNum)); + } + } + + } + else { + if (PictureMimeType.isHasVideo(oldMimeType) && config.maxVideoSelectNum > 0) { + if (count < config.maxVideoSelectNum) { + if (mimeTypeSame || count == 0) { + if (selectedData.size() < config.maxVideoSelectNum) { + selectedData.add(0, media); + mAdapter.bindSelectData(selectedData); + } + } + } + else { + showPromptDialog(StringUtils.getMsg(getContext(), oldMimeType, + config.maxVideoSelectNum)); + } + } + else { + if (count < config.maxSelectNum) { + if (mimeTypeSame || count == 0) { + selectedData.add(0, media); + mAdapter.bindSelectData(selectedData); + } + } + else { + showPromptDialog(StringUtils.getMsg(getContext(), oldMimeType, config.maxSelectNum)); + } + } + } + } + + /** + * After using the camera, the radio mode handles the logic + * + * @param media media + */ + private void dispatchHandleSingle (LocalMedia media) { + if (config.isSingleDirectReturn) { + List selectedData = mAdapter.getSelectedData(); + selectedData.add(media); + mAdapter.bindSelectData(selectedData); + singleDirectReturnCameraHandleResult(media.getMimeType()); + } + else { + List selectedData = mAdapter.getSelectedData(); + String mimeType = selectedData.size() > 0 ? selectedData.get(0).getMimeType() : ""; + boolean mimeTypeSame = PictureMimeType.isMimeTypeSame(mimeType, media.getMimeType()); + if (mimeTypeSame || selectedData.size() == 0) { + singleRadioMediaImage(); + selectedData.add(media); + mAdapter.bindSelectData(selectedData); + } + } + } + + /** + * Verify the validity of the video + * + * @param media media + * @return check video + */ + private boolean checkVideoLegitimacy (LocalMedia media) { + boolean isEnterNext = true; + if (PictureMimeType.isHasVideo(media.getMimeType())) { + if (config.videoMinSecond > 0 && config.videoMaxSecond > 0) { + // The user sets the minimum and maximum video length to determine whether the video is within the interval + if (media.getDuration() < config.videoMinSecond || media.getDuration() > config.videoMaxSecond) { + isEnterNext = false; + showPromptDialog(getString(R.string.picture_choose_limit_seconds, config.videoMinSecond / 1000, config.videoMaxSecond / 1000)); + } + } + else if (config.videoMinSecond > 0) { + // The user has only set a minimum video length limit + if (media.getDuration() < config.videoMinSecond) { + isEnterNext = false; + showPromptDialog(getString(R.string.picture_choose_min_seconds, config.videoMinSecond / 1000)); + } + } + else if (config.videoMaxSecond > 0) { + // Only the maximum length of video is set + if (media.getDuration() > config.videoMaxSecond) { + isEnterNext = false; + showPromptDialog(getString(R.string.picture_choose_max_seconds, config.videoMaxSecond / 1000)); + } + } + } + return isEnterNext; + } + + /** + * Single picture clipping callback + * + * @param data data + */ + private void singleCropHandleResult (Intent data) { + if (data == null) { + return; + } + Uri resultUri = UCrop.getOutput(data); + if (resultUri == null) { + return; + } + List result = new ArrayList<>(); + String cutPath = resultUri.getPath(); + if (mAdapter != null) { + List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); + if (list != null) { + mAdapter.bindSelectData(list); + mAdapter.notifyDataSetChanged(); + } + List mediaList = mAdapter.getSelectedData(); + LocalMedia media = mediaList != null && mediaList.size() > 0 ? mediaList.get(0) : null; + if (media != null) { + config.originalPath = media.getPath(); + media.setCutPath(cutPath); + media.setChooseModel(config.chooseMode); + boolean isCutPathEmpty = !TextUtils.isEmpty(cutPath); + if (SdkVersionUtils.checkedAndroid_Q() + && PictureMimeType.isContent(media.getPath())) { + if (isCutPathEmpty) { + media.setSize(new File(cutPath).length()); + } + else { + media.setSize(!TextUtils.isEmpty(media.getRealPath()) ? new File(media.getRealPath()).length() : 0); + } + media.setAndroidQToPath(cutPath); + } + else { + media.setSize(isCutPathEmpty ? new File(cutPath).length() : 0); + } + media.setCut(isCutPathEmpty); + result.add(media); + handlerResult(result); + } + else { + // Preview screen selects the image and crop the callback + media = list != null && list.size() > 0 ? list.get(0) : null; + if (media != null) { + config.originalPath = media.getPath(); + media.setCutPath(cutPath); + media.setChooseModel(config.chooseMode); + boolean isCutPathEmpty = !TextUtils.isEmpty(cutPath); + if (SdkVersionUtils.checkedAndroid_Q() + && PictureMimeType.isContent(media.getPath())) { + if (isCutPathEmpty) { + media.setSize(new File(cutPath).length()); + } + else { + media.setSize(!TextUtils.isEmpty(media.getRealPath()) ? new File(media.getRealPath()).length() : 0); + } + media.setAndroidQToPath(cutPath); + } + else { + media.setSize(isCutPathEmpty ? new File(cutPath).length() : 0); + } + media.setCut(isCutPathEmpty); + result.add(media); + handlerResult(result); + } + } + } + } + + /** + * Multiple picture crop + * + * @param data data + */ + protected void multiCropHandleResult (Intent data) { + if (data == null) { + return; + } + List mCuts = UCrop.getMultipleOutput(data); + if (mCuts == null || mCuts.size() == 0) { + return; + } + int size = mCuts.size(); + boolean isAndroidQ = SdkVersionUtils.checkedAndroid_Q(); + List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); + if (list != null) { + mAdapter.bindSelectData(list); + mAdapter.notifyDataSetChanged(); + } + int oldSize = mAdapter != null ? mAdapter.getSelectedData().size() : 0; + if (oldSize == size) { + List result = mAdapter.getSelectedData(); + for (int i = 0; i < size; i++) { + CutInfo c = mCuts.get(i); + LocalMedia media = result.get(i); + media.setCut(!TextUtils.isEmpty(c.getCutPath())); + media.setPath(c.getPath()); + media.setMimeType(c.getMimeType()); + media.setCutPath(c.getCutPath()); + media.setWidth(c.getImageWidth()); + media.setHeight(c.getImageHeight()); + media.setAndroidQToPath(isAndroidQ ? c.getCutPath() : media.getAndroidQToPath()); + media.setSize(!TextUtils.isEmpty(c.getCutPath()) ? new File(c.getCutPath()).length() : media.getSize()); + } + handlerResult(result); + } + else { + // Fault-tolerant processing + List result = new ArrayList<>(); + for (int i = 0; i < size; i++) { + CutInfo c = mCuts.get(i); + LocalMedia media = new LocalMedia(); + media.setId(c.getId()); + media.setCut(!TextUtils.isEmpty(c.getCutPath())); + media.setPath(c.getPath()); + media.setCutPath(c.getCutPath()); + media.setMimeType(c.getMimeType()); + media.setWidth(c.getImageWidth()); + media.setHeight(c.getImageHeight()); + media.setDuration(c.getDuration()); + media.setChooseModel(config.chooseMode); + media.setAndroidQToPath(isAndroidQ ? c.getCutPath() : c.getAndroidQToPath()); + if (!TextUtils.isEmpty(c.getCutPath())) { + media.setSize(new File(c.getCutPath()).length()); + } + else { + if (SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isContent(c.getPath())) { + media.setSize(!TextUtils.isEmpty(c.getRealPath()) ? new File(c.getRealPath()).length() : 0); + } + else { + media.setSize(new File(c.getPath()).length()); + } + } + result.add(media); + } + handlerResult(result); + } + } + + /** + * Just make sure you pick one + */ + private void singleRadioMediaImage () { + List selectData = mAdapter.getSelectedData(); + if (selectData != null + && selectData.size() > 0) { + LocalMedia media = selectData.get(0); + int position = media.getPosition(); + selectData.clear(); + mAdapter.notifyItemChanged(position); + } + } + + /** + * Manually add the photo to the list of photos and set it to select-paging mode + * + * @param media media + */ + private void manualSaveFolderForPageModel (LocalMedia media) { + if (media == null) { + return; + } + int count = folderWindow.getFolderData().size(); + LocalMediaFolder allFolder = count > 0 ? folderWindow.getFolderData().get(0) : new LocalMediaFolder(); + if (allFolder != null) { + int totalNum = allFolder.getImageNum(); + allFolder.setFirstImagePath(media.getPath()); + allFolder.setImageNum(isAddSameImp(totalNum) ? allFolder.getImageNum() : allFolder.getImageNum() + 1); + // Create All folder + if (count == 0) { + //noinspection deprecation + allFolder.setName(config.chooseMode == PictureMimeType.ofAudio() ? getString(R.string.picture_all_audio) : getString(R.string.picture_camera_roll)); + allFolder.setOfAllType(config.chooseMode); + allFolder.setCameraFolder(true); + allFolder.setChecked(true); + allFolder.setBucketId(-1); + folderWindow.getFolderData().add(0, allFolder); + // Create Camera + LocalMediaFolder cameraFolder = new LocalMediaFolder(); + cameraFolder.setName(media.getParentFolderName()); + cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); + cameraFolder.setFirstImagePath(media.getPath()); + cameraFolder.setBucketId(media.getBucketId()); + folderWindow.getFolderData().add(folderWindow.getFolderData().size(), cameraFolder); + } + else { + boolean isCamera = false; + String newFolder = SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isHasVideo(media.getMimeType()) + ? Environment.DIRECTORY_MOVIES : PictureMimeType.CAMERA; + for (int i = 0; i < count; i++) { + LocalMediaFolder cameraFolder = folderWindow.getFolderData().get(i); + if (!TextUtils.isEmpty(cameraFolder.getName()) && cameraFolder.getName().startsWith(newFolder)) { + media.setBucketId(cameraFolder.getBucketId()); + cameraFolder.setFirstImagePath(config.cameraPath); + cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); + if (cameraFolder.getData() != null && cameraFolder.getData().size() > 0) { + cameraFolder.getData().add(0, media); + } + isCamera = true; + break; + } + } + if (!isCamera) { + // There is no Camera folder locally. Create one + LocalMediaFolder cameraFolder = new LocalMediaFolder(); + cameraFolder.setName(media.getParentFolderName()); + cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); + cameraFolder.setFirstImagePath(media.getPath()); + cameraFolder.setBucketId(media.getBucketId()); + folderWindow.getFolderData().add(cameraFolder); + sortFolder(folderWindow.getFolderData()); + } + } + folderWindow.bindFolder(folderWindow.getFolderData()); + } + } + + /** + * Manually add the photo to the list of photos and set it to select + * + * @param media media + */ + private void manualSaveFolder (LocalMedia media) { + try { + boolean isEmpty = folderWindow.isEmpty(); + int totalNum = folderWindow.getFolder(0) != null ? folderWindow.getFolder(0).getImageNum() : 0; + LocalMediaFolder allFolder; + if (isEmpty) { + // All Folder + createNewFolder(folderWindow.getFolderData()); + allFolder = folderWindow.getFolderData().size() > 0 ? folderWindow.getFolderData().get(0) : null; + if (allFolder == null) { + allFolder = new LocalMediaFolder(); + folderWindow.getFolderData().add(0, allFolder); + } + } + else { + // All Folder + allFolder = folderWindow.getFolderData().get(0); + } + allFolder.setFirstImagePath(media.getPath()); + allFolder.setData(mAdapter.getData()); + allFolder.setBucketId(-1); + allFolder.setImageNum(isAddSameImp(totalNum) ? allFolder.getImageNum() : allFolder.getImageNum() + 1); + + // Camera + LocalMediaFolder cameraFolder = getImageFolder(media.getPath(), media.getRealPath(), folderWindow.getFolderData()); + if (cameraFolder != null) { + cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); + if (!isAddSameImp(totalNum)) { + cameraFolder.getData().add(0, media); + } + cameraFolder.setBucketId(media.getBucketId()); + cameraFolder.setFirstImagePath(config.cameraPath); + } + folderWindow.bindFolder(folderWindow.getFolderData()); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Is the quantity consistent + * + * @return is add same + */ + private boolean isAddSameImp (int totalNum) { + if (totalNum == 0) { + return false; + } + return allFolderSize > 0 && allFolderSize < totalNum; + } + + /** + * Update Folder + * + * @param imageFolders image folder list + */ + private void updateMediaFolder (List imageFolders, LocalMedia media) { + File imageFile = new File(media.getRealPath()); + File folderFile = imageFile.getParentFile(); + if (folderFile == null) { + return; + } + int size = imageFolders.size(); + for (int i = 0; i < size; i++) { + LocalMediaFolder folder = imageFolders.get(i); + String name = folder.getName(); + if (TextUtils.isEmpty(name)) { + continue; + } + if (name.equals(folderFile.getName())) { + folder.setFirstImagePath(config.cameraPath); + folder.setImageNum(folder.getImageNum() + 1); + folder.setCheckedNum(1); + folder.getData().add(0, media); + break; + } + } + } + + @Override + public void onBackPressed () { + if (SdkVersionUtils.checkedAndroid_Q()) { + finishAfterTransition(); + } + else { + super.onBackPressed(); + } + if (PictureSelectionConfig.listener != null) { + PictureSelectionConfig.listener.onCancel(); + } + exit(); + } + + @Override + protected void onDestroy () { + super.onDestroy(); + if (animation != null) { + animation.cancel(); + animation = null; + } + if (mediaPlayer != null && mHandler != null) { + mHandler.removeCallbacks(mRunnable); + mediaPlayer.release(); + mediaPlayer = null; + } + } + + @Override + public void onItemClick (View view, int position) { + switch (position) { + case PhotoItemSelectedDialog.IMAGE_CAMERA: + if (PictureSelectionConfig.onCustomCameraInterfaceListener != null) { + PictureSelectionConfig.onCustomCameraInterfaceListener.onCameraClick(getContext(), config, PictureConfig.TYPE_IMAGE); + config.cameraMimeType = PictureMimeType.ofImage(); + } + else { + startOpenCamera(); + } + break; + case PhotoItemSelectedDialog.VIDEO_CAMERA: + if (PictureSelectionConfig.onCustomCameraInterfaceListener != null) { + PictureSelectionConfig.onCustomCameraInterfaceListener.onCameraClick(getContext(), config, PictureConfig.TYPE_IMAGE); + config.cameraMimeType = PictureMimeType.ofVideo(); + } + else { + startOpenCameraVideo(); + } + break; + default: + break; + } + } + + @Override + public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + switch (requestCode) { + case PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE: + // Store Permissions + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + readLocalMedia(); + } + else { + showPermissionsDialog(false, getString(R.string.picture_jurisdiction)); + } + break; + case PictureConfig.APPLY_CAMERA_PERMISSIONS_CODE: + // Camera Permissions + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + onTakePhoto(); + } + else { + showPermissionsDialog(true, getString(R.string.picture_camera)); + } + break; + case PictureConfig.APPLY_CAMERA_STORAGE_PERMISSIONS_CODE: + // Using the camera, retrieve the storage permission + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + startCamera(); + } + else { + showPermissionsDialog(false, getString(R.string.picture_jurisdiction)); + } + break; + case PictureConfig.APPLY_RECORD_AUDIO_PERMISSIONS_CODE: + // Recording Permissions + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + startCustomCamera(); + } + else { + showPermissionsDialog(false, getString(R.string.picture_audio)); + } + break; + } + } + + @Override + protected void showPermissionsDialog (boolean isCamera, String errorMsg) { + if (isFinishing()) { + return; + } + final PictureCustomDialog dialog = + new PictureCustomDialog(getContext(), R.layout.picture_wind_base_dialog); + dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + Button btn_cancel = dialog.findViewById(R.id.btn_cancel); + Button btn_commit = dialog.findViewById(R.id.btn_commit); + btn_commit.setText(getString(R.string.picture_go_setting)); + TextView tvTitle = dialog.findViewById(R.id.tvTitle); + TextView tv_content = dialog.findViewById(R.id.tv_content); + tvTitle.setText(getString(R.string.picture_prompt)); + tv_content.setText(errorMsg); + btn_cancel.setOnClickListener(v -> { + if (!isFinishing()) { + dialog.dismiss(); + } + if (!isCamera) { + if (PictureSelectionConfig.listener != null) { + PictureSelectionConfig.listener.onCancel(); + } + exit(); + } + }); + btn_commit.setOnClickListener(v -> { + if (!isFinishing()) { + dialog.dismiss(); + } + PermissionChecker.launchAppDetailsSettings(getContext()); + isEnterSetting = true; + }); + dialog.show(); + } + + /** + * set Data Null + * + * @param msg msg + */ + private void showDataNull (String msg, int topErrorResId) { + if (mTvEmpty.getVisibility() == View.GONE || mTvEmpty.getVisibility() == View.INVISIBLE) { + mTvEmpty.setCompoundDrawablesRelativeWithIntrinsicBounds(0, topErrorResId, 0, 0); + mTvEmpty.setText(msg); + mTvEmpty.setVisibility(View.VISIBLE); + } + } + + /** + * hidden + */ + private void hideDataNull () { + if (mTvEmpty.getVisibility() == View.VISIBLE) { + mTvEmpty.setVisibility(View.GONE); + } + } + + /** + * Audio Click + */ + public class AudioOnClick implements View.OnClickListener { + public AudioOnClick (String path) { + super(); + this.path = path; + } + + @Override + public void onClick (View v) { + int id = v.getId(); + if (id == R.id.tv_PlayPause) { + playAudio(); + } + if (id == R.id.tv_Stop) { + mTvMusicStatus.setText(getString(R.string.picture_stop_audio)); + mTvPlayPause.setText(getString(R.string.picture_play_audio)); + stop(path); + } + if (id == R.id.tv_Quit) { + if (mHandler != null) { + mHandler.postDelayed(() -> stop(path), 30); + try { + if (audioDialog != null + && audioDialog.isShowing()) { + audioDialog.dismiss(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + mHandler.removeCallbacks(mRunnable); + } + } + } + + private final String path; + } +} diff --git a/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java b/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java index b72f9fb3b..2f23d6c6a 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java +++ b/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java @@ -13,6 +13,7 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; @@ -20,7 +21,6 @@ import com.luck.picture.lib.config.PictureConfig; import com.luck.picture.lib.config.PictureMimeType; import com.luck.picture.lib.config.PictureSelectionConfig; -import com.luck.picture.lib.dialog.PictureCustomDialog; import com.luck.picture.lib.entity.LocalMedia; import com.luck.picture.lib.listener.OnPhotoSelectChangedListener; import com.luck.picture.lib.tools.AnimUtils; @@ -753,12 +753,12 @@ public void selectImage(ViewHolder holder, boolean isChecked) { * Tips */ private void showPromptDialog(String content) { - PictureCustomDialog dialog = new PictureCustomDialog(context, R.layout.picture_prompt_dialog); - TextView btnOk = dialog.findViewById(R.id.btnOk); - TextView tvContent = dialog.findViewById(R.id.tv_content); - tvContent.setText(content); - btnOk.setOnClickListener(v -> dialog.dismiss()); - dialog.show(); + + new AlertDialog.Builder(context) + .setMessage(content) + .setPositiveButton(R.string.picture_know, (dialog, which) -> { + }) + .show(); } diff --git a/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java b/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java index fd27d43a9..29a496bd2 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java +++ b/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java @@ -73,6 +73,7 @@ public final class PictureSelectionConfig implements Parcelable { public boolean isMultipleRecyclerAnimation; public boolean isMultipleSkipCrop; public boolean isWeChatStyle; + public boolean isDoctalkStyle; public boolean isUseCustomCamera; public boolean zoomAnim; public boolean isCompress; diff --git a/picture_library/src/main/res/layout/picture_album_folder_item.xml b/picture_library/src/main/res/layout/picture_album_folder_item.xml index ed9017356..c745af428 100644 --- a/picture_library/src/main/res/layout/picture_album_folder_item.xml +++ b/picture_library/src/main/res/layout/picture_album_folder_item.xml @@ -23,15 +23,15 @@ android:visibility="invisible" /> + android:id="@+id/tv_folder_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="10dp" + android:layout_centerVertical="true" + android:layout_toRightOf="@id/first_image" + android:text="@string/picture_camera_roll_num" + android:textColor="@color/picture_color_4d" + android:textSize="16sp" /> \ No newline at end of file diff --git a/picture_library/src/main/res/layout/picture_doctalk.xml b/picture_library/src/main/res/layout/picture_doctalk.xml new file mode 100644 index 000000000..8c0165dcb --- /dev/null +++ b/picture_library/src/main/res/layout/picture_doctalk.xml @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/picture_library/src/main/res/layout/picture_title_bar.xml b/picture_library/src/main/res/layout/picture_title_bar.xml index 652767eee..96437c608 100644 --- a/picture_library/src/main/res/layout/picture_title_bar.xml +++ b/picture_library/src/main/res/layout/picture_title_bar.xml @@ -2,7 +2,7 @@ - Kamerafilm - %1$s (%2$d) - Abbrechen - Schießen - Es kann nicht gleichzeitig ein Bild oder Video ausgewählt werden - Sie können bis zu %1$s Bilder auswählen - Die minimale Videoauswahl darf %1$s nicht unterschreiten - Sie können bis zu %1$s Videos auswählen - Sie können bis zu %1$s Audio auswählen - Vorschau - Bitte warten… - %1$d/%2$d Vervollständigen - Abgeschlossen - Vollständig - Bitte wählen Sie - Keine Videos oder Fotos\n - Keine Audiodatei\n - Sie können mit Ihrer Kamera ein Foto oder Video aufnehmen - Sie können Audio mit der Systemaufzeichnung aufnehmen - Die Mindestauswahl an Bildern darf %1$s nicht unterschreiten - Bewegen - Leseberechtigungen für Speicherkarten verweigert - Systemkameraberechtigung verweigert - Holen Sie sich die Systemaufzeichnungsberechtigung verweigert - Das Video kann nicht in der Vorschau angezeigt werden - Video aufnehmen - Kamera - Langes Bild - Keine Mediendateien! - Aufforderung - Gibt an, ob das Bild auf dem Telefon gespeichert werden soll? - Bildspeicherung fehlgeschlagen - Bild erfolgreich gespeichert - Alles Audio - Aufnahme - Spielen - Halt an - Ausfahrt - Anhalten - Bild ist beschädigt - Das Video ist beschädigt - Audio ist fehlerhaft - Gut - %1$d/%2$d - Keine Erntedaten verfügbar - Original - Vollständig - Vollständig(%1$d/%2$d) - Siehe(%1$d) - Auswahl - Ausnahme von Album-Daten… - Die Aufnahmezeit ist zu kurz - Machen Sie ein Foto - Nur Videos innerhalb von %1$ds können ausgewählt werden - Video nicht weniger als %1$ds auswählen - Nur Videos innerhalb von %1$ds bis %2$ds können ausgewählt werden - - Fotografie - Lange Presse Videoband - Set up - Das stimmt - Hier ist es leer… - diff --git a/picture_library/src/main/res/values-en/strings.xml b/picture_library/src/main/res/values-en/strings.xml deleted file mode 100644 index 0a4d0d2ed..000000000 --- a/picture_library/src/main/res/values-en/strings.xml +++ /dev/null @@ -1,64 +0,0 @@ - - CameraRoll - %1$s (%2$d) - Cancel - Shot - not pictures or video - Video Selection Cannot%1$sNumber - Select up to %1$s images - Select up to %1$s Audio - Select up to %1$s Video - Preview - Please later… - %1$d/%2$d Ok - Completed - Complete - Please Select - No video or photos\n - No audio file\n - You can use system recordings to record audio - you can use your camera to take photos or videos - Picture Selection Cannot%1$sNumber - gif - Access to system recording permission denied - Read memory card access denied - Get system camera permission denied - Video not Preview - Record Video - Photograph - Long - No Media files! - Prompt - Do you want to save pictures to your phone? - Picture save failed - Save picture successfully until - All audio - Tape - Play - Stop - Quit - Pause - The picture is corrupted - The video is corrupted - The audio is corrupted - Confirm - %1$d/%2$d - No cropped data - Original - Complete - Complete(%1$d/%2$d) - Preview(%1$d) - Choose - Get album data exception… - recording time is too short - Photograph, photograph - You can only select videos within %1$ds - You cannot select a video less than %1$ds - Only videos from %1$ds to %2$ds can be selected - - Take Picture - Long Press Camera - Go Setting - I know the - There no data here… - diff --git a/picture_library/src/main/res/values-es-rES/string.xml b/picture_library/src/main/res/values-es-rES/string.xml deleted file mode 100644 index a9ec621f1..000000000 --- a/picture_library/src/main/res/values-es-rES/string.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - Todos los audios - Permiso de acceso al sistema de grabación denegado - Puedes utilizar el sistema de grabación para grabar audios - Audio corrupto - Permiso de acceso a la cámara denegado - Galería - %1$s (%2$d) - Cancelar - Únicamente pueden seleccionarse videos entre %1$ds y %2$ds - Puedes seleccionar videos de no más de %1$ds - No puedes seleccionar videos de menos de %1$ds - Completado - Confirmar - Error al obtener datos de galería… - No hay nada aquí… - Completar - %1$d/%2$d Ok - Puedes utilizar tu cámara para tomar fotos o videos - No hay audios\n - No hay fotos o videos\n - Foto corrupta - gif - Configuración - Acceso a la tarjeta de memoria denegado - Entendido - Imagen larga - Seleccciona hasta %1$s audios - Selecciona hasta %1$s fotos - Selecciona %1$s videos - Las imágenes seleccionadas no deben ser menos de %1$s - Los videos seleccionados no deben ser menos de %1$s - No hay datos - Original - Pausar - Foto con clic, foto con clic extendido - Tomar foto con clic - Tomar foto con clic extendido - Tomar foto - Reproducir - Espera un momento… - Seleccionar - Vista previa - %1$d/%2$d - Vista previa(%1$d) - Aviso - ¿Guardar las imágenes en tu teléfono? - Salir - Grabar video - Tiempo de grabación demasiado breve - No pueden seleccionarse fotos y videos simultáneamente - Guardado fallido - Foto guardada exitosamente en - Seleccionar - Completar - Completar(%1$d/%2$d) - Detener - Capturar - Grabar - Video corrupto - No hay vista previa del video - No hay ningún archivo - \ No newline at end of file diff --git a/picture_library/src/main/res/values-fr-rFR/strings.xml b/picture_library/src/main/res/values-fr-rFR/strings.xml deleted file mode 100644 index a087263bb..000000000 --- a/picture_library/src/main/res/values-fr-rFR/strings.xml +++ /dev/null @@ -1,64 +0,0 @@ - - l’album - %1$s (%2$d) - l’abandon - photo - Il n’est pas possible de sélectionner des images ou des vidéos en même temps - Vous pouvez choisir, au maximum, une image en %1$s - La sélection minimale des vidéos ne peut être inférieure à %1$s - Vous pouvez choisir au maximum %1$s de vidéos - Vous pouvez choisir au maximum %1$s audio - avant-première - attendez… - %1$d/%2$d L’achèvement - achevés - L’achèvement du - Le choix - Pas de vidéos ou de photos\n - Pas de fichier audio\n - Vous pouvez utiliser votre caméra pour prendre des photos ou des vidéos - Vous pouvez utiliser le système d’enregistrement pour enregistrer l’audio - La sélection minimale des images ne doit pas être inférieure à %1$s - Bouge fig - L’autorisation de lire la carte de mémoire a été refusée - L’accès à la caméra du système a été refusé - L’accès au système d’enregistrement est refusé - Vidéo non disponible - Enregistrement vidéo - photo - Figure longue - Pas de documents pour les médias! - rappel - Conserver ou non une image sur un téléphone portable? - Défaut de conservation des images - Image conservée avec succès - Tous audio - Les transcriptions in extenso - diffusion - cessation - Le retrait - La suspension - Image endommagée - Vidéo endommagée - Audio endommagé - déterminer - %1$d/%2$d - Pas de données recadrées - - Original - Finir - Finir(%1$d/%2$d) - voir(%1$d) - Le choix - Anomalie des données de l’album… - La durée d’enregistrement est trop courte - Prendre des photos, filmer - Vous pouvez sélectionner la vidéo dans un maximum de %1$ds - Impossible de sélectionner une vidéo en dessous de %1$ds - Vous ne pouvez sélectionner que les vidéos dans les %1$ds à %2$ds - - Clic photo - Imagerie - Je sais - Pas de données… - diff --git a/picture_library/src/main/res/values-ja-rJP/strings.xml b/picture_library/src/main/res/values-ja-rJP/strings.xml deleted file mode 100644 index 906aa2913..000000000 --- a/picture_library/src/main/res/values-ja-rJP/strings.xml +++ /dev/null @@ -1,63 +0,0 @@ - - カメラ - %1$s (%2$d) - キャンセル - カメラ - 画像や動画を同時に選択することはできない - 最大で %1$s 枚の画像を選択することができます - ビデオの最低選択数は %1$s 個までである - 最大で %1$s のビデオを選択できます - 最大で %1$s の音声を選択することができます - プレビュー - ちょっと待ってください… - %1$d/%2$d 選べた - 選べた - 選べた - 選んでください - ビデオや写真はない\n - オーディオなし\n - カメラを使って写真やビデオを撮ることができます - システムを使って音声を録音することができます - 画像の最低値は %1$s 枚までとする - 动図 - メモリーカードの読み取り権限が拒否された - システムカメラの取得権限は拒否される - システムの録音権の取得は拒否される - ビデオプレビュー不可 - 録画ビデオ - 撮影 - 長い図 - メディアファイル! - 提示 - 画像を携帯電話に保存します? - 画像の保存に失敗 - 写真保存に成功まで - 全てのオーディオ - 録音 - 放送 - 停止 - 退出 - 暂停 - 画像が破損した - 映像が壊れた - オーディオが破損した - 確定 - %1$d/%2$d - トリミングされたデータはありません - 原図 - を選択します - を選択します(%1$d/%2$d) - プレビュー(%1$d) - 選択 - アルバムデータ取得異常... - 収録時間が短すぎる - 写真を撮る - 最大 %1$ds 以内のビデオしか選択できません - %1$ds 以下のビデオは選択できません - %1$ds sから %2$ds までのビデオしか選択できません - 写真を撮る - 長押しする - 設定 - はい - データがありません… - diff --git a/picture_library/src/main/res/values-ko-rKR/strings.xml b/picture_library/src/main/res/values-ko-rKR/strings.xml deleted file mode 100644 index d1f4fee68..000000000 --- a/picture_library/src/main/res/values-ko-rKR/strings.xml +++ /dev/null @@ -1,63 +0,0 @@ - - 카메라 필름 - %1$s (%2$d) - 취소 - 촬영 - 사진이나 비디오를 동시에 선택할 수 없습니다. - 최대 %1$s 달러 자 그림 선택 - 최소한 비디오 선택은 %1$s 달러 자 이상이어야 합니다. - 최대 %1$s 달러 개의 동영상을 선택할 수 있습니다. - 최대 %1$s 달러 개의 오디오를 선택할 수 있습니다. - 미리 보기 - 잠시만 기다려 주십시오.... - %1$d/%2$d 완료 - 완료됨 - 완료 - 선택하십시오 - 비디오나 사진 없음\n - 오디오 파일 없음\n - 사진을 찍거나 동영상을 찍을 수 있습니다 - 시스템으로 오디오 녹음 작업을 할 수 있습니다 - 그림 선택 최소 %1$s 달러 장 이상 - 움직이 지도 - 메모리 카드 읽기 권한이 거부됨 - 시스템 카메라 가져오기 권한이 거부됨 - 시스템 녹음 권한 가져오기 거부됨 - 미리 볼 수 없는 동영상 - 비디오 녹화 - 촬영 - 투 생 - 미디어 파일 없음! - 제시 - 그림을 휴대 전화에 저장할지 여부? - 그림 저장 실패 - 그림 저장 성공 - 모든 오디오 - 녹음 - 재생 - 중지 - 출구 - 일시 정지 - 이미지 손상됨 - 비디오가 손상되었습니다 - 오디오가 손상됨 - 확정 - %1$d/%2$d - 자른 데이터가 없습니다 - 원본 이미지 - 완성 - 완성(%1$d/%2$d) - 미리보기(%1$d) - 선택 - 앨범 정보 이상 가져오기… - 녹화 시간이 너무 짧다 - 사진 찍기 - 최대 %1$ds 초 이내의 영상을 선택할 수 있습니다 - %1$ds 내의 영상을 선택할 수 없습니다 - %1$ds~%2$ds 내의 영상만 선택할 수 있습니다 - 사진 찍기 클릭 - 카메라 - 설치 - 알 겠 습 니 다 - 데이터 없 음… - diff --git a/picture_library/src/main/res/values-vi-rVN/string.xml b/picture_library/src/main/res/values-vi-rVN/string.xml deleted file mode 100644 index 544a33d39..000000000 --- a/picture_library/src/main/res/values-vi-rVN/string.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - Camera cuộn - %1$s (%2$d) - Hủy bỏ - Bắn - Không thể chọn hình ảnh hoặc video cùng một lúc - Bạn có thể chọn tối đa%1$shình ảnh - Lựa chọn video tối thiểu phải có ít nhất%1$s - Bạn có thể chọn tối đa%1$s video - Bạn có thể chọn tối đa%1$sâm thanh - Xem trước - Xin vui lòng chờ… - %1$d/%2$d Hoàn thành - Đã hoàn thành - Hoàn thành - Vui lòng chọn - Không có video hoặc hình ảnh\n - Không có tập tin âm thanh\n - Bạn có thể sử dụng máy ảnh để chụp ảnh hoặc quay video - Bạn có thể ghi lại âm thanh bằng cách ghi hệ thống - Lựa chọn tối thiểu của hình ảnh không được ít hơn%1$s - Hình ảnh chuyển động - Đọc thẻ nhớ bị từ chối - Nhận được sự cho phép của hệ thống camera - Nhận quyền ghi lại hệ thống bị từ chối - Video không thể xem trước - Quay video - Chụp ảnh - Hình dài - Không có tập tin phương tiện! - Gợi ý - Có lưu ảnh vào điện thoại không? - Lưu ảnh thất bại - Hình ảnh được lưu vào - Tất cả âm thanh - Ghi âm - Chơi - Dừng lại - Thoát - Tạm dừng - Hình ảnh bị hỏng - Video bị hỏng - Âm thanh bị hỏng - Được rồi - %1$d/%2$d - Không có dữ liệu cây trồng - Ảnh gốc - Hoàn - Hoàn(%1$d/%2$d) - Xem trước(%1$d) - Chọn - Lấy ngoại lệ dữ liệu album… - Thời gian ghi âm quá ngắn - Chụp ảnh đi - Bạn chỉ có thể chọn ảnh trong vòng %1$ds nhất - Không thể chọn video dưới %1$ds giây - Chỉ có thể chọn ảnh giữa %1$ds và %2$ds giây - Ảnh - Máy ảnh dài - Chuẩn bị - Được rồi - không có dữ liệu… - \ No newline at end of file diff --git a/picture_library/src/main/res/values-zh-rTW/strings.xml b/picture_library/src/main/res/values-zh-rTW/strings.xml deleted file mode 100644 index bf06f8f4a..000000000 --- a/picture_library/src/main/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,63 +0,0 @@ - - 相機膠卷 - %1$s (%2$d) - 取消 - 拍攝 - 不能同時選擇圖片或視頻 - 妳最多只能選擇%1$s張照片 - 視頻最低選擇不能少於%1$s個 - 妳最多只能選擇%1$s個視頻 - 妳最多只能選擇%1$s個音頻 - 預覽 - 請稍候… - %1$d/%2$d 完成 - 已完成 - 完 成 - 請選擇 - 無視頻或照片\n - 無音頻文件\n - 妳可以使用相機拍攝照片或視頻 - 妳可以使用系統錄音錄制音頻 - 圖片最低選擇不能少於%1$s張 - 動圖 - 讀取內存卡權限被拒絕 - 獲取系統相機權限被拒絕 - 獲取系統錄音權限被拒絕 - 視頻不可預覽 - 錄視頻 - 拍照 - 長圖 - 暫無媒體文件! - 提示 - 是否保存圖片至手機? - 圖片保存失敗 - 圖片保存成功至 - 所有音頻 - 錄音 - 播放 - 停止 - 退出 - 暫停 - 圖片已損壞 - 視頻已損壞 - 音頻已損壞 - 確定 - %1$d/%2$d - 無可用裁剪數據 - 原圖 - 完成 - 完成(%1$d/%2$d) - 預覽(%1$d) - 選擇 - 獲取相冊數據異常... - 錄制時間過短 - 单击拍照,長按攝像 - 點擊拍照 - 長按攝像 - 最大只能選擇 %1$ds 以內的視頻 - 不能選擇低於 %1$ds 內的視頻 - 只能選擇 %1$ds 至 %2$ds內的視頻 - 去設置 - 我知道了 - 這裏空空如也… - diff --git a/picture_library/src/main/res/values-zh/strings.xml b/picture_library/src/main/res/values-zh/strings.xml deleted file mode 100644 index 708203e59..000000000 --- a/picture_library/src/main/res/values-zh/strings.xml +++ /dev/null @@ -1,63 +0,0 @@ - - 相机胶卷 - %1$s (%2$d) - 取消 - 拍摄 - 不能同时选择图片或视频 - 你最多只能选择%1$s张照片 - 视频最低选择不能少于%1$s个 - 你最多只能选择%1$s个视频 - 你最多只能选择%1$s个音频 - 预览 - 请稍候… - %1$d/%2$d 完成 - 已完成 - 完 成 - 请选择 - 无视频或照片\n - 无音频文件\n - 你可以使用相机拍摄照片或视频 - 你可以使用系统录音录制音频 - 图片最低选择不能少于%1$s张 - 动图 - 读取内存卡权限被拒绝 - 获取系统相机权限被拒绝 - 获取系统录音权限被拒绝 - 视频不可预览 - 录视频 - 拍照 - 长图 - 暂无媒体文件! - 提示 - 是否保存图片至手机? - 图片保存失败 - 图片保存成功至 - 所有音频 - 录音 - 播放 - 停止 - 退出 - 暂停 - 图片已损坏 - 视频已损坏 - 音频已损坏 - 确定 - %1$d/%2$d - 无可用裁剪数据 - 原图 - 完成 - 完成(%1$d/%2$d) - 预览(%1$d) - 选择 - 获取相册数据异常… - 录制时间过短 - 单击拍照,长按摄像 - 单击拍照 - 长按摄像 - 最大只能选择 %1$ds 以内的视频 - 不能选择低于 %1$ds 内的视频 - 只能选择 %1$ds 至 %2$ds内的视频 - 去设置 - 我知道了 - 这里空空如也… - diff --git a/picture_library/src/main/res/values/strings.xml b/picture_library/src/main/res/values/strings.xml index 708203e59..db8e53802 100644 --- a/picture_library/src/main/res/values/strings.xml +++ b/picture_library/src/main/res/values/strings.xml @@ -1,63 +1,63 @@ - 相机胶卷 - %1$s (%2$d) - 取消 - 拍摄 - 不能同时选择图片或视频 - 你最多只能选择%1$s张照片 - 视频最低选择不能少于%1$s个 - 你最多只能选择%1$s个视频 - 你最多只能选择%1$s个音频 - 预览 - 请稍候… - %1$d/%2$d 完成 - 已完成 - 完 成 - 请选择 - 无视频或照片\n - 无音频文件\n - 你可以使用相机拍摄照片或视频 - 你可以使用系统录音录制音频 - 图片最低选择不能少于%1$s张 - 动图 - 读取内存卡权限被拒绝 - 获取系统相机权限被拒绝 - 获取系统录音权限被拒绝 - 视频不可预览 - 录视频 - 拍照 - 长图 - 暂无媒体文件! - 提示 - 是否保存图片至手机? - 图片保存失败 - 图片保存成功至 - 所有音频 - 录音 - 播放 - 停止 - 退出 - 暂停 - 图片已损坏 - 视频已损坏 - 音频已损坏 - 确定 - %1$d/%2$d - 无可用裁剪数据 - 原图 - 完成 - 完成(%1$d/%2$d) - 预览(%1$d) - 选择 - 获取相册数据异常… - 录制时间过短 - 单击拍照,长按摄像 - 单击拍照 - 长按摄像 - 最大只能选择 %1$ds 以内的视频 - 不能选择低于 %1$ds 内的视频 - 只能选择 %1$ds 至 %2$ds内的视频 - 去设置 - 我知道了 - 这里空空如也… + 카메라 필름 + %1$s (%2$d) + 취소 + 촬영 + 사진과 동영상를 동시에 선택할 수 없습니다 + 최대 %1$d장 사진 선택이 가능합니다 + 최소한 동영상 선택은 %1$d장 이상이어야 합니다 + 최대 %1$d개의 동영상을 선택할 수 있습니다 + 최대 %1$d개의 오디오를 선택할 수 있습니다 + 미리보기 + 잠시 기다려 주세요 + %1$d/%2$d 완료 + 완료 + 완료 + 완료(%1$d) + 선택하십시오 + 사진과 동영상이 없음\n + 오디오 파일 없음\n + 사진을 찍거나 동영상을 찍을 수 있습니다 + 시스템으로 오디오 녹음을 할 수 있습니다 + 사진은 최소 %1$d장 이상이어야 합니다 + GIF + 저장소 읽기 권한이 거부되었습니다 + 시스템 카메라 가져오기 권한이 거부되었습니다 + 시스템 녹음 권한 가져오기 거부되었습니다 + 동영상 녹화 + 촬영 + 세로형 + 미디어 파일 없음! + 확인 + 사진을 핸드폰에 저장히시겠습니까? + 사진 저장 실패 + 사진 저장 성공 + 모든 오디오 + 녹음 + 재생 + 중지 + 나가기 + 일시 정지 + 이미지가 손상되었습니다 + 동영상이 손상되었습니다 + 오디오가 손상되었습니다 + 확정 + %1$d/%2$d + 자른 데이터가 없습니다 + 원본 이미지 + 완성 + 완성(%1$d/%2$d) + 미리보기(%1$d) + 선택 + 앨범 정보 불러오기 실패 + 녹화 시간이 너무 짧습니다 + 사진 찍기 + 최대 %1$d초 이내의 영상을 선택할 수 있습니다 + %1$d내의 영상을 선택할 수 없습니다 + %1$d~%2$d 내의 영상만 선택할 수 있습니다 + 사진 찍기 + 카메라 + 설정 + 확인 + 데이터 없음 diff --git a/ucrop/src/main/res/values-de/strings.xml b/ucrop/src/main/res/values-de/strings.xml deleted file mode 100755 index 381392d32..000000000 --- a/ucrop/src/main/res/values-de/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Foto editieren - Original - Zuschneiden - Bewegen - \ No newline at end of file diff --git a/ucrop/src/main/res/values-es-rES/string.xml b/ucrop/src/main/res/values-es-rES/string.xml deleted file mode 100644 index 2bb82f453..000000000 --- a/ucrop/src/main/res/values-es-rES/string.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - gif - Editar foto - Original - Recortar - \ No newline at end of file diff --git a/ucrop/src/main/res/values-fi/strings.xml b/ucrop/src/main/res/values-fi/strings.xml deleted file mode 100755 index 823987d14..000000000 --- a/ucrop/src/main/res/values-fi/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - Muokkaa kuvaa - Rajaa - Sekä sisäänmeno- että ulostulo-Urit täytyy olla määritettyinä - - Lahja - \ No newline at end of file diff --git a/ucrop/src/main/res/values-fr/strings.xml b/ucrop/src/main/res/values-fr/strings.xml deleted file mode 100755 index 82524b17f..000000000 --- a/ucrop/src/main/res/values-fr/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Original - Modifier la photo - Recadrer - Bouge fig - diff --git a/ucrop/src/main/res/values-it/strings.xml b/ucrop/src/main/res/values-it/strings.xml deleted file mode 100755 index 68d02893b..000000000 --- a/ucrop/src/main/res/values-it/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Originale - Modifica foto - Taglia - Muovi - diff --git a/ucrop/src/main/res/values-ja-rJP/strings.xml b/ucrop/src/main/res/values-ja-rJP/strings.xml deleted file mode 100755 index c0b2c9266..000000000 --- a/ucrop/src/main/res/values-ja-rJP/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - 元の比率 - 切り取り - - 切り取り - gif図 - diff --git a/ucrop/src/main/res/values-ko/strings.xml b/ucrop/src/main/res/values-ko/strings.xml deleted file mode 100755 index 2f963693a..000000000 --- a/ucrop/src/main/res/values-ko/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 사진 편집 - 원본 - 확인 - 움직이 - \ No newline at end of file diff --git a/ucrop/src/main/res/values-nl/strings.xml b/ucrop/src/main/res/values-nl/strings.xml deleted file mode 100755 index 097dfa5dd..000000000 --- a/ucrop/src/main/res/values-nl/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Origineel - Foto bewerken - Bijsnijden - Bewegen - diff --git a/ucrop/src/main/res/values-sk/strings.xml b/ucrop/src/main/res/values-sk/strings.xml deleted file mode 100755 index 871e34f26..000000000 --- a/ucrop/src/main/res/values-sk/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Pôvodná - Upraviť fotografiu - Orezať - Pohybu - diff --git a/ucrop/src/main/res/values-zh-rTW/strings.xml b/ucrop/src/main/res/values-zh-rTW/strings.xml deleted file mode 100755 index cc1aa3f71..000000000 --- a/ucrop/src/main/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - 原始比例 - 裁切 - - 裁切 - - 必須指定輸入以及輸出的 Uri - 在你的 App 內覆寫顏色資源檔 (ucrop_color_toolbar_widget) 使 5.0 以前裝置正常運作 - 動圖 - diff --git a/ucrop/src/main/res/values-zh/strings.xml b/ucrop/src/main/res/values-zh/strings.xml deleted file mode 100755 index 6916204e4..000000000 --- a/ucrop/src/main/res/values-zh/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - 原始比例 - 裁剪 - - 裁剪 - 动图 - diff --git a/ucrop/src/main/res/values/strings.xml b/ucrop/src/main/res/values/strings.xml index f37d68919..a608cbf5a 100755 --- a/ucrop/src/main/res/values/strings.xml +++ b/ucrop/src/main/res/values/strings.xml @@ -1,15 +1,12 @@ - - Original - Edit Photo - - Crop - - Both input and output Uri must be specified - Therefore, override color resource (ucrop_color_toolbar_widget) in your app to make it work on pre-L devices - Rotate - Scale - Crop - - gif + 원본 + 사진 편집 + 확인 + GIF + 회전 + 크기 + 자르기 + + 일시적인 오류가 발생했습니다.(CROP_URI_ERROR) + 일시적인 오류가 발생했습니다.(CROP_TOOLBAR_WIDGET) From 679f7e02335f8749a979718a84da6f80dfdda4c5 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Thu, 1 Apr 2021 15:11:00 +0900 Subject: [PATCH 02/11] forResult Method intent add --- .../picture/lib/PictureSelectionModel.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java index c718f5091..3499dee31 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java @@ -1432,6 +1432,34 @@ else if (selectionConfig.isDoctalkStyle) { } } + /** + * Start to select media and wait for result. + * + * @param intent Picture selector intent + * @param listener The resulting callback listens + */ + public void forResult (Intent intent, OnResultCallbackListener listener) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null || selectionConfig == null) { + return; + } + // 绑定回调监听 + PictureSelectionConfig.listener = new WeakReference<>(listener).get(); + selectionConfig.isCallbackMode = true; + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivity(intent); + } + else { + activity.startActivity(intent); + } + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition( + windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + /** * Start to select media and wait for result. * From bad5baa57a22d9b2325ab51c03013f4733759f00 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Wed, 27 Oct 2021 15:23:03 +0900 Subject: [PATCH 03/11] =?UTF-8?q?2.7.3=20=EC=BD=94=EB=93=9C=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- picture_library/build.gradle | 2 +- picture_library/src/main/AndroidManifest.xml | 3 - .../luck/picture/lib/PictureBaseActivity.java | 1 + .../lib/PictureSelectorDoctalkActivity.java | 2312 ----------------- .../lib/adapter/PictureImageGridAdapter.java | 1 + .../src/main/res/layout/picture_doctalk.xml | 37 - .../src/main/res/values-de-rDE/strings.xml | 72 - .../src/main/res/values-en-rUS/string.xml | 80 - .../src/main/res/values-es-rES/string.xml | 72 - .../src/main/res/values-fr-rFR/strings.xml | 71 - .../src/main/res/values-ja-rJP/strings.xml | 72 - .../src/main/res/values-ko-rKR/strings.xml | 71 - .../src/main/res/values-pt-rPT/strings.xml | 77 - .../src/main/res/values-vi-rVN/string.xml | 72 - .../src/main/res/values-zh-rCN/strings.xml | 77 - .../src/main/res/values-zh-rTW/strings.xml | 73 - .../src/main/res/values/strings.xml | 141 +- settings.gradle | 2 +- 18 files changed, 75 insertions(+), 3161 deletions(-) delete mode 100644 picture_library/src/main/java/com/luck/picture/lib/PictureSelectorDoctalkActivity.java delete mode 100644 picture_library/src/main/res/layout/picture_doctalk.xml delete mode 100644 picture_library/src/main/res/values-de-rDE/strings.xml delete mode 100644 picture_library/src/main/res/values-en-rUS/string.xml delete mode 100644 picture_library/src/main/res/values-es-rES/string.xml delete mode 100644 picture_library/src/main/res/values-fr-rFR/strings.xml delete mode 100644 picture_library/src/main/res/values-ja-rJP/strings.xml delete mode 100644 picture_library/src/main/res/values-ko-rKR/strings.xml delete mode 100644 picture_library/src/main/res/values-pt-rPT/strings.xml delete mode 100644 picture_library/src/main/res/values-vi-rVN/string.xml delete mode 100644 picture_library/src/main/res/values-zh-rCN/strings.xml delete mode 100644 picture_library/src/main/res/values-zh-rTW/strings.xml diff --git a/picture_library/build.gradle b/picture_library/build.gradle index 6756e4d72..8cbe367c3 100644 --- a/picture_library/build.gradle +++ b/picture_library/build.gradle @@ -27,7 +27,7 @@ android { abortOnError false } - resourcePrefix 'ucrop_' +// resourcePrefix 'ucrop_' } apply from: '../publish.gradle' diff --git a/picture_library/src/main/AndroidManifest.xml b/picture_library/src/main/AndroidManifest.xml index 19444aac4..c10e4a115 100644 --- a/picture_library/src/main/AndroidManifest.xml +++ b/picture_library/src/main/AndroidManifest.xml @@ -25,9 +25,6 @@ - , OnItemClickListener, OnRecyclerViewPreloadMoreListener { - - private static final String TAG = PictureSelectorDoctalkActivity.class.getSimpleName(); - - // 상단 왼쪽 뒤로가기 버튼 - protected ImageView mIvPictureLeftBack; - // 폴더 접이 화살표 - protected ImageView mIvArrow; - // 상단 타이틀바 레이아웃 - protected View mTitleBar; - // 상단 타이틀 클릭 이펙트 - protected View viewClickMask; - // 상단 타이틀 텍스트 - protected TextView mTvPictureTitle; - // 상단 타이틀 오른쪽 버튼 - protected TextView mTvPictureRight; - - // 오디오 플레이 버튼 - protected TextView mTvPlayPause; - // 오디오 멈춤 버튼 - protected TextView mTvStop; - // 오디오 종료 버튼 - protected TextView mTvQuit; - // 오디오 상태 정보 - protected TextView mTvMusicStatus; - // 오디오 총 시간 길이 - protected TextView mTvMusicTotal; - // 오디오 현재 시간위치 - protected TextView mTvMusicTime; - // 오디오 재생 플레이어 - protected MediaPlayer mediaPlayer; - // 오디오 SeekBar - protected SeekBar musicSeekBar; - public Runnable mRunnable = new Runnable() { - @Override - public void run () { - try { - if (mediaPlayer != null) { - mTvMusicTime.setText(DateUtils.formatDurationTime(mediaPlayer.getCurrentPosition())); - musicSeekBar.setProgress(mediaPlayer.getCurrentPosition()); - musicSeekBar.setMax(mediaPlayer.getDuration()); - mTvMusicTotal.setText(DateUtils.formatDurationTime(mediaPlayer.getDuration())); - if (mHandler != null) { - mHandler.postDelayed(mRunnable, 200); - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - }; - // 오디오 재생 여부 - protected boolean isPlayAudio = false; - // 리스트뷰 - protected RecyclerPreloadView mRecyclerView; - // 아답터 - protected PictureImageGridAdapter mAdapter; - // 미디어가 없을 때 표시 - protected TextView mTvEmpty; - // 폴더 팝업 - protected FolderPopWindow folderWindow; - // 애니메이션 정의 - protected Animation animation = null; - // 애니메이션 시작 여부 - protected boolean isStartAnimation = false; - // 커스텀 다이얼로그 팝업 - protected PictureCustomDialog audioDialog; - // 이전 선택 이미지 사이즈 - protected int oldCurrentListSize; - // 해당 화면 진입해서 초기화 여부 - protected boolean isEnterSetting; - // 최상위 이동 인터벌 처리 - private long intervalClickTime = 0; - // 해당 폴더안에 이미지 갯수 - private int allFolderSize; - // 카메라 수 - private int mOpenCameraCount; - - @Override - protected void onCreate (Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState != null) { - allFolderSize = savedInstanceState.getInt(PictureConfig.EXTRA_ALL_FOLDER_SIZE); - oldCurrentListSize = savedInstanceState.getInt(PictureConfig.EXTRA_OLD_CURRENT_LIST_SIZE, 0); - List cacheData = PictureSelector.obtainSelectorList(savedInstanceState); - selectionMedias = cacheData != null ? cacheData : selectionMedias; - if (mAdapter != null) { - isStartAnimation = true; - mAdapter.bindSelectData(selectionMedias); - } - } - } - - @Override - protected void onResume () { - super.onResume(); - if (isEnterSetting) { - if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && - PermissionChecker.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - - if (mAdapter.isDataEmpty()) { - readLocalMedia(); - } - } - else { - showPermissionsDialog(false, getString(R.string.picture_jurisdiction)); - } - isEnterSetting = false; - } - } - - @Override - public int getResourceId () { - return R.layout.picture_doctalk; - } - - @Override - protected void initWidgets () { - super.initWidgets(); - container = findViewById(R.id.container); - mTitleBar = findViewById(R.id.titleBar); - mIvPictureLeftBack = findViewById(R.id.pictureLeftBack); - mTvPictureTitle = findViewById(R.id.picture_title); - mTvPictureRight = findViewById(R.id.picture_right); - mIvArrow = findViewById(R.id.ivArrow); - viewClickMask = findViewById(R.id.viewClickMask); - mRecyclerView = findViewById(R.id.picture_recycler); - mTvEmpty = findViewById(R.id.tv_empty); - isNumComplete(numComplete); - if (!numComplete) { - animation = AnimationUtils.loadAnimation(this, R.anim.picture_anim_modal_in); - } - if (config.isAutomaticTitleRecyclerTop) { - mTitleBar.setOnClickListener(this); - } - mIvPictureLeftBack.setOnClickListener(this); - mTvPictureRight.setOnClickListener(this); - viewClickMask.setOnClickListener(this); - mTvPictureTitle.setOnClickListener(this); - mIvArrow.setOnClickListener(this); - //noinspection deprecation - String title = config.chooseMode == PictureMimeType.ofAudio() ? getString(R.string.picture_all_audio) : getString(R.string.picture_camera_roll); - mTvPictureTitle.setText(title); - mTvPictureTitle.setTag(R.id.view_tag, -1); - folderWindow = new FolderPopWindow(this); - folderWindow.setArrowImageView(mIvArrow); - folderWindow.setOnAlbumItemClickListener(this); - mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(config.imageSpanCount <= 0 ? PictureConfig.DEFAULT_SPAN_COUNT : config.imageSpanCount, ScreenUtils.dip2px(this, 2), false)); - mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), config.imageSpanCount <= 0 ? PictureConfig.DEFAULT_SPAN_COUNT : config.imageSpanCount)); - if (!config.isPageStrategy) { - mRecyclerView.setHasFixedSize(true); - } - else { - mRecyclerView.setReachBottomRow(RecyclerPreloadView.BOTTOM_PRELOAD); - mRecyclerView.setOnRecyclerViewPreloadListener(PictureSelectorDoctalkActivity.this); - } - RecyclerView.ItemAnimator itemAnimator = mRecyclerView.getItemAnimator(); - if (itemAnimator != null) { - ((SimpleItemAnimator) itemAnimator).setSupportsChangeAnimations(false); - mRecyclerView.setItemAnimator(null); - } - loadAllMediaData(); - //noinspection deprecation - mTvEmpty.setText(config.chooseMode == PictureMimeType.ofAudio() ? getString(R.string.picture_audio_empty) : getString(R.string.picture_empty)); - StringUtils.tempTextFont(mTvEmpty, config.chooseMode); - mAdapter = new PictureImageGridAdapter(getContext(), config); - mAdapter.setOnPhotoSelectChangedListener(this); - - switch (config.animationMode) { - case AnimationType.ALPHA_IN_ANIMATION: - mRecyclerView.setAdapter(new AlphaInAnimationAdapter(mAdapter)); - break; - case AnimationType.SLIDE_IN_BOTTOM_ANIMATION: - mRecyclerView.setAdapter(new SlideInBottomAnimationAdapter(mAdapter)); - break; - default: - mRecyclerView.setAdapter(mAdapter); - break; - } - } - - @Override - public void onRecyclerViewPreloadMore () { - loadMoreData(); - } - - /** - * getPageLimit - * # If the user clicks to take a photo and returns, the Limit should be adjusted dynamically - * - * @return - */ - private int getPageLimit () { - int bucketId = ValueOf.toInt(mTvPictureTitle.getTag(R.id.view_tag)); - if (bucketId == -1) { - int limit = mOpenCameraCount > 0 ? config.pageSize - mOpenCameraCount : config.pageSize; - mOpenCameraCount = 0; - return limit; - } - return config.pageSize; - } - - /** - * load more data - */ - private void loadMoreData () { - if (mAdapter != null) { - if (isHasMore) { - mPage++; - long bucketId = ValueOf.toLong(mTvPictureTitle.getTag(R.id.view_tag)); - LocalMediaPageLoader.getInstance(getContext()).loadPageMediaData(bucketId, mPage, getPageLimit(), - (OnQueryDataResultListener) (result, currentPage, isHasMore) -> { - if (!isFinishing()) { - this.isHasMore = isHasMore; - if (isHasMore) { - hideDataNull(); - int size = result.size(); - if (size > 0) { - int positionStart = mAdapter.getSize(); - mAdapter.getData().addAll(result); - int itemCount = mAdapter.getItemCount(); - mAdapter.notifyItemRangeChanged(positionStart, itemCount); - } - else { - onRecyclerViewPreloadMore(); - } - if (size < PictureConfig.MIN_PAGE_SIZE) { - mRecyclerView.onScrolled(mRecyclerView.getScrollX(), mRecyclerView.getScrollY()); - } - } - else { - boolean isEmpty = mAdapter.isDataEmpty(); - if (isEmpty) { - showDataNull(bucketId == -1 ? getString(R.string.picture_empty) : getString(R.string.picture_data_null), R.drawable.picture_icon_no_data); - } - } - } - }); - } - } - } - - /** - * load All Data - */ - private void loadAllMediaData () { - if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && - PermissionChecker.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - - readLocalMedia(); - } - else { - PermissionChecker.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE); - } - } - - @Override - public void initPictureSelectorStyle () { - if (PictureSelectionConfig.uiStyle != null) { - if (PictureSelectionConfig.uiStyle.picture_top_titleArrowDownDrawable != 0) { - Drawable drawable = ContextCompat.getDrawable(this, PictureSelectionConfig.uiStyle.picture_top_titleArrowDownDrawable); - mIvArrow.setImageDrawable(drawable); - } - - if (PictureSelectionConfig.uiStyle.picture_top_titleTextColor != 0) { - mTvPictureTitle.setTextColor(PictureSelectionConfig.uiStyle.picture_top_titleTextColor); - } - if (PictureSelectionConfig.uiStyle.picture_top_titleTextSize != 0) { - mTvPictureTitle.setTextSize(PictureSelectionConfig.uiStyle.picture_top_titleTextSize); - } - if (PictureSelectionConfig.uiStyle.picture_top_titleRightTextColor.length > 0) { - ColorStateList colorStateList = AttrsUtils.getColorStateList(PictureSelectionConfig.uiStyle.picture_top_titleRightTextColor); - if (colorStateList != null) { - mTvPictureRight.setTextColor(colorStateList); - } - } - if (PictureSelectionConfig.uiStyle.picture_top_titleRightTextSize != 0) { - mTvPictureRight.setTextSize(PictureSelectionConfig.uiStyle.picture_top_titleRightTextSize); - } - if (PictureSelectionConfig.uiStyle.picture_top_leftBack != 0) { - mIvPictureLeftBack.setImageResource(PictureSelectionConfig.uiStyle.picture_top_leftBack); - } - - if (PictureSelectionConfig.uiStyle.picture_container_backgroundColor != 0) { - container.setBackgroundColor(PictureSelectionConfig.uiStyle.picture_container_backgroundColor); - } - if (PictureSelectionConfig.uiStyle.picture_top_titleRightDefaultText != 0) { - mTvPictureRight.setText(PictureSelectionConfig.uiStyle.picture_top_titleRightDefaultText); - } - - if (PictureSelectionConfig.uiStyle.picture_top_titleArrowLeftPadding != 0) { - RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvArrow.getLayoutParams(); - params.leftMargin = PictureSelectionConfig.uiStyle.picture_top_titleArrowLeftPadding; - } - - if (PictureSelectionConfig.uiStyle.picture_top_titleBarHeight > 0) { - ViewGroup.LayoutParams params = mTitleBar.getLayoutParams(); - params.height = PictureSelectionConfig.uiStyle.picture_top_titleBarHeight; - } - } - else if (PictureSelectionConfig.style != null) { - if (PictureSelectionConfig.style.pictureTitleDownResId != 0) { - Drawable drawable = ContextCompat.getDrawable(this, PictureSelectionConfig.style.pictureTitleDownResId); - mIvArrow.setImageDrawable(drawable); - } - if (PictureSelectionConfig.style.pictureTitleTextColor != 0) { - mTvPictureTitle.setTextColor(PictureSelectionConfig.style.pictureTitleTextColor); - } - if (PictureSelectionConfig.style.pictureTitleTextSize != 0) { - mTvPictureTitle.setTextSize(PictureSelectionConfig.style.pictureTitleTextSize); - } - - if (PictureSelectionConfig.style.pictureRightDefaultTextColor != 0) { - mTvPictureRight.setTextColor(PictureSelectionConfig.style.pictureRightDefaultTextColor); - } - else { - //noinspection deprecation - if (PictureSelectionConfig.style.pictureCancelTextColor != 0) { - //noinspection deprecation - mTvPictureRight.setTextColor(PictureSelectionConfig.style.pictureCancelTextColor); - } - } - if (PictureSelectionConfig.style.pictureRightTextSize != 0) { - mTvPictureRight.setTextSize(PictureSelectionConfig.style.pictureRightTextSize); - } - - if (PictureSelectionConfig.style.pictureLeftBackIcon != 0) { - mIvPictureLeftBack.setImageResource(PictureSelectionConfig.style.pictureLeftBackIcon); - } - if (PictureSelectionConfig.style.pictureContainerBackgroundColor != 0) { - container.setBackgroundColor(PictureSelectionConfig.style.pictureContainerBackgroundColor); - } - if (!TextUtils.isEmpty(PictureSelectionConfig.style.pictureRightDefaultText)) { - mTvPictureRight.setText(PictureSelectionConfig.style.pictureRightDefaultText); - } - - if (PictureSelectionConfig.style.pictureTitleRightArrowLeftPadding != 0) { - RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvArrow.getLayoutParams(); - params.leftMargin = PictureSelectionConfig.style.pictureTitleRightArrowLeftPadding; - } - - if (PictureSelectionConfig.style.pictureTitleBarHeight > 0) { - ViewGroup.LayoutParams params = mTitleBar.getLayoutParams(); - params.height = PictureSelectionConfig.style.pictureTitleBarHeight; - } - } - else { - int titleColor = AttrsUtils.getTypeValueColor(getContext(), R.attr.picture_title_textColor); - if (titleColor != 0) { - mTvPictureTitle.setTextColor(titleColor); - } - int rightTitleColor = AttrsUtils.getTypeValueColor(getContext(), R.attr.picture_right_textColor); - if (rightTitleColor != 0) { - mTvPictureRight.setTextColor(rightTitleColor); - } - int containerBackgroundColor = AttrsUtils.getTypeValueColor(getContext(), R.attr.picture_container_backgroundColor); - if (containerBackgroundColor != 0) { - container.setBackgroundColor(containerBackgroundColor); - } - Drawable leftDrawable = AttrsUtils.getTypeValueDrawable(getContext(), R.attr.picture_leftBack_icon, R.drawable.picture_icon_back); - mIvPictureLeftBack.setImageDrawable(leftDrawable); - - //noinspection deprecation - if (config.downResId != 0) { - //noinspection deprecation - Drawable drawable = ContextCompat.getDrawable(this, config.downResId); - mIvArrow.setImageDrawable(drawable); - } - else { - Drawable downDrawable = AttrsUtils.getTypeValueDrawable(getContext(), R.attr.picture_arrow_down_icon, R.drawable.picture_icon_arrow_down); - mIvArrow.setImageDrawable(downDrawable); - } - int pictureTitleRightArrowLeftPadding = AttrsUtils.getTypeValueSizeForInt(getContext(), R.attr.picture_titleRightArrow_LeftPadding); - if (pictureTitleRightArrowLeftPadding != 0) { - RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvArrow.getLayoutParams(); - params.leftMargin = pictureTitleRightArrowLeftPadding; - } - - int titleBarHeight = AttrsUtils.getTypeValueSizeForInt(getContext(), R.attr.picture_titleBar_height); - if (titleBarHeight > 0) { - ViewGroup.LayoutParams params = mTitleBar.getLayoutParams(); - params.height = titleBarHeight; - } - } - mTitleBar.setBackgroundColor(colorPrimary); - mAdapter.bindSelectData(selectionMedias); - } - - @Override - protected void onSaveInstanceState (@NotNull Bundle outState) { - super.onSaveInstanceState(outState); - if (mAdapter != null) { - // Save the number of pictures or videos in the current list - outState.putInt(PictureConfig.EXTRA_OLD_CURRENT_LIST_SIZE, mAdapter.getSize()); - // Save the number of Camera film and Camera folder files - int size = folderWindow.getFolderData().size(); - if (size > 0) { - outState.putInt(PictureConfig.EXTRA_ALL_FOLDER_SIZE, folderWindow.getFolder(0).getImageNum()); - } - if (mAdapter.getSelectedData() != null) { - List selectedImages = mAdapter.getSelectedData(); - PictureSelector.saveSelectorList(outState, selectedImages); - } - } - } - - /** - * none number style - */ - private void isNumComplete (boolean numComplete) { - if (numComplete) { - initCompleteText(0); - } - } - - /** - * init Text - */ - @Override - protected void initCompleteText (int startCount) { - if (config.selectionMode == PictureConfig.SINGLE) { - if (startCount <= 0) { - mTvPictureRight.setText(getString(R.string.picture_cancel)); - } - else { - mTvPictureRight.setText(getString(R.string.picture_done)); - } - } - else { - if (startCount <= 0) { - mTvPictureRight.setText(getString(R.string.picture_cancel)); - } - else { - mTvPictureRight.setText(getString(R.string.picture_done_count, startCount)); - } - } - } - - /** - * get LocalMedia s - */ - protected void readLocalMedia () { - showPleaseDialog(); - if (config.isPageStrategy) { - LocalMediaPageLoader.getInstance(getContext()).loadAllMedia( - (data, currentPage, isHasMore) -> { - if (!isFinishing()) { - this.isHasMore = true; - initPageModel(data); - synchronousCover(); - } - }); - } - else { - PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask>() { - - @Override - public List doInBackground () { - //noinspection deprecation - return new LocalMediaLoader(getContext()).loadAllMedia(); - } - - @Override - public void onSuccess (List folders) { - initStandardModel(folders); - } - }); - } - } - - /** - * Page Model - * - * @param folders folders - */ - private void initPageModel (List folders) { - if (folders != null) { - folderWindow.bindFolder(folders); - mPage = 1; - LocalMediaFolder folder = folderWindow.getFolder(0); - mTvPictureTitle.setTag(R.id.view_count_tag, folder != null ? folder.getImageNum() : 0); - mTvPictureTitle.setTag(R.id.view_index_tag, 0); - long bucketId = folder != null ? folder.getBucketId() : -1; - mRecyclerView.setEnabledLoadMore(true); - LocalMediaPageLoader.getInstance(getContext()).loadPageMediaData(bucketId, mPage, - (data, currentPage, isHasMore) -> { - if (!isFinishing()) { - dismissDialog(); - if (mAdapter != null) { - this.isHasMore = true; - // IsHasMore being true means that there's still data, but data being 0 might be a filter that's turned on and that doesn't happen to fit on the whole page - if (isHasMore && data.size() == 0) { - onRecyclerViewPreloadMore(); - return; - } - int currentSize = mAdapter.getSize(); - int resultSize = data.size(); - oldCurrentListSize = oldCurrentListSize + currentSize; - if (resultSize >= currentSize) { - // This situation is mainly caused by the use of camera memory, the Activity is recycled - if (currentSize > 0 && currentSize < resultSize && oldCurrentListSize != resultSize) { - if (isLocalMediaSame(data.get(0))) { - mAdapter.bindData(data); - } - else { - mAdapter.getData().addAll(data); - } - } - else { - mAdapter.bindData(data); - } - } - boolean isEmpty = mAdapter.isDataEmpty(); - if (isEmpty) { - showDataNull(getString(R.string.picture_empty), R.drawable.picture_icon_no_data); - } - else { - hideDataNull(); - } - - } - } - }); - } - else { - showDataNull(getString(R.string.picture_data_exception), R.drawable.picture_icon_data_error); - dismissDialog(); - } - } - - /** - * ofAll Page Model Synchronous cover - */ - private void synchronousCover () { - if (config.chooseMode == PictureMimeType.ofAll()) { - PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask() { - - @Override - public Boolean doInBackground () { - int size = folderWindow.getFolderData().size(); - for (int i = 0; i < size; i++) { - LocalMediaFolder mediaFolder = folderWindow.getFolder(i); - if (mediaFolder == null) { - continue; - } - String firstCover = LocalMediaPageLoader - .getInstance(getContext()).getFirstCover(mediaFolder.getBucketId()); - mediaFolder.setFirstImagePath(firstCover); - } - return true; - } - - @Override - public void onSuccess (Boolean result) { - // TODO Synchronous Success - } - }); - } - } - - /** - * Standard Model - * - * @param folders folders - */ - private void initStandardModel (List folders) { - if (folders != null) { - if (folders.size() > 0) { - folderWindow.bindFolder(folders); - LocalMediaFolder folder = folders.get(0); - folder.setChecked(true); - mTvPictureTitle.setTag(R.id.view_count_tag, folder.getImageNum()); - List result = folder.getData(); - if (mAdapter != null) { - int currentSize = mAdapter.getSize(); - int resultSize = result.size(); - oldCurrentListSize = oldCurrentListSize + currentSize; - if (resultSize >= currentSize) { - // This situation is mainly caused by the use of camera memory, the Activity is recycled - if (currentSize > 0 && currentSize < resultSize && oldCurrentListSize != resultSize) { - mAdapter.getData().addAll(result); - LocalMedia media = mAdapter.getData().get(0); - folder.setFirstImagePath(media.getPath()); - folder.getData().add(0, media); - folder.setCheckedNum(1); - folder.setImageNum(folder.getImageNum() + 1); - updateMediaFolder(folderWindow.getFolderData(), media); - } - else { - mAdapter.bindData(result); - } - } - boolean isEmpty = mAdapter.isDataEmpty(); - if (isEmpty) { - showDataNull(getString(R.string.picture_empty), R.drawable.picture_icon_no_data); - } - else { - hideDataNull(); - } - } - } - else { - showDataNull(getString(R.string.picture_empty), R.drawable.picture_icon_no_data); - } - } - else { - showDataNull(getString(R.string.picture_data_exception), R.drawable.picture_icon_data_error); - } - dismissDialog(); - } - - /** - * isSame - * - * @param newMedia new media - * @return same media true/false - */ - private boolean isLocalMediaSame (LocalMedia newMedia) { - LocalMedia oldMedia = mAdapter.getItem(0); - if (oldMedia == null || newMedia == null) { - return false; - } - if (oldMedia.getPath().equals(newMedia.getPath())) { - return true; - } - // if Content:// type,determines whether the suffix id is consistent, mainly to solve the following two types of problems - // content://media/external/images/media/5844 - // content://media/external/file/5844 - if (PictureMimeType.isContent(newMedia.getPath()) - && PictureMimeType.isContent(oldMedia.getPath())) { - if (!TextUtils.isEmpty(newMedia.getPath()) && !TextUtils.isEmpty(oldMedia.getPath())) { - String newId = newMedia.getPath().substring(newMedia.getPath().lastIndexOf("/") + 1); - String oldId = oldMedia.getPath().substring(oldMedia.getPath().lastIndexOf("/") + 1); - return newId.equals(oldId); - } - } - return false; - } - - /** - * Open Camera - */ - public void startCamera () { - if (!DoubleUtils.isFastDoubleClick()) { - if (PictureSelectionConfig.onCustomCameraInterfaceListener != null) { - if (config.chooseMode == PictureConfig.TYPE_ALL) { - PhotoItemSelectedDialog selectedDialog = PhotoItemSelectedDialog.newInstance(); - selectedDialog.setOnItemClickListener(this); - selectedDialog.show(getSupportFragmentManager(), "PhotoItemSelectedDialog"); - } - else { - PictureSelectionConfig.onCustomCameraInterfaceListener.onCameraClick(getContext(), config, config.chooseMode); - config.cameraMimeType = config.chooseMode; - } - return; - } - if (config.isUseCustomCamera) { - startCustomCamera(); - return; - } - switch (config.chooseMode) { - case PictureConfig.TYPE_ALL: - PhotoItemSelectedDialog selectedDialog = PhotoItemSelectedDialog.newInstance(); - selectedDialog.setOnItemClickListener(this); - selectedDialog.show(getSupportFragmentManager(), "PhotoItemSelectedDialog"); - break; - case PictureConfig.TYPE_IMAGE: - startOpenCamera(); - break; - case PictureConfig.TYPE_VIDEO: - startOpenCameraVideo(); - break; - case PictureConfig.TYPE_AUDIO: - startOpenCameraAudio(); - break; - default: - break; - } - } - } - - /** - * Open Custom Camera - */ - private void startCustomCamera () { - if (PermissionChecker.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)) { - Intent intent = new Intent(this, PictureCustomCameraActivity.class); - startActivityForResult(intent, PictureConfig.REQUEST_CAMERA); - PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; - overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); - } - else { - PermissionChecker - .requestPermissions(this, - new String[]{Manifest.permission.RECORD_AUDIO}, PictureConfig.APPLY_RECORD_AUDIO_PERMISSIONS_CODE); - } - } - - @Override - public void onClick (View v) { - int id = v.getId(); - if (id == R.id.pictureLeftBack) { - if (folderWindow != null && folderWindow.isShowing()) { - folderWindow.dismiss(); - } - else { - onBackPressed(); - } - } - else if (id == R.id.picture_title || id == R.id.ivArrow || id == R.id.viewClickMask) { - if (folderWindow.isShowing()) { - folderWindow.dismiss(); - } - else { - if (!folderWindow.isEmpty()) { - folderWindow.showAsDropDown(mTitleBar); - if (!config.isSingleDirectReturn) { - List selectedImages = mAdapter.getSelectedData(); - folderWindow.updateFolderCheckStatus(selectedImages); - } - } - } - } - else if (id == R.id.picture_id_preview) { - onPreview(); - } - else if (id == R.id.picture_right) { - if (mAdapter.getSelectedSize() <= 0) { - if (folderWindow != null && folderWindow.isShowing()) { - folderWindow.dismiss(); - } - else { - onBackPressed(); - } - } - else { - onComplete(); - } - } - else if (id == R.id.titleBar) { - if (config.isAutomaticTitleRecyclerTop) { - int intervalTime = 500; - if (SystemClock.uptimeMillis() - intervalClickTime < intervalTime) { - if (mAdapter.getItemCount() > 0) { - mRecyclerView.scrollToPosition(0); - } - } - else { - intervalClickTime = SystemClock.uptimeMillis(); - } - } - } - } - - /** - * Preview - */ - private void onPreview () { - List selectedData = mAdapter.getSelectedData(); - List medias = new ArrayList<>(); - int size = selectedData.size(); - for (int i = 0; i < size; i++) { - LocalMedia media = selectedData.get(i); - medias.add(media); - } - if (PictureSelectionConfig.onCustomImagePreviewCallback != null) { - //noinspection unchecked - PictureSelectionConfig.onCustomImagePreviewCallback.onCustomPreviewCallback(getContext(), selectedData, 0); - return; - } - Bundle bundle = new Bundle(); - bundle.putParcelableArrayList(PictureConfig.EXTRA_PREVIEW_SELECT_LIST, (ArrayList) medias); - bundle.putParcelableArrayList(PictureConfig.EXTRA_SELECT_LIST, (ArrayList) selectedData); - bundle.putBoolean(PictureConfig.EXTRA_BOTTOM_PREVIEW, true); - bundle.putBoolean(PictureConfig.EXTRA_CHANGE_ORIGINAL, config.isCheckOriginalImage); - bundle.putBoolean(PictureConfig.EXTRA_SHOW_CAMERA, mAdapter.isShowCamera()); - bundle.putString(PictureConfig.EXTRA_IS_CURRENT_DIRECTORY, mTvPictureTitle.getText().toString()); - JumpUtils.startPicturePreviewActivity(getContext(), config.isWeChatStyle, bundle, - config.selectionMode == PictureConfig.SINGLE ? UCrop.REQUEST_CROP : UCrop.REQUEST_MULTI_CROP); - - overridePendingTransition(PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation, - R.anim.picture_anim_fade_in); - } - - /** - * Complete - */ - private void onComplete () { - List result = mAdapter.getSelectedData(); - int size = result.size(); - LocalMedia image = result.size() > 0 ? result.get(0) : null; - String mimeType = image != null ? image.getMimeType() : ""; - boolean isHasImage = PictureMimeType.isHasImage(mimeType); - if (config.isWithVideoImage) { - int videoSize = 0; - int imageSize = 0; - for (int i = 0; i < size; i++) { - LocalMedia media = result.get(i); - if (PictureMimeType.isHasVideo(media.getMimeType())) { - videoSize++; - } - else { - imageSize++; - } - } - if (config.selectionMode == PictureConfig.MULTIPLE) { - if (config.minSelectNum > 0) { - if (imageSize < config.minSelectNum) { - showPromptDialog(getString(R.string.picture_min_img_num, config.minSelectNum)); - return; - } - } - if (config.minVideoSelectNum > 0) { - if (videoSize < config.minVideoSelectNum) { - showPromptDialog(getString(R.string.picture_min_video_num, config.minVideoSelectNum)); - return; - } - } - } - } - else { - if (config.selectionMode == PictureConfig.MULTIPLE) { - if (PictureMimeType.isHasImage(mimeType) && config.minSelectNum > 0 && size < config.minSelectNum) { - String str = getString(R.string.picture_min_img_num, config.minSelectNum); - showPromptDialog(str); - return; - } - if (PictureMimeType.isHasVideo(mimeType) && config.minVideoSelectNum > 0 && size < config.minVideoSelectNum) { - String str = getString(R.string.picture_min_video_num, config.minVideoSelectNum); - showPromptDialog(str); - return; - } - } - } - - if (config.returnEmpty && size == 0) { - if (config.selectionMode == PictureConfig.MULTIPLE) { - if (config.minSelectNum > 0 && size < config.minSelectNum) { - String str = getString(R.string.picture_min_img_num, config.minSelectNum); - showPromptDialog(str); - return; - } - if (config.minVideoSelectNum > 0 && size < config.minVideoSelectNum) { - String str = getString(R.string.picture_min_video_num, config.minVideoSelectNum); - showPromptDialog(str); - return; - } - } - if (PictureSelectionConfig.listener != null) { - //noinspection unchecked - PictureSelectionConfig.listener.onResult(result); - } - else { - Intent intent = PictureSelector.putIntentResult(result); - setResult(RESULT_OK, intent); - } - exit(); - return; - } - if (config.isCheckOriginalImage) { - onResult(result); - return; - } - if (config.chooseMode == PictureMimeType.ofAll() && config.isWithVideoImage) { - bothMimeTypeWith(isHasImage, result); - } - else { - separateMimeTypeWith(isHasImage, result); - } - } - - /** - * They are different types of processing - * - * @param isHasImage has image - * @param images image list - */ - private void bothMimeTypeWith (boolean isHasImage, List images) { - LocalMedia image = images.size() > 0 ? images.get(0) : null; - if (image == null) { - return; - } - if (config.enableCrop) { - if (config.selectionMode == PictureConfig.SINGLE && isHasImage) { - config.originalPath = image.getPath(); - UCropManager.ofCrop(this, config.originalPath, image.getMimeType()); - } - else { - ArrayList cuts = new ArrayList<>(); - int count = images.size(); - int imageNum = 0; - for (int i = 0; i < count; i++) { - LocalMedia media = images.get(i); - if (media == null - || TextUtils.isEmpty(media.getPath())) { - continue; - } - if (PictureMimeType.isHasImage(media.getMimeType())) { - imageNum++; - } - CutInfo cutInfo = new CutInfo(); - cutInfo.setId(media.getId()); - cutInfo.setPath(media.getPath()); - cutInfo.setImageWidth(media.getWidth()); - cutInfo.setImageHeight(media.getHeight()); - cutInfo.setMimeType(media.getMimeType()); - cutInfo.setDuration(media.getDuration()); - cutInfo.setRealPath(media.getRealPath()); - cuts.add(cutInfo); - } - if (imageNum <= 0) { - onResult(images); - } - else { - UCropManager.ofCrop(this, cuts); - } - } - } - else if (config.isCompress) { - int size = images.size(); - int imageNum = 0; - for (int i = 0; i < size; i++) { - LocalMedia media = images.get(i); - if (PictureMimeType.isHasImage(media.getMimeType())) { - imageNum++; - break; - } - } - if (imageNum <= 0) { - onResult(images); - } - else { - compressImage(images); - } - } - else { - onResult(images); - } - } - - /** - * Same type of image or video processing logic - * - * @param isHasImage has image - * @param images image list - */ - private void separateMimeTypeWith (boolean isHasImage, List images) { - LocalMedia image = images.size() > 0 ? images.get(0) : null; - if (image == null) { - return; - } - if (config.enableCrop && isHasImage) { - if (config.selectionMode == PictureConfig.SINGLE) { - config.originalPath = image.getPath(); - UCropManager.ofCrop(this, config.originalPath, image.getMimeType()); - } - else { - ArrayList cuts = new ArrayList<>(); - int count = images.size(); - for (int i = 0; i < count; i++) { - LocalMedia media = images.get(i); - if (media == null - || TextUtils.isEmpty(media.getPath())) { - continue; - } - CutInfo cutInfo = new CutInfo(); - cutInfo.setId(media.getId()); - cutInfo.setPath(media.getPath()); - cutInfo.setImageWidth(media.getWidth()); - cutInfo.setImageHeight(media.getHeight()); - cutInfo.setMimeType(media.getMimeType()); - cutInfo.setDuration(media.getDuration()); - cutInfo.setRealPath(media.getRealPath()); - cuts.add(cutInfo); - } - UCropManager.ofCrop(this, cuts); - } - } - else if (config.isCompress - && isHasImage) { - compressImage(images); - } - else { - onResult(images); - } - } - - /** - * Play Audio - * - * @param path path - */ - private void AudioDialog (final String path) { - if (!isFinishing()) { - audioDialog = new PictureCustomDialog(getContext(), R.layout.picture_audio_dialog); - if (audioDialog.getWindow() != null) { - audioDialog.getWindow().setWindowAnimations(R.style.Picture_Theme_Dialog_AudioStyle); - } - mTvMusicStatus = audioDialog.findViewById(R.id.tv_musicStatus); - mTvMusicTime = audioDialog.findViewById(R.id.tv_musicTime); - musicSeekBar = audioDialog.findViewById(R.id.musicSeekBar); - mTvMusicTotal = audioDialog.findViewById(R.id.tv_musicTotal); - mTvPlayPause = audioDialog.findViewById(R.id.tv_PlayPause); - mTvStop = audioDialog.findViewById(R.id.tv_Stop); - mTvQuit = audioDialog.findViewById(R.id.tv_Quit); - if (mHandler != null) { - mHandler.postDelayed(() -> initPlayer(path), 30); - } - mTvPlayPause.setOnClickListener(new AudioOnClick(path)); - mTvStop.setOnClickListener(new AudioOnClick(path)); - mTvQuit.setOnClickListener(new AudioOnClick(path)); - musicSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - mediaPlayer.seekTo(progress); - } - } - - @Override - public void onStartTrackingTouch (SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch (SeekBar seekBar) { - } - }); - audioDialog.setOnDismissListener(dialog -> { - if (mHandler != null) { - mHandler.removeCallbacks(mRunnable); - } - new Handler().postDelayed(() -> stop(path), 30); - try { - if (audioDialog != null - && audioDialog.isShowing()) { - audioDialog.dismiss(); - } - } - catch (Exception e) { - e.printStackTrace(); - } - }); - if (mHandler != null) { - mHandler.post(mRunnable); - } - audioDialog.show(); - } - } - - /** - * init Player - * - * @param path path - */ - private void initPlayer (String path) { - mediaPlayer = new MediaPlayer(); - try { - mediaPlayer.setDataSource(path); - mediaPlayer.prepare(); - mediaPlayer.setLooping(true); - playAudio(); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Play Audio - */ - private void playAudio () { - if (mediaPlayer != null) { - musicSeekBar.setProgress(mediaPlayer.getCurrentPosition()); - musicSeekBar.setMax(mediaPlayer.getDuration()); - } - String ppStr = mTvPlayPause.getText().toString(); - if (ppStr.equals(getString(R.string.picture_play_audio))) { - mTvPlayPause.setText(getString(R.string.picture_pause_audio)); - mTvMusicStatus.setText(getString(R.string.picture_play_audio)); - } - else { - mTvPlayPause.setText(getString(R.string.picture_play_audio)); - mTvMusicStatus.setText(getString(R.string.picture_pause_audio)); - } - playOrPause(); - if (!isPlayAudio) { - if (mHandler != null) { - mHandler.post(mRunnable); - } - isPlayAudio = true; - } - } - - /** - * Audio Stop - * - * @param path path - */ - public void stop (String path) { - if (mediaPlayer != null) { - try { - mediaPlayer.stop(); - mediaPlayer.reset(); - mediaPlayer.setDataSource(path); - mediaPlayer.prepare(); - mediaPlayer.seekTo(0); - } - catch (Exception e) { - e.printStackTrace(); - } - } - } - - /** - * Audio Pause - */ - public void playOrPause () { - try { - if (mediaPlayer != null) { - if (mediaPlayer.isPlaying()) { - mediaPlayer.pause(); - } - else { - mediaPlayer.start(); - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void onItemClick (int position, boolean isCameraFolder, long bucketId, String - folderName, List data) { - boolean camera = config.isCamera && isCameraFolder; - mAdapter.setShowCamera(camera); - mTvPictureTitle.setText(folderName); - long currentBucketId = ValueOf.toLong(mTvPictureTitle.getTag(R.id.view_tag)); - mTvPictureTitle.setTag(R.id.view_count_tag, folderWindow.getFolder(position) != null - ? folderWindow.getFolder(position).getImageNum() : 0); - if (config.isPageStrategy) { - if (currentBucketId != bucketId) { - setLastCacheFolderData(); - boolean isCurrentCacheFolderData = isCurrentCacheFolderData(position); - if (!isCurrentCacheFolderData) { - mPage = 1; - showPleaseDialog(); - LocalMediaPageLoader.getInstance(getContext()).loadPageMediaData(bucketId, mPage, - (result, currentPage, isHasMore) -> { - this.isHasMore = isHasMore; - if (!isFinishing()) { - if (result.size() == 0) { - mAdapter.clear(); - } - mAdapter.bindData(result); - mRecyclerView.onScrolled(0, 0); - mRecyclerView.smoothScrollToPosition(0); - dismissDialog(); - } - }); - } - } - } - else { - mAdapter.bindData(data); - mRecyclerView.smoothScrollToPosition(0); - } - mTvPictureTitle.setTag(R.id.view_tag, bucketId); - folderWindow.dismiss(); - } - - /** - * Before switching directories, set the current directory cache - */ - private void setLastCacheFolderData () { - int oldPosition = ValueOf.toInt(mTvPictureTitle.getTag(R.id.view_index_tag)); - LocalMediaFolder lastFolder = folderWindow.getFolder(oldPosition); - lastFolder.setData(mAdapter.getData()); - lastFolder.setCurrentDataPage(mPage); - lastFolder.setHasMore(isHasMore); - } - - /** - * Does the current album have a cache - * - * @param position position - */ - private boolean isCurrentCacheFolderData (int position) { - mTvPictureTitle.setTag(R.id.view_index_tag, position); - LocalMediaFolder currentFolder = folderWindow.getFolder(position); - if (currentFolder != null - && currentFolder.getData() != null - && currentFolder.getData().size() > 0) { - mAdapter.bindData(currentFolder.getData()); - mPage = currentFolder.getCurrentDataPage(); - isHasMore = currentFolder.isHasMore(); - mRecyclerView.smoothScrollToPosition(0); - - return true; - } - return false; - } - - @Override - public void onTakePhoto () { - // Check the permissions - if (PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA)) { - if (PermissionChecker - .checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && - PermissionChecker - .checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - startCamera(); - } - else { - PermissionChecker.requestPermissions(this, new String[]{ - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE}, PictureConfig.APPLY_CAMERA_STORAGE_PERMISSIONS_CODE); - } - } - else { - PermissionChecker - .requestPermissions(this, - new String[]{Manifest.permission.CAMERA}, PictureConfig.APPLY_CAMERA_PERMISSIONS_CODE); - } - } - - @Override - public void onChange (List selectData) { - changeImageNumber(selectData); - } - - @Override - public void onPictureClick (LocalMedia media, int position) { - if (config.selectionMode == PictureConfig.SINGLE && config.isSingleDirectReturn) { - List list = new ArrayList<>(); - list.add(media); - if (config.enableCrop && PictureMimeType.isHasImage(media.getMimeType()) && !config.isCheckOriginalImage) { - mAdapter.bindSelectData(list); - UCropManager.ofCrop(this, media.getPath(), media.getMimeType()); - } - else { - handlerResult(list); - } - } - else { - List data = mAdapter.getData(); - startPreview(data, position); - } - } - - /** - * preview image and video - * - * @param previewData preview data - * @param position position - */ - public void startPreview (List previewData, int position) { - LocalMedia media = previewData.get(position); - String mimeType = media.getMimeType(); - Bundle bundle = new Bundle(); - List result = new ArrayList<>(); - if (PictureMimeType.isHasVideo(mimeType)) { - // video - if (config.selectionMode == PictureConfig.SINGLE && !config.enPreviewVideo) { - result.add(media); - onResult(result); - } - else { - if (PictureSelectionConfig.customVideoPlayCallback != null) { - PictureSelectionConfig.customVideoPlayCallback.startPlayVideo(media); - } - else { - bundle.putParcelable(PictureConfig.EXTRA_MEDIA_KEY, media); - JumpUtils.startPictureVideoPlayActivity(getContext(), bundle, PictureConfig.PREVIEW_VIDEO_CODE); - } - } - } - else if (PictureMimeType.isHasAudio(mimeType)) { - // audio - if (config.selectionMode == PictureConfig.SINGLE) { - result.add(media); - onResult(result); - } - else { - AudioDialog(media.getRealPath()); - } - } - else { - // image - if (PictureSelectionConfig.onCustomImagePreviewCallback != null) { - PictureSelectionConfig.onCustomImagePreviewCallback.onCustomPreviewCallback(getContext(), previewData, position); - return; - } - List selectedData = mAdapter.getSelectedData(); - ImagesObservable.getInstance().savePreviewMediaData(new ArrayList<>(previewData)); - bundle.putParcelableArrayList(PictureConfig.EXTRA_SELECT_LIST, (ArrayList) selectedData); - bundle.putInt(PictureConfig.EXTRA_POSITION, position); - bundle.putBoolean(PictureConfig.EXTRA_CHANGE_ORIGINAL, config.isCheckOriginalImage); - bundle.putBoolean(PictureConfig.EXTRA_SHOW_CAMERA, mAdapter.isShowCamera()); - bundle.putLong(PictureConfig.EXTRA_BUCKET_ID, ValueOf.toLong(mTvPictureTitle.getTag(R.id.view_tag))); - bundle.putInt(PictureConfig.EXTRA_PAGE, mPage); - bundle.putParcelable(PictureConfig.EXTRA_CONFIG, config); - bundle.putInt(PictureConfig.EXTRA_DATA_COUNT, ValueOf.toInt(mTvPictureTitle.getTag(R.id.view_count_tag))); - bundle.putString(PictureConfig.EXTRA_IS_CURRENT_DIRECTORY, mTvPictureTitle.getText().toString()); - JumpUtils.startPicturePreviewActivity(getContext(), config.isWeChatStyle, bundle, - config.selectionMode == PictureConfig.SINGLE ? UCrop.REQUEST_CROP : UCrop.REQUEST_MULTI_CROP); - overridePendingTransition(PictureSelectionConfig.windowAnimationStyle.activityPreviewEnterAnimation, R.anim.picture_anim_fade_in); - } - } - - /** - * change image selector state - * - * @param selectData - */ - protected void changeImageNumber (List selectData) { - initCompleteText(selectData.size()); - } - - @Override - protected void onActivityResult (int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - switch (requestCode) { - case PictureConfig.PREVIEW_VIDEO_CODE: - if (data != null) { - List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); - if (list != null && list.size() > 0) { - onResult(list); - } - } - break; - case UCrop.REQUEST_CROP: - singleCropHandleResult(data); - break; - case UCrop.REQUEST_MULTI_CROP: - multiCropHandleResult(data); - break; - case PictureConfig.REQUEST_CAMERA: - dispatchHandleCamera(data); - break; - default: - break; - } - } - else if (resultCode == RESULT_CANCELED) { - previewCallback(data); - } - else if (resultCode == UCrop.RESULT_ERROR) { - if (data != null) { - Throwable throwable = (Throwable) data.getSerializableExtra(UCrop.EXTRA_ERROR); - if (throwable != null) { - ToastUtils.s(getContext(), throwable.getMessage()); - } - } - } - } - - /** - * Preview interface callback processing - * - * @param data data - */ - private void previewCallback (Intent data) { - if (data == null) { - return; - } - List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); - if (mAdapter != null && list != null) { - boolean isCompleteOrSelected = data.getBooleanExtra(PictureConfig.EXTRA_COMPLETE_SELECTED, false); - if (isCompleteOrSelected) { - onChangeData(list); - if (config.isWithVideoImage) { - int size = list.size(); - int imageSize = 0; - for (int i = 0; i < size; i++) { - LocalMedia media = list.get(i); - if (PictureMimeType.isHasImage(media.getMimeType())) { - imageSize++; - break; - } - } - if (imageSize <= 0 || !config.isCompress || config.isCheckOriginalImage) { - onResult(list); - } - else { - compressImage(list); - } - } - else { - // Determine if the resource is of the same type - String mimeType = list.size() > 0 ? list.get(0).getMimeType() : ""; - if (config.isCompress && PictureMimeType.isHasImage(mimeType) - && !config.isCheckOriginalImage) { - compressImage(list); - } - else { - onResult(list); - } - } - } - else { - // Resources are selected on the preview page - isStartAnimation = true; - } - mAdapter.bindSelectData(list); - mAdapter.notifyDataSetChanged(); - } - } - - /** - * Preview the callback - * - * @param list list - */ - protected void onChangeData (List list) { - - } - - /** - * singleDirectReturn - * - * @param mimeType mimeType - */ - private void singleDirectReturnCameraHandleResult (String mimeType) { - boolean isHasImage = PictureMimeType.isHasImage(mimeType); - if (config.enableCrop && isHasImage) { - config.originalPath = config.cameraPath; - UCropManager.ofCrop(this, config.originalPath, mimeType); - } - else if (config.isCompress && isHasImage) { - List selectedImages = mAdapter.getSelectedData(); - compressImage(selectedImages); - } - else { - onResult(mAdapter.getSelectedData()); - } - } - - /** - * Camera Handle - * - * @param intent intent - */ - private void dispatchHandleCamera (Intent intent) { - // If PictureSelectionConfig is not empty, synchronize it - PictureSelectionConfig selectionConfig = intent != null ? intent.getParcelableExtra(PictureConfig.EXTRA_CONFIG) : null; - if (selectionConfig != null) { - config = selectionConfig; - } - //noinspection deprecation - boolean isAudio = config.chooseMode == PictureMimeType.ofAudio(); - config.cameraPath = isAudio ? getAudioPath(intent) : config.cameraPath; - if (TextUtils.isEmpty(config.cameraPath)) { - return; - } - showPleaseDialog(); - PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask() { - - @Override - public LocalMedia doInBackground () { - LocalMedia media = new LocalMedia(); - String mimeType = isAudio ? PictureMimeType.MIME_TYPE_AUDIO : ""; - long duration = 0; - if (!isAudio) { - if (PictureMimeType.isContent(config.cameraPath)) { - // content: Processing rules - String path = PictureFileUtils.getPath(getContext(), Uri.parse(config.cameraPath)); - if (path != null && !TextUtils.isEmpty(path)) { - File cameraFile = new File(path); - mimeType = PictureMimeType.getMimeType(config.cameraMimeType); - media.setSize(cameraFile.length()); - media.setFileName(cameraFile.getName()); - } - if (PictureMimeType.isHasImage(mimeType)) { - int[] newSize = MediaUtils.getImageSizeForUrlToAndroidQ(getContext(), config.cameraPath); - media.setWidth(newSize[0]); - media.setHeight(newSize[1]); - } - else if (PictureMimeType.isHasVideo(mimeType)) { - MediaUtils.getVideoSizeForUri(getContext(), Uri.parse(config.cameraPath), media); - duration = MediaUtils.extractDuration(getContext(), SdkVersionUtils.checkedAndroid_Q(), config.cameraPath); - } - int lastIndexOf = config.cameraPath.lastIndexOf("/") + 1; - media.setId(lastIndexOf > 0 ? ValueOf.toLong(config.cameraPath.substring(lastIndexOf)) : -1); - media.setRealPath(path); - // Custom photo has been in the application sandbox into the file - String mediaPath = intent != null ? intent.getStringExtra(PictureConfig.EXTRA_MEDIA_PATH) : null; - media.setAndroidQToPath(mediaPath); - } - else { - File cameraFile = new File(config.cameraPath); - mimeType = PictureMimeType.getMimeType(config.cameraMimeType); - media.setSize(cameraFile.length()); - media.setFileName(cameraFile.getName()); - if (PictureMimeType.isHasImage(mimeType)) { - int degree = PictureFileUtils.readPictureDegree(getContext(), config.cameraPath); - BitmapUtils.rotateImage(degree, config.cameraPath); - int[] newSize = MediaUtils.getImageSizeForUrl(config.cameraPath); - media.setWidth(newSize[0]); - media.setHeight(newSize[1]); - } - else if (PictureMimeType.isHasVideo(mimeType)) { - int[] newSize = MediaUtils.getVideoSizeForUrl(config.cameraPath); - duration = MediaUtils.extractDuration(getContext(), SdkVersionUtils.checkedAndroid_Q(), config.cameraPath); - media.setWidth(newSize[0]); - media.setHeight(newSize[1]); - } - // Taking a photo generates a temporary id - media.setId(System.currentTimeMillis()); - } - media.setPath(config.cameraPath); - media.setDuration(duration); - media.setMimeType(mimeType); - if (SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isHasVideo(media.getMimeType())) { - media.setParentFolderName(Environment.DIRECTORY_MOVIES); - } - else { - media.setParentFolderName(PictureMimeType.CAMERA); - } - media.setChooseModel(config.chooseMode); - long bucketId = MediaUtils.getCameraFirstBucketId(getContext()); - media.setBucketId(bucketId); - // The width and height of the image are reversed if there is rotation information - MediaUtils.setOrientationSynchronous(getContext(), media, config.isAndroidQChangeWH, config.isAndroidQChangeVideoWH); - } - return media; - } - - @Override - public void onSuccess (LocalMedia result) { - dismissDialog(); - // Refresh the system library - if (!SdkVersionUtils.checkedAndroid_Q()) { - if (config.isFallbackVersion3) { - new PictureMediaScannerConnection(getContext(), config.cameraPath); - } - else { - sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(config.cameraPath)))); - } - } - // add data Adapter - notifyAdapterData(result); - // Solve some phone using Camera, DCIM will produce repetitive problems - if (!SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isHasImage(result.getMimeType())) { - int lastImageId = MediaUtils.getDCIMLastImageId(getContext()); - if (lastImageId != -1) { - MediaUtils.removeMedia(getContext(), lastImageId); - } - } - } - }); - - } - - /** - * Update Adapter Data - * - * @param media media - */ - private void notifyAdapterData (LocalMedia media) { - if (mAdapter != null) { - boolean isAddSameImp = isAddSameImp(folderWindow.getFolder(0) != null ? folderWindow.getFolder(0).getImageNum() : 0); - if (!isAddSameImp) { - mAdapter.getData().add(0, media); - mOpenCameraCount++; - } - if (checkVideoLegitimacy(media)) { - if (config.selectionMode == PictureConfig.SINGLE) { - dispatchHandleSingle(media); - } - else { - dispatchHandleMultiple(media); - } - } - mAdapter.notifyItemInserted(config.isCamera ? 1 : 0); - mAdapter.notifyItemRangeChanged(config.isCamera ? 1 : 0, mAdapter.getSize()); - // Solve the problem that some mobile phones do not refresh the system library timely after using Camera - if (config.isPageStrategy) { - manualSaveFolderForPageModel(media); - } - else { - manualSaveFolder(media); - } - mTvEmpty.setVisibility(mAdapter.getSize() > 0 || config.isSingleDirectReturn ? View.GONE : View.VISIBLE); - // update all count - if (folderWindow.getFolder(0) != null) { - mTvPictureTitle.setTag(R.id.view_count_tag, folderWindow.getFolder(0).getImageNum()); - } - allFolderSize = 0; - } - } - - /** - * After using Camera, MultiSelect mode handles the logic - * - * @param media media - */ - private void dispatchHandleMultiple (LocalMedia media) { - List selectedData = mAdapter.getSelectedData(); - int count = selectedData.size(); - String oldMimeType = count > 0 ? selectedData.get(0).getMimeType() : ""; - boolean mimeTypeSame = PictureMimeType.isMimeTypeSame(oldMimeType, media.getMimeType()); - if (config.isWithVideoImage) { - int videoSize = 0; - for (int i = 0; i < count; i++) { - LocalMedia item = selectedData.get(i); - if (PictureMimeType.isHasVideo(item.getMimeType())) { - videoSize++; - } - } - if (PictureMimeType.isHasVideo(media.getMimeType())) { - if (config.maxVideoSelectNum <= 0) { - showPromptDialog(getString(R.string.picture_rule)); - } - else { - if (videoSize >= config.maxVideoSelectNum) { - showPromptDialog(getString(R.string.picture_message_max_num, config.maxVideoSelectNum)); - } - else { - selectedData.add(0, media); - mAdapter.bindSelectData(selectedData); - } - } - } - else { - if (selectedData.size() < config.maxSelectNum) { - selectedData.add(0, media); - mAdapter.bindSelectData(selectedData); - } - else { - showPromptDialog(StringUtils.getMsg(getContext(), media.getMimeType(), config.maxSelectNum)); - } - } - - } - else { - if (PictureMimeType.isHasVideo(oldMimeType) && config.maxVideoSelectNum > 0) { - if (count < config.maxVideoSelectNum) { - if (mimeTypeSame || count == 0) { - if (selectedData.size() < config.maxVideoSelectNum) { - selectedData.add(0, media); - mAdapter.bindSelectData(selectedData); - } - } - } - else { - showPromptDialog(StringUtils.getMsg(getContext(), oldMimeType, - config.maxVideoSelectNum)); - } - } - else { - if (count < config.maxSelectNum) { - if (mimeTypeSame || count == 0) { - selectedData.add(0, media); - mAdapter.bindSelectData(selectedData); - } - } - else { - showPromptDialog(StringUtils.getMsg(getContext(), oldMimeType, config.maxSelectNum)); - } - } - } - } - - /** - * After using the camera, the radio mode handles the logic - * - * @param media media - */ - private void dispatchHandleSingle (LocalMedia media) { - if (config.isSingleDirectReturn) { - List selectedData = mAdapter.getSelectedData(); - selectedData.add(media); - mAdapter.bindSelectData(selectedData); - singleDirectReturnCameraHandleResult(media.getMimeType()); - } - else { - List selectedData = mAdapter.getSelectedData(); - String mimeType = selectedData.size() > 0 ? selectedData.get(0).getMimeType() : ""; - boolean mimeTypeSame = PictureMimeType.isMimeTypeSame(mimeType, media.getMimeType()); - if (mimeTypeSame || selectedData.size() == 0) { - singleRadioMediaImage(); - selectedData.add(media); - mAdapter.bindSelectData(selectedData); - } - } - } - - /** - * Verify the validity of the video - * - * @param media media - * @return check video - */ - private boolean checkVideoLegitimacy (LocalMedia media) { - boolean isEnterNext = true; - if (PictureMimeType.isHasVideo(media.getMimeType())) { - if (config.videoMinSecond > 0 && config.videoMaxSecond > 0) { - // The user sets the minimum and maximum video length to determine whether the video is within the interval - if (media.getDuration() < config.videoMinSecond || media.getDuration() > config.videoMaxSecond) { - isEnterNext = false; - showPromptDialog(getString(R.string.picture_choose_limit_seconds, config.videoMinSecond / 1000, config.videoMaxSecond / 1000)); - } - } - else if (config.videoMinSecond > 0) { - // The user has only set a minimum video length limit - if (media.getDuration() < config.videoMinSecond) { - isEnterNext = false; - showPromptDialog(getString(R.string.picture_choose_min_seconds, config.videoMinSecond / 1000)); - } - } - else if (config.videoMaxSecond > 0) { - // Only the maximum length of video is set - if (media.getDuration() > config.videoMaxSecond) { - isEnterNext = false; - showPromptDialog(getString(R.string.picture_choose_max_seconds, config.videoMaxSecond / 1000)); - } - } - } - return isEnterNext; - } - - /** - * Single picture clipping callback - * - * @param data data - */ - private void singleCropHandleResult (Intent data) { - if (data == null) { - return; - } - Uri resultUri = UCrop.getOutput(data); - if (resultUri == null) { - return; - } - List result = new ArrayList<>(); - String cutPath = resultUri.getPath(); - if (mAdapter != null) { - List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); - if (list != null) { - mAdapter.bindSelectData(list); - mAdapter.notifyDataSetChanged(); - } - List mediaList = mAdapter.getSelectedData(); - LocalMedia media = mediaList != null && mediaList.size() > 0 ? mediaList.get(0) : null; - if (media != null) { - config.originalPath = media.getPath(); - media.setCutPath(cutPath); - media.setChooseModel(config.chooseMode); - boolean isCutPathEmpty = !TextUtils.isEmpty(cutPath); - if (SdkVersionUtils.checkedAndroid_Q() - && PictureMimeType.isContent(media.getPath())) { - if (isCutPathEmpty) { - media.setSize(new File(cutPath).length()); - } - else { - media.setSize(!TextUtils.isEmpty(media.getRealPath()) ? new File(media.getRealPath()).length() : 0); - } - media.setAndroidQToPath(cutPath); - } - else { - media.setSize(isCutPathEmpty ? new File(cutPath).length() : 0); - } - media.setCut(isCutPathEmpty); - result.add(media); - handlerResult(result); - } - else { - // Preview screen selects the image and crop the callback - media = list != null && list.size() > 0 ? list.get(0) : null; - if (media != null) { - config.originalPath = media.getPath(); - media.setCutPath(cutPath); - media.setChooseModel(config.chooseMode); - boolean isCutPathEmpty = !TextUtils.isEmpty(cutPath); - if (SdkVersionUtils.checkedAndroid_Q() - && PictureMimeType.isContent(media.getPath())) { - if (isCutPathEmpty) { - media.setSize(new File(cutPath).length()); - } - else { - media.setSize(!TextUtils.isEmpty(media.getRealPath()) ? new File(media.getRealPath()).length() : 0); - } - media.setAndroidQToPath(cutPath); - } - else { - media.setSize(isCutPathEmpty ? new File(cutPath).length() : 0); - } - media.setCut(isCutPathEmpty); - result.add(media); - handlerResult(result); - } - } - } - } - - /** - * Multiple picture crop - * - * @param data data - */ - protected void multiCropHandleResult (Intent data) { - if (data == null) { - return; - } - List mCuts = UCrop.getMultipleOutput(data); - if (mCuts == null || mCuts.size() == 0) { - return; - } - int size = mCuts.size(); - boolean isAndroidQ = SdkVersionUtils.checkedAndroid_Q(); - List list = data.getParcelableArrayListExtra(PictureConfig.EXTRA_SELECT_LIST); - if (list != null) { - mAdapter.bindSelectData(list); - mAdapter.notifyDataSetChanged(); - } - int oldSize = mAdapter != null ? mAdapter.getSelectedData().size() : 0; - if (oldSize == size) { - List result = mAdapter.getSelectedData(); - for (int i = 0; i < size; i++) { - CutInfo c = mCuts.get(i); - LocalMedia media = result.get(i); - media.setCut(!TextUtils.isEmpty(c.getCutPath())); - media.setPath(c.getPath()); - media.setMimeType(c.getMimeType()); - media.setCutPath(c.getCutPath()); - media.setWidth(c.getImageWidth()); - media.setHeight(c.getImageHeight()); - media.setAndroidQToPath(isAndroidQ ? c.getCutPath() : media.getAndroidQToPath()); - media.setSize(!TextUtils.isEmpty(c.getCutPath()) ? new File(c.getCutPath()).length() : media.getSize()); - } - handlerResult(result); - } - else { - // Fault-tolerant processing - List result = new ArrayList<>(); - for (int i = 0; i < size; i++) { - CutInfo c = mCuts.get(i); - LocalMedia media = new LocalMedia(); - media.setId(c.getId()); - media.setCut(!TextUtils.isEmpty(c.getCutPath())); - media.setPath(c.getPath()); - media.setCutPath(c.getCutPath()); - media.setMimeType(c.getMimeType()); - media.setWidth(c.getImageWidth()); - media.setHeight(c.getImageHeight()); - media.setDuration(c.getDuration()); - media.setChooseModel(config.chooseMode); - media.setAndroidQToPath(isAndroidQ ? c.getCutPath() : c.getAndroidQToPath()); - if (!TextUtils.isEmpty(c.getCutPath())) { - media.setSize(new File(c.getCutPath()).length()); - } - else { - if (SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isContent(c.getPath())) { - media.setSize(!TextUtils.isEmpty(c.getRealPath()) ? new File(c.getRealPath()).length() : 0); - } - else { - media.setSize(new File(c.getPath()).length()); - } - } - result.add(media); - } - handlerResult(result); - } - } - - /** - * Just make sure you pick one - */ - private void singleRadioMediaImage () { - List selectData = mAdapter.getSelectedData(); - if (selectData != null - && selectData.size() > 0) { - LocalMedia media = selectData.get(0); - int position = media.getPosition(); - selectData.clear(); - mAdapter.notifyItemChanged(position); - } - } - - /** - * Manually add the photo to the list of photos and set it to select-paging mode - * - * @param media media - */ - private void manualSaveFolderForPageModel (LocalMedia media) { - if (media == null) { - return; - } - int count = folderWindow.getFolderData().size(); - LocalMediaFolder allFolder = count > 0 ? folderWindow.getFolderData().get(0) : new LocalMediaFolder(); - if (allFolder != null) { - int totalNum = allFolder.getImageNum(); - allFolder.setFirstImagePath(media.getPath()); - allFolder.setImageNum(isAddSameImp(totalNum) ? allFolder.getImageNum() : allFolder.getImageNum() + 1); - // Create All folder - if (count == 0) { - //noinspection deprecation - allFolder.setName(config.chooseMode == PictureMimeType.ofAudio() ? getString(R.string.picture_all_audio) : getString(R.string.picture_camera_roll)); - allFolder.setOfAllType(config.chooseMode); - allFolder.setCameraFolder(true); - allFolder.setChecked(true); - allFolder.setBucketId(-1); - folderWindow.getFolderData().add(0, allFolder); - // Create Camera - LocalMediaFolder cameraFolder = new LocalMediaFolder(); - cameraFolder.setName(media.getParentFolderName()); - cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); - cameraFolder.setFirstImagePath(media.getPath()); - cameraFolder.setBucketId(media.getBucketId()); - folderWindow.getFolderData().add(folderWindow.getFolderData().size(), cameraFolder); - } - else { - boolean isCamera = false; - String newFolder = SdkVersionUtils.checkedAndroid_Q() && PictureMimeType.isHasVideo(media.getMimeType()) - ? Environment.DIRECTORY_MOVIES : PictureMimeType.CAMERA; - for (int i = 0; i < count; i++) { - LocalMediaFolder cameraFolder = folderWindow.getFolderData().get(i); - if (!TextUtils.isEmpty(cameraFolder.getName()) && cameraFolder.getName().startsWith(newFolder)) { - media.setBucketId(cameraFolder.getBucketId()); - cameraFolder.setFirstImagePath(config.cameraPath); - cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); - if (cameraFolder.getData() != null && cameraFolder.getData().size() > 0) { - cameraFolder.getData().add(0, media); - } - isCamera = true; - break; - } - } - if (!isCamera) { - // There is no Camera folder locally. Create one - LocalMediaFolder cameraFolder = new LocalMediaFolder(); - cameraFolder.setName(media.getParentFolderName()); - cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); - cameraFolder.setFirstImagePath(media.getPath()); - cameraFolder.setBucketId(media.getBucketId()); - folderWindow.getFolderData().add(cameraFolder); - sortFolder(folderWindow.getFolderData()); - } - } - folderWindow.bindFolder(folderWindow.getFolderData()); - } - } - - /** - * Manually add the photo to the list of photos and set it to select - * - * @param media media - */ - private void manualSaveFolder (LocalMedia media) { - try { - boolean isEmpty = folderWindow.isEmpty(); - int totalNum = folderWindow.getFolder(0) != null ? folderWindow.getFolder(0).getImageNum() : 0; - LocalMediaFolder allFolder; - if (isEmpty) { - // All Folder - createNewFolder(folderWindow.getFolderData()); - allFolder = folderWindow.getFolderData().size() > 0 ? folderWindow.getFolderData().get(0) : null; - if (allFolder == null) { - allFolder = new LocalMediaFolder(); - folderWindow.getFolderData().add(0, allFolder); - } - } - else { - // All Folder - allFolder = folderWindow.getFolderData().get(0); - } - allFolder.setFirstImagePath(media.getPath()); - allFolder.setData(mAdapter.getData()); - allFolder.setBucketId(-1); - allFolder.setImageNum(isAddSameImp(totalNum) ? allFolder.getImageNum() : allFolder.getImageNum() + 1); - - // Camera - LocalMediaFolder cameraFolder = getImageFolder(media.getPath(), media.getRealPath(), folderWindow.getFolderData()); - if (cameraFolder != null) { - cameraFolder.setImageNum(isAddSameImp(totalNum) ? cameraFolder.getImageNum() : cameraFolder.getImageNum() + 1); - if (!isAddSameImp(totalNum)) { - cameraFolder.getData().add(0, media); - } - cameraFolder.setBucketId(media.getBucketId()); - cameraFolder.setFirstImagePath(config.cameraPath); - } - folderWindow.bindFolder(folderWindow.getFolderData()); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Is the quantity consistent - * - * @return is add same - */ - private boolean isAddSameImp (int totalNum) { - if (totalNum == 0) { - return false; - } - return allFolderSize > 0 && allFolderSize < totalNum; - } - - /** - * Update Folder - * - * @param imageFolders image folder list - */ - private void updateMediaFolder (List imageFolders, LocalMedia media) { - File imageFile = new File(media.getRealPath()); - File folderFile = imageFile.getParentFile(); - if (folderFile == null) { - return; - } - int size = imageFolders.size(); - for (int i = 0; i < size; i++) { - LocalMediaFolder folder = imageFolders.get(i); - String name = folder.getName(); - if (TextUtils.isEmpty(name)) { - continue; - } - if (name.equals(folderFile.getName())) { - folder.setFirstImagePath(config.cameraPath); - folder.setImageNum(folder.getImageNum() + 1); - folder.setCheckedNum(1); - folder.getData().add(0, media); - break; - } - } - } - - @Override - public void onBackPressed () { - if (SdkVersionUtils.checkedAndroid_Q()) { - finishAfterTransition(); - } - else { - super.onBackPressed(); - } - if (PictureSelectionConfig.listener != null) { - PictureSelectionConfig.listener.onCancel(); - } - exit(); - } - - @Override - protected void onDestroy () { - super.onDestroy(); - if (animation != null) { - animation.cancel(); - animation = null; - } - if (mediaPlayer != null && mHandler != null) { - mHandler.removeCallbacks(mRunnable); - mediaPlayer.release(); - mediaPlayer = null; - } - } - - @Override - public void onItemClick (View view, int position) { - switch (position) { - case PhotoItemSelectedDialog.IMAGE_CAMERA: - if (PictureSelectionConfig.onCustomCameraInterfaceListener != null) { - PictureSelectionConfig.onCustomCameraInterfaceListener.onCameraClick(getContext(), config, PictureConfig.TYPE_IMAGE); - config.cameraMimeType = PictureMimeType.ofImage(); - } - else { - startOpenCamera(); - } - break; - case PhotoItemSelectedDialog.VIDEO_CAMERA: - if (PictureSelectionConfig.onCustomCameraInterfaceListener != null) { - PictureSelectionConfig.onCustomCameraInterfaceListener.onCameraClick(getContext(), config, PictureConfig.TYPE_IMAGE); - config.cameraMimeType = PictureMimeType.ofVideo(); - } - else { - startOpenCameraVideo(); - } - break; - default: - break; - } - } - - @Override - public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - switch (requestCode) { - case PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE: - // Store Permissions - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - readLocalMedia(); - } - else { - showPermissionsDialog(false, getString(R.string.picture_jurisdiction)); - } - break; - case PictureConfig.APPLY_CAMERA_PERMISSIONS_CODE: - // Camera Permissions - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - onTakePhoto(); - } - else { - showPermissionsDialog(true, getString(R.string.picture_camera)); - } - break; - case PictureConfig.APPLY_CAMERA_STORAGE_PERMISSIONS_CODE: - // Using the camera, retrieve the storage permission - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - startCamera(); - } - else { - showPermissionsDialog(false, getString(R.string.picture_jurisdiction)); - } - break; - case PictureConfig.APPLY_RECORD_AUDIO_PERMISSIONS_CODE: - // Recording Permissions - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - startCustomCamera(); - } - else { - showPermissionsDialog(false, getString(R.string.picture_audio)); - } - break; - } - } - - @Override - protected void showPermissionsDialog (boolean isCamera, String errorMsg) { - if (isFinishing()) { - return; - } - final PictureCustomDialog dialog = - new PictureCustomDialog(getContext(), R.layout.picture_wind_base_dialog); - dialog.setCancelable(false); - dialog.setCanceledOnTouchOutside(false); - Button btn_cancel = dialog.findViewById(R.id.btn_cancel); - Button btn_commit = dialog.findViewById(R.id.btn_commit); - btn_commit.setText(getString(R.string.picture_go_setting)); - TextView tvTitle = dialog.findViewById(R.id.tvTitle); - TextView tv_content = dialog.findViewById(R.id.tv_content); - tvTitle.setText(getString(R.string.picture_prompt)); - tv_content.setText(errorMsg); - btn_cancel.setOnClickListener(v -> { - if (!isFinishing()) { - dialog.dismiss(); - } - if (!isCamera) { - if (PictureSelectionConfig.listener != null) { - PictureSelectionConfig.listener.onCancel(); - } - exit(); - } - }); - btn_commit.setOnClickListener(v -> { - if (!isFinishing()) { - dialog.dismiss(); - } - PermissionChecker.launchAppDetailsSettings(getContext()); - isEnterSetting = true; - }); - dialog.show(); - } - - /** - * set Data Null - * - * @param msg msg - */ - private void showDataNull (String msg, int topErrorResId) { - if (mTvEmpty.getVisibility() == View.GONE || mTvEmpty.getVisibility() == View.INVISIBLE) { - mTvEmpty.setCompoundDrawablesRelativeWithIntrinsicBounds(0, topErrorResId, 0, 0); - mTvEmpty.setText(msg); - mTvEmpty.setVisibility(View.VISIBLE); - } - } - - /** - * hidden - */ - private void hideDataNull () { - if (mTvEmpty.getVisibility() == View.VISIBLE) { - mTvEmpty.setVisibility(View.GONE); - } - } - - /** - * Audio Click - */ - public class AudioOnClick implements View.OnClickListener { - public AudioOnClick (String path) { - super(); - this.path = path; - } - - @Override - public void onClick (View v) { - int id = v.getId(); - if (id == R.id.tv_PlayPause) { - playAudio(); - } - if (id == R.id.tv_Stop) { - mTvMusicStatus.setText(getString(R.string.picture_stop_audio)); - mTvPlayPause.setText(getString(R.string.picture_play_audio)); - stop(path); - } - if (id == R.id.tv_Quit) { - if (mHandler != null) { - mHandler.postDelayed(() -> stop(path), 30); - try { - if (audioDialog != null - && audioDialog.isShowing()) { - audioDialog.dismiss(); - } - } - catch (Exception e) { - e.printStackTrace(); - } - mHandler.removeCallbacks(mRunnable); - } - } - } - - private final String path; - } -} diff --git a/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java b/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java index 15eb47bc1..2d673276f 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java +++ b/picture_library/src/main/java/com/luck/picture/lib/adapter/PictureImageGridAdapter.java @@ -2,6 +2,7 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.net.Uri; diff --git a/picture_library/src/main/res/layout/picture_doctalk.xml b/picture_library/src/main/res/layout/picture_doctalk.xml deleted file mode 100644 index 8c0165dcb..000000000 --- a/picture_library/src/main/res/layout/picture_doctalk.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - diff --git a/picture_library/src/main/res/values-de-rDE/strings.xml b/picture_library/src/main/res/values-de-rDE/strings.xml deleted file mode 100644 index f0e294775..000000000 --- a/picture_library/src/main/res/values-de-rDE/strings.xml +++ /dev/null @@ -1,72 +0,0 @@ - - Kamerafilm - %1$s (%2$d) - Abbrechen - Schießen - Es kann nicht gleichzeitig ein Bild oder Video ausgewählt werden - Sie können bis zu %1$s Bilder auswählen - Die minimale Videoauswahl darf %1$s nicht unterschreiten - Sie können bis zu %1$s Videos auswählen - Sie können bis zu %1$s Audio auswählen - Vorschau - Bitte warten… - %1$d/%2$d Vervollständigen - Abgeschlossen - Vollständig - Bitte wählen Sie - Keine Videos oder Fotos\n - Keine Audiodatei\n - Sie können mit Ihrer Kamera ein Foto oder Video aufnehmen - Sie können Audio mit der Systemaufzeichnung aufnehmen - Die Mindestauswahl an Bildern darf %1$s nicht unterschreiten - gif - webp - Leseberechtigungen für Speicherkarten verweigert - Systemkameraberechtigung verweigert - Holen Sie sich die Systemaufzeichnungsberechtigung verweigert - Das Video kann nicht in der Vorschau angezeigt werden - Video aufnehmen - Kamera - Langes Bild - Keine Mediendateien! - Aufforderung - Gibt an, ob das Bild auf dem Telefon gespeichert werden soll? - Bildspeicherung fehlgeschlagen - Bild erfolgreich gespeichert - Alles Audio - Aufnahme - Spielen - Halt an - Ausfahrt - Anhalten - Bild ist beschädigt - Das Video ist beschädigt - Audio ist fehlerhaft - Gut - %1$d/%2$d - Keine Erntedaten verfügbar - Original (%1$s) - Original - Vollständig - Vollständig(%1$d/%2$d) - Siehe(%1$d) - Auswahl - Ausnahme von Album-Daten… - Die Aufnahmezeit ist zu kurz - Machen Sie ein Foto - Nur Videos innerhalb von %1$ds können ausgewählt werden - Video nicht weniger als %1$ds auswählen - Nur Videos innerhalb von %1$ds bis %2$ds können ausgewählt werden - - Fotografie - Lange Presse Videoband - Set up - Das stimmt - Hier ist es leer… - Edit - - Foto editieren - Original - Zuschneiden - Bewegen - diff --git a/picture_library/src/main/res/values-en-rUS/string.xml b/picture_library/src/main/res/values-en-rUS/string.xml deleted file mode 100644 index bef6339e6..000000000 --- a/picture_library/src/main/res/values-en-rUS/string.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - CameraRoll - %1$s (%2$d) - Cancel - Shot - not pictures or video - Video Selection Cannot%1$sNumber - Select up to %1$s images - Select up to %1$s Audio - Select up to %1$s Video - Preview - Please later… - %1$d/%2$d Ok - Completed - Complete - Please Select - No video or photos\n - No audio file\n - You can use system recordings to record audio - you can use your camera to take photos or videos - Picture Selection Cannot%1$sNumber - gif - webp - Access to system recording permission denied - Read memory card access denied - Get system camera permission denied - Video not Preview - Record Video - Photograph - Long - No Media files! - Prompt - Do you want to save pictures to your phone? - Picture save failed - Save picture successfully until - All audio - Tape - Play - Stop - Quit - Pause - The picture is corrupted - The video is corrupted - The audio is corrupted - Confirm - %1$d/%2$d - No cropped data - Original (%1$s) - Original - Complete - Complete(%1$d/%2$d) - Preview(%1$d) - Choose - Get album data exception… - recording time is too short - Photograph, photograph - You can only select videos within %1$ds - You cannot select a video less than %1$ds - Only videos from %1$ds to %2$ds can be selected - - Take Picture - Long Press Camera - Go Setting - Ok - There no data here… - Editor - - - Original - Edit Photo - - Crop - - Rotate - Scale - Crop - - gif - \ No newline at end of file diff --git a/picture_library/src/main/res/values-es-rES/string.xml b/picture_library/src/main/res/values-es-rES/string.xml deleted file mode 100644 index ca2fa5e48..000000000 --- a/picture_library/src/main/res/values-es-rES/string.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - Todos los audios - Permiso de acceso al sistema de grabación denegado - Puedes utilizar el sistema de grabación para grabar audios - Audio corrupto - Permiso de acceso a la cámara denegado - Galería - %1$s (%2$d) - Cancelar - Únicamente pueden seleccionarse videos entre %1$ds y %2$ds - Puedes seleccionar videos de no más de %1$ds - No puedes seleccionar videos de menos de %1$ds - Completado - Confirmar - Error al obtener datos de galería… - No hay nada aquí… - Completar - %1$d/%2$d Ok - Puedes utilizar tu cámara para tomar fotos o videos - No hay audios\n - No hay fotos o videos\n - Foto corrupta - gif - webp - Configuración - Acceso a la tarjeta de memoria denegado - Entendido - Imagen larga - Seleccciona hasta %1$s audios - Selecciona hasta %1$s fotos - Selecciona %1$s videos - Las imágenes seleccionadas no deben ser menos de %1$s - Los videos seleccionados no deben ser menos de %1$s - No hay datos - Original (%1$s) - Original - Pausar - Foto con clic, foto con clic extendido - Tomar foto con clic - Tomar foto con clic extendido - Tomar foto - Reproducir - Espera un momento… - Seleccionar - Vista previa - %1$d/%2$d - Vista previa(%1$d) - Aviso - ¿Guardar las imágenes en tu teléfono? - Salir - Grabar video - Tiempo de grabación demasiado breve - No pueden seleccionarse fotos y videos simultáneamente - Guardado fallido - Foto guardada exitosamente en - Seleccionar - Completar - Completar(%1$d/%2$d) - Detener - Capturar - Grabar - Video corrupto - No hay vista previa del video - No hay ningún archivo - Editar - - gif - Editar foto - Original - Recortar - \ No newline at end of file diff --git a/picture_library/src/main/res/values-fr-rFR/strings.xml b/picture_library/src/main/res/values-fr-rFR/strings.xml deleted file mode 100644 index 87866a1c5..000000000 --- a/picture_library/src/main/res/values-fr-rFR/strings.xml +++ /dev/null @@ -1,71 +0,0 @@ - - l’album - %1$s (%2$d) - l’abandon - photo - Il n’est pas possible de sélectionner des images ou des vidéos en même temps - Vous pouvez choisir, au maximum, une image en %1$s - La sélection minimale des vidéos ne peut être inférieure à %1$s - Vous pouvez choisir au maximum %1$s de vidéos - Vous pouvez choisir au maximum %1$s audio - avant-première - attendez… - %1$d/%2$d L’achèvement - achevés - L’achèvement du - Le choix - Pas de vidéos ou de photos\n - Pas de fichier audio\n - Vous pouvez utiliser votre caméra pour prendre des photos ou des vidéos - Vous pouvez utiliser le système d’enregistrement pour enregistrer l’audio - La sélection minimale des images ne doit pas être inférieure à %1$s - gif - webp - L’autorisation de lire la carte de mémoire a été refusée - L’accès à la caméra du système a été refusé - L’accès au système d’enregistrement est refusé - Vidéo non disponible - Enregistrement vidéo - photo - Figure longue - Pas de documents pour les médias! - rappel - Conserver ou non une image sur un téléphone portable? - Défaut de conservation des images - Image conservée avec succès - Tous audio - Les transcriptions in extenso - diffusion - cessation - Le retrait - La suspension - Image endommagée - Vidéo endommagée - Audio endommagé - déterminer - %1$d/%2$d - Pas de données recadrées - Original (%1$s) - Original - Finir - Finir(%1$d/%2$d) - voir(%1$d) - Le choix - Anomalie des données de l’album… - La durée d’enregistrement est trop courte - Prendre des photos, filmer - Vous pouvez sélectionner la vidéo dans un maximum de %1$ds - Impossible de sélectionner une vidéo en dessous de %1$ds - Vous ne pouvez sélectionner que les vidéos dans les %1$ds à %2$ds - - Clic photo - Imagerie - Je sais - Pas de données… - Édition - - Original - Modifier la photo - Recadrer - Bouge fig - diff --git a/picture_library/src/main/res/values-ja-rJP/strings.xml b/picture_library/src/main/res/values-ja-rJP/strings.xml deleted file mode 100644 index 779c5977d..000000000 --- a/picture_library/src/main/res/values-ja-rJP/strings.xml +++ /dev/null @@ -1,72 +0,0 @@ - - カメラ - %1$s (%2$d) - キャンセル - カメラ - 画像や動画を同時に選択することはできない - 最大で %1$s 枚の画像を選択することができます - ビデオの最低選択数は %1$s 個までである - 最大で %1$s のビデオを選択できます - 最大で %1$s の音声を選択することができます - プレビュー - ちょっと待ってください… - %1$d/%2$d 選べた - 選べた - 選べた - 選んでください - ビデオや写真はない\n - オーディオなし\n - カメラを使って写真やビデオを撮ることができます - システムを使って音声を録音することができます - 画像の最低値は %1$s 枚までとする - 动図 - webp - メモリーカードの読み取り権限が拒否された - システムカメラの取得権限は拒否される - システムの録音権の取得は拒否される - ビデオプレビュー不可 - 録画ビデオ - 撮影 - 長い図 - メディアファイル! - 提示 - 画像を携帯電話に保存します? - 画像の保存に失敗 - 写真保存に成功まで - 全てのオーディオ - 録音 - 放送 - 停止 - 退出 - 暂停 - 画像が破損した - 映像が壊れた - オーディオが破損した - 確定 - %1$d/%2$d - トリミングされたデータはありません - 原図 (%1$s) - 原図 - を選択します - を選択します(%1$d/%2$d) - プレビュー(%1$d) - 選択 - アルバムデータ取得異常... - 収録時間が短すぎる - 写真を撮る - 最大 %1$ds 以内のビデオしか選択できません - %1$ds 以下のビデオは選択できません - %1$ds sから %2$ds までのビデオしか選択できません - 写真を撮る - 長押しする - 設定 - はい - データがありません… - 編集 - - 元の比率 - 切り取り - - 切り取り - gif図 - diff --git a/picture_library/src/main/res/values-ko-rKR/strings.xml b/picture_library/src/main/res/values-ko-rKR/strings.xml deleted file mode 100644 index 0d02216d5..000000000 --- a/picture_library/src/main/res/values-ko-rKR/strings.xml +++ /dev/null @@ -1,71 +0,0 @@ - - 카메라 필름 - %1$s (%2$d) - 취소 - 촬영 - 사진이나 비디오를 동시에 선택할 수 없습니다. - 최대 %1$s 달러 자 그림 선택 - 최소한 비디오 선택은 %1$s 달러 자 이상이어야 합니다. - 최대 %1$s 달러 개의 동영상을 선택할 수 있습니다. - 최대 %1$s 달러 개의 오디오를 선택할 수 있습니다. - 미리 보기 - 잠시만 기다려 주십시오.... - %1$d/%2$d 완료 - 완료됨 - 완료 - 선택하십시오 - 비디오나 사진 없음\n - 오디오 파일 없음\n - 사진을 찍거나 동영상을 찍을 수 있습니다 - 시스템으로 오디오 녹음 작업을 할 수 있습니다 - 그림 선택 최소 %1$s 달러 장 이상 - gif - webp - 메모리 카드 읽기 권한이 거부됨 - 시스템 카메라 가져오기 권한이 거부됨 - 시스템 녹음 권한 가져오기 거부됨 - 미리 볼 수 없는 동영상 - 비디오 녹화 - 촬영 - 투 생 - 미디어 파일 없음! - 제시 - 그림을 휴대 전화에 저장할지 여부? - 그림 저장 실패 - 그림 저장 성공 - 모든 오디오 - 녹음 - 재생 - 중지 - 출구 - 일시 정지 - 이미지 손상됨 - 비디오가 손상되었습니다 - 오디오가 손상됨 - 확정 - %1$d/%2$d - 자른 데이터가 없습니다 - 원본 이미지 (%1$s) - 원본 이미지 - 완성 - 완성(%1$d/%2$d) - 미리보기(%1$d) - 선택 - 앨범 정보 이상 가져오기… - 녹화 시간이 너무 짧다 - 사진 찍기 - 최대 %1$ds 초 이내의 영상을 선택할 수 있습니다 - %1$ds 내의 영상을 선택할 수 없습니다 - %1$ds~%2$ds 내의 영상만 선택할 수 있습니다 - 사진 찍기 클릭 - 카메라 - 설치 - 알 겠 습 니 다 - 데이터 없 음… - 편집 하 다 - - 사진 편집 - 원본 - 확인 - 움직이 - diff --git a/picture_library/src/main/res/values-pt-rPT/strings.xml b/picture_library/src/main/res/values-pt-rPT/strings.xml deleted file mode 100644 index a01560beb..000000000 --- a/picture_library/src/main/res/values-pt-rPT/strings.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - Todos - %1$s (%2$d) - Cancelar - Fotografia - Não é possível selecionar imagens ou vídeos ao mesmo tempo - Você pode escolher um máximo de %1$s foto - Os vídeos não podem ser menos de %1$s - Você pode escolher um máximo de %1$s vídeo - Você pode escolher um máximo de %1$s áudio - Antevisão - Espera… - %1$d/%2$d Terminar - Terminar - Terminar - Escolha - Não há arquivos de vídeo ou imagem\n - Não há ficheiros de áudio\n - Você pode usar a câmera para tirar fotos ou vídeos - Você pode gravar o áudio usando o sistema de gravação - Não pode haver menos de %1$s imagens - gif - webp - A permissão para ler o cartão de memória foi negada - Acesso à câmera do sistema negado - Acesso ao sistema de gravação negado - A visualização do vídeo não é suportada - Gravem video - Tirar fotos - Figura muito - Não há documentos! - Dica - Salve a imagem para o telemóvel? - Falha em salvar a imagem - A imagem foi salva com sucesso - Todos os áudios - Gravação - Play - Parar - Desistir - Pausa - imagem está danificada - vídeo está danificada - áudio está danificada - Certeza - %1$d/%2$d - Recursos sem cortes - Original (%1$s) - Original - Terminar - Terminar(%1$d/%2$d) - Antevisão(%1$d) - Escolha - Obter uma exceção para os dados do álbum… - Tempo de gravação é muito curto - Tirar fotos,Câmara - Tirar fotos - Câmara - Até um máximo de %1$ds vídeos podem ser selecionados - No mínimo, só podem ser selecionados vídeos de %1$ds segundos - Só podem ser selecionados vídeos de %1$ds a %2$ds segundos - As configurações - Entendo - Dados em branco… - Editar - - Rotação - Proporção - Recorte - - Proporção inicial - Recorte - - Recorte - Gif - diff --git a/picture_library/src/main/res/values-vi-rVN/string.xml b/picture_library/src/main/res/values-vi-rVN/string.xml deleted file mode 100644 index 78db5d60a..000000000 --- a/picture_library/src/main/res/values-vi-rVN/string.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - Camera cuộn - %1$s (%2$d) - Hủy bỏ - Bắn - Không thể chọn hình ảnh hoặc video cùng một lúc - Bạn có thể chọn tối đa%1$shình ảnh - Lựa chọn video tối thiểu phải có ít nhất%1$s - Bạn có thể chọn tối đa%1$s video - Bạn có thể chọn tối đa%1$sâm thanh - Xem trước - Xin vui lòng chờ… - %1$d/%2$d Hoàn thành - Đã hoàn thành - Hoàn thành - Vui lòng chọn - Không có video hoặc hình ảnh\n - Không có tập tin âm thanh\n - Bạn có thể sử dụng máy ảnh để chụp ảnh hoặc quay video - Bạn có thể ghi lại âm thanh bằng cách ghi hệ thống - Lựa chọn tối thiểu của hình ảnh không được ít hơn%1$s - gif - webp - Đọc thẻ nhớ bị từ chối - Nhận được sự cho phép của hệ thống camera - Nhận quyền ghi lại hệ thống bị từ chối - Video không thể xem trước - Quay video - Chụp ảnh - Hình dài - Không có tập tin phương tiện! - Gợi ý - Có lưu ảnh vào điện thoại không? - Lưu ảnh thất bại - Hình ảnh được lưu vào - Tất cả âm thanh - Ghi âm - Chơi - Dừng lại - Thoát - Tạm dừng - Hình ảnh bị hỏng - Video bị hỏng - Âm thanh bị hỏng - Được rồi - %1$d/%2$d - Không có dữ liệu cây trồng - Ảnh gốc (%1$s) - Ảnh gốc - Hoàn - Hoàn(%1$d/%2$d) - Xem trước(%1$d) - Chọn - Lấy ngoại lệ dữ liệu album… - Thời gian ghi âm quá ngắn - Chụp ảnh đi - Bạn chỉ có thể chọn ảnh trong vòng %1$ds nhất - Không thể chọn video dưới %1$ds giây - Chỉ có thể chọn ảnh giữa %1$ds và %2$ds giây - Ảnh - Máy ảnh dài - Chuẩn bị - Được rồi - không có dữ liệu… - Soạnthảo - - gif - Editar foto - Original - Recortar - \ No newline at end of file diff --git a/picture_library/src/main/res/values-zh-rCN/strings.xml b/picture_library/src/main/res/values-zh-rCN/strings.xml deleted file mode 100644 index e3e501e15..000000000 --- a/picture_library/src/main/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,77 +0,0 @@ - - 相机胶卷 - %1$s (%2$d) - 取消 - 拍摄 - 不能同时选择图片或视频 - 你最多只能选择%1$s张照片 - 视频最低选择不能少于%1$s个 - 你最多只能选择%1$s个视频 - 你最多只能选择%1$s个音频 - 预览 - 请稍候… - %1$d/%2$d 完成 - 已完成 - 完 成 - 请选择 - 无视频或照片\n - 无音频文件\n - 你可以使用相机拍摄照片或视频 - 你可以使用系统录音录制音频 - 图片最低选择不能少于%1$s张 - 动图 - 读取内存卡权限被拒绝 - 获取系统相机权限被拒绝 - 获取系统录音权限被拒绝 - 视频不可预览 - 录视频 - 拍照 - 长图 - 暂无媒体文件! - 提示 - 是否保存图片至手机? - 图片保存失败 - 图片保存成功至 - 所有音频 - 录音 - 播放 - 停止 - 退出 - 暂停 - 图片已损坏 - 视频已损坏 - 音频已损坏 - 确定 - %1$d/%2$d - 无可用裁剪数据 - 原图 (%1$s) - 原图 - 完成 - 完成(%1$d/%2$d) - 预览(%1$d) - 选择 - 获取相册数据异常… - 录制时间过短 - 单击拍照,长按摄像 - 单击拍照 - 长按摄像 - 最大只能选择 %1$ds 以内的视频 - 不能选择低于 %1$ds 内的视频 - 只能选择 %1$ds 至 %2$ds内的视频 - 去设置 - 我知道了 - 这里空空如也… - 编辑 - webp - - 旋转 - 比例 - 裁剪 - - 原始比例 - 裁剪 - - 裁剪 - 动图 - - diff --git a/picture_library/src/main/res/values-zh-rTW/strings.xml b/picture_library/src/main/res/values-zh-rTW/strings.xml deleted file mode 100644 index a80a7c6d7..000000000 --- a/picture_library/src/main/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,73 +0,0 @@ - - 相機膠卷 - %1$s (%2$d) - 取消 - 拍攝 - 不能同時選擇圖片或視頻 - 妳最多只能選擇%1$s張照片 - 視頻最低選擇不能少於%1$s個 - 妳最多只能選擇%1$s個視頻 - 妳最多只能選擇%1$s個音頻 - 預覽 - 請稍候… - %1$d/%2$d 完成 - 已完成 - 完 成 - 請選擇 - 無視頻或照片\n - 無音頻文件\n - 妳可以使用相機拍攝照片或視頻 - 妳可以使用系統錄音錄制音頻 - 圖片最低選擇不能少於%1$s張 - 動圖 - webp - 讀取內存卡權限被拒絕 - 獲取系統相機權限被拒絕 - 獲取系統錄音權限被拒絕 - 視頻不可預覽 - 錄視頻 - 拍照 - 長圖 - 暫無媒體文件! - 提示 - 是否保存圖片至手機? - 圖片保存失敗 - 圖片保存成功至 - 所有音頻 - 錄音 - 播放 - 停止 - 退出 - 暫停 - 圖片已損壞 - 視頻已損壞 - 音頻已損壞 - 確定 - %1$d/%2$d - 無可用裁剪數據 - 原圖 (%1$s) - 原圖 - 完成 - 完成(%1$d/%2$d) - 預覽(%1$d) - 選擇 - 獲取相冊數據異常... - 錄制時間過短 - 单击拍照,長按攝像 - 點擊拍照 - 長按攝像 - 最大只能選擇 %1$ds 以內的視頻 - 不能選擇低於 %1$ds 內的視頻 - 只能選擇 %1$ds 至 %2$ds內的視頻 - 去設置 - 我知道了 - 這裏空空如也… - 編輯 - - 原始比例 - 裁切 - - 裁切 - - 動圖 - diff --git a/picture_library/src/main/res/values/strings.xml b/picture_library/src/main/res/values/strings.xml index ee7c5d275..7bd2e6484 100644 --- a/picture_library/src/main/res/values/strings.xml +++ b/picture_library/src/main/res/values/strings.xml @@ -1,76 +1,77 @@ - 相机胶卷 + 카메라 필름 %1$s (%2$d) - 取消 - 拍摄 - 不能同时选择图片或视频 - 你最多只能选择%1$s张照片 - 视频最低选择不能少于%1$s个 - 你最多只能选择%1$s个视频 - 你最多只能选择%1$s个音频 - 预览 - 请稍候… - %1$d/%2$d 完成 - 已完成 - 完 成 - 请选择 - 无视频或照片\n - 无音频文件\n - 你可以使用相机拍摄照片或视频 - 你可以使用系统录音录制音频 - 图片最低选择不能少于%1$s张 - 动图 - 读取内存卡权限被拒绝 - 获取系统相机权限被拒绝 - 获取系统录音权限被拒绝 - 视频不可预览 - 录视频 - 拍照 - 长图 - 暂无媒体文件! - 提示 - 是否保存图片至手机? - 图片保存失败 - 图片保存成功至 - 所有音频 - 录音 - 播放 - 停止 - 退出 - 暂停 - 图片已损坏 - 视频已损坏 - 音频已损坏 - 确定 + 취소 + 촬영 + 사진과 동영상를 동시에 선택할 수 없습니다 + 최대 %1$d장 사진 선택이 가능합니다 + 최소한 동영상 선택은 %1$d장 이상이어야 합니다 + 최대 %1$d개의 동영상을 선택할 수 있습니다 + 최대 %1$d개의 오디오를 선택할 수 있습니다 + 미리보기 + 잠시 기다려 주세요 + %1$d/%2$d 완료 + 완료 + 완료 + 완료(%1$d) + 선택하십시오 + 사진과 동영상이 없음\n + 오디오 파일 없음\n + 사진을 찍거나 동영상을 찍을 수 있습니다 + 시스템으로 오디오 녹음을 할 수 있습니다 + 사진은 최소 %1$d장 이상이어야 합니다 + GIF + 저장소 읽기 권한이 거부되었습니다 + 시스템 카메라 가져오기 권한이 거부되었습니다 + 시스템 녹음 권한 가져오기 거부되었습니다 + 동영상 녹화 + 촬영 + 세로형 + 미디어 파일 없음! + 확인 + 사진을 핸드폰에 저장히시겠습니까? + 사진 저장 실패 + 사진 저장 성공 + 모든 오디오 + 녹음 + 재생 + 중지 + 나가기 + 일시 정지 + 이미지가 손상되었습니다 + 동영상이 손상되었습니다 + 오디오가 손상되었습니다 + 확정 %1$d/%2$d - 无可用裁剪数据 - 原图 (%1$s) - 原图 - 完成 - 完成(%1$d/%2$d) - 预览(%1$d) - 选择 - 获取相册数据异常… - 录制时间过短 - 单击拍照,长按摄像 - 单击拍照 - 长按摄像 - 最大只能选择 %1$ds 以内的视频 - 不能选择低于 %1$ds 内的视频 - 只能选择 %1$ds 至 %2$ds内的视频 - 去设置 - 我知道了 - 这里空空如也… - 编辑 - webp + 자른 데이터가 없습니다 + 원본 이미지 (%1$s) + 원본 이미지 + 완성 + 완성(%1$d/%2$d) + 미리보기(%1$d) + 선택 + 앨범 정보 불러오기 실패 + 녹화 시간이 너무 짧습니다 + 사진 찍기 + 최대 %1$d초 이내의 영상을 선택할 수 있습니다 + %1$d내의 영상을 선택할 수 없습니다 + %1$d~%2$d 내의 영상만 선택할 수 있습니다 + 사진 찍기 + 카메라 + 설정 + 확인 + 데이터 없음 + 편집 + WebP - 旋转 - 比例 - 裁剪 + 원본 + 사진 편집 + 확인 + GIF + 회전 + 크기 + 자르기 - 原始比例 - 裁剪 - - 裁剪 - 动图 + 일시적인 오류가 발생했습니다.(CROP_URI_ERROR) + 일시적인 오류가 발생했습니다.(CROP_TOOLBAR_WIDGET) diff --git a/settings.gradle b/settings.gradle index 49f7e9e90..45124f509 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':picture_library', ':ucrop' \ No newline at end of file +include ':app', ':picture_library' \ No newline at end of file From 2b6369f907f760f3e8d3256e1324372a21a892f1 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Wed, 27 Oct 2021 15:53:22 +0900 Subject: [PATCH 04/11] =?UTF-8?q?publish.gradle=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- picture_library/build.gradle | 2 - publish.gradle | 155 ----------------------------------- 2 files changed, 157 deletions(-) delete mode 100644 publish.gradle diff --git a/picture_library/build.gradle b/picture_library/build.gradle index 8cbe367c3..93f490222 100644 --- a/picture_library/build.gradle +++ b/picture_library/build.gradle @@ -30,8 +30,6 @@ android { // resourcePrefix 'ucrop_' } -apply from: '../publish.gradle' - dependencies { implementation "androidx.appcompat:appcompat:${cfgs.version_appcompat}" implementation "androidx.recyclerview:recyclerview:${cfgs.version_recyclerview}" diff --git a/publish.gradle b/publish.gradle deleted file mode 100644 index 3fd69daa2..000000000 --- a/publish.gradle +++ /dev/null @@ -1,155 +0,0 @@ -apply plugin: 'maven-publish' -apply plugin: 'signing' - -Properties localProperties = new Properties() -localProperties.load(project.rootProject.file('local.properties').newDataInputStream()) -localProperties.each { name, value -> - project.ext[name] = value -} - -def mavenUsername = localProperties.getProperty("sonatype.username") -def mavenPassword = localProperties.getProperty("sonatype.password") -def projectGroupId = localProperties.getProperty("groupId") -def projectArtifactId = localProperties.getProperty("artifactId") -def projectVersionName = cfgs.versionName -def projectDescription = localProperties.getProperty("description") -def projectGitUrl = localProperties.getProperty("gitUrl") -def projectLicense = localProperties.getProperty("license") -def projectLicenseUrl = projectLicense ? "https://opensource.org/licenses/${projectLicense.toString().replace(" ", "-")} " : null -def developerAuthorEmail = localProperties.getProperty("email") - -def developerAuthorId = mavenUsername -def developerAuthorName = mavenUsername - - -println("${mavenUsername} ${mavenPassword} - ${projectGroupId}:${projectArtifactId}:${projectVersionName}") -println("${projectLicense} - ${projectLicenseUrl}") - -if (!mavenUsername || !mavenPassword || !projectGroupId || !projectArtifactId || !projectVersionName) { - println('Error:缺少参数') - return -} -if (!projectDescription || !projectGitUrl || !projectLicense || !projectLicenseUrl || !developerAuthorId || !developerAuthorName || !developerAuthorEmail) { - println('Warning:缺少可选信息') -} - -def isAndroidProject = project.hasProperty('android') -if (isAndroidProject) { - println("使用Android工程方式发布") - task androidJavadocs(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - } - task javadocsJar(type: Jar, dependsOn: androidJavadocs) { - archiveClassifier.set("javadoc") - from androidJavadocs.destinationDir - } - task sourcesJar(type: Jar) { - archiveClassifier.set("sources") - from android.sourceSets.main.java.srcDirs - } -} else { - println("使用Java工程方式发布") - task javadocsJar(type: Jar, dependsOn: javadoc) { - archiveClassifier.set("javadoc") - from javadoc.destinationDir - } - task sourcesJar(type: Jar) { - archiveClassifier.set("sources") - from sourceSets.main.allJava - } -} - -tasks.withType(Javadoc).all { - options { - encoding "UTF-8" - charSet 'UTF-8' - author true - version true - links "http://docs.oracle.com/javase/8/docs/api" - if (isAndroidProject) { - linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference" - } - failOnError = false - } - enabled = false -} - -artifacts { - archives javadocsJar, sourcesJar -} - -publishing { - publications { - aar(MavenPublication) { - groupId = projectGroupId - artifactId = projectArtifactId - version = projectVersionName - // Tell maven to prepare the generated "*.aar" file for publishing - if (isAndroidProject) { - artifact("$buildDir/outputs/aar/${project.getName()}-release.aar") - } else { - artifact("$buildDir/libs/${project.getName()}.jar") - } - artifact javadocsJar - artifact sourcesJar - - pom { - name = projectArtifactId - description = projectDescription - // If your project has a dedicated site, use its URL here - url = projectGitUrl - licenses { - license { - name = projectLicense - url = projectLicenseUrl - } - } - developers { - developer { - id = developerAuthorId - name = developerAuthorName - email = developerAuthorEmail - } - } - // Version control info, if you're using GitHub, follow the format as seen here - scm { - connection = "scm:git:${projectGitUrl}" - developerConnection = "scm:git:${projectGitUrl}" - url = projectGitUrl - } - withXml { - def dependenciesNode = asNode().appendNode('dependencies') - project.configurations.implementation.allDependencies.each { - def dependencyNode = dependenciesNode.appendNode('dependency') - dependencyNode.appendNode('groupId', it.group) - dependencyNode.appendNode('artifactId', it.name) - dependencyNode.appendNode('version', it.version) - } - } - } - } - } - - repositories { - maven { - name = projectArtifactId - - def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" - def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" - // You only need this if you want to publish snapshots, otherwise just set the URL - // to the release repo directly - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - - // The username and password we've fetched earlier - credentials { - username mavenUsername - password mavenPassword - } - } - } -} - -signing { - sign publishing.publications -} \ No newline at end of file From e4fcf1a8e4443f9981acb8a8d9495d44dad98ed9 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Wed, 27 Oct 2021 17:19:44 +0900 Subject: [PATCH 05/11] =?UTF-8?q?Doctalk=20=EC=A0=84=EC=9A=A9=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../picture/lib/PictureSelectionModel.java | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java index bbc824e1d..10f9055db 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java @@ -1711,11 +1711,40 @@ public void forResult(OnResultCallbackListener listener) { } } + /** + * Doctalk 사용 + * @param intent + * @param listener + */ + public void forResult (Intent intent, OnResultCallbackListener listener) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null || selectionConfig == null) { + return; + } + if (PictureSelectionConfig.imageEngine == null){ + throw new NullPointerException("api imageEngine is null,Please implement ImageEngine"); + } + // 绑定回调监听 + PictureSelectionConfig.listener = new WeakReference<>(listener).get(); + selectionConfig.isCallbackMode = true; + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivity(intent); + } + else { + activity.startActivity(intent); + } + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition( + windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + /** * Start to select media and wait for result. * - * @param launcher use {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)} - * passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}. + * @param launcher */ public void forResult(ActivityResultLauncher launcher) { if (!DoubleUtils.isFastDoubleClick()) { @@ -1742,6 +1771,27 @@ public void forResult(ActivityResultLauncher launcher) { } } + /** + * Start to select media and wait for result. + * + * @param launcher + */ + public void forResult(Intent intent, ActivityResultLauncher launcher) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (launcher == null || activity == null || selectionConfig == null) { + return; + } + if (PictureSelectionConfig.imageEngine == null){ + throw new NullPointerException("api imageEngine is null,Please implement ImageEngine"); + } + selectionConfig.isCallbackMode = false; + launcher.launch(intent); + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + /** * Start to select media and wait for result. * From aad888ad344eb407ec3e3b46fd32053b0c504155 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Thu, 16 Dec 2021 12:09:06 +0900 Subject: [PATCH 06/11] 1. startOpenCameraImage deprecated, and add startOpenCameraImage ActivityResultLauncher 2. startOpenCameraVideo deprecated, and add startOpenCameraVideo ActivityResultLauncher 3. startOpenCameraAudio deprecated, and add startOpenCameraAudio ActivityResultLauncher 4. library version up --- build.gradle | 2 +- config.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- picture_library/build.gradle | 4 +- .../luck/picture/lib/PictureBaseActivity.java | 139 +++++++++++++++++- .../lib/config/PictureSelectionConfig.java | 1 - 6 files changed, 140 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index deca82ae2..9fe1dd3dd 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' + classpath 'com.android.tools.build:gradle:7.0.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/config.gradle b/config.gradle index 483093d4b..bda15b57a 100644 --- a/config.gradle +++ b/config.gradle @@ -12,13 +12,13 @@ ext { //open version control androidSupportVersion : "27.0.2", version_recyclerview : "1.2.1", - version_appcompat : "1.3.1", + version_appcompat : "1.4.0", localbroadcastmanager : "1.0.0", activity_version : "1.3.1", fragment_version : "1.3.6", camerax_view : "1.0.0-alpha28", - camerax_version : "1.1.0-alpha08", + camerax_version : "1.1.0-alpha11", camera_core_version : "1.0.0-rc04", experimental_version : "1.1.0", futures_version : "1.1.0", diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f6d4cc062..7cecca866 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip diff --git a/picture_library/build.gradle b/picture_library/build.gradle index 93f490222..f8a23ab2b 100644 --- a/picture_library/build.gradle +++ b/picture_library/build.gradle @@ -6,8 +6,6 @@ android { defaultConfig { minSdkVersion cfgs.minSdkVersion targetSdkVersion cfgs.targetSdkVersion - versionCode cfgs.versionCode - versionName cfgs.versionName vectorDrawables.useSupportLibrary = true } @@ -40,6 +38,6 @@ dependencies { implementation "androidx.exifinterface:exifinterface:${cfgs.androidx_exifinterface_version}" implementation "androidx.localbroadcastmanager:localbroadcastmanager:${cfgs.localbroadcastmanager}" implementation "androidx.camera:camera-view:${cfgs.camerax_view}" - implementation "androidx.transition:transition:${cfgs.androidx_transition_version}" implementation "androidx.camera:camera-lifecycle:${cfgs.camerax_version}" + implementation "androidx.transition:transition:${cfgs.androidx_transition_version}" } diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureBaseActivity.java b/picture_library/src/main/java/com/luck/picture/lib/PictureBaseActivity.java index 77969f858..3cf0315e0 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/PictureBaseActivity.java +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureBaseActivity.java @@ -5,15 +5,14 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.provider.MediaStore; import android.text.TextUtils; import android.view.View; -import android.widget.TextView; +import androidx.activity.result.ActivityResultLauncher; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -52,6 +51,8 @@ import java.util.Collections; import java.util.List; +import kotlin.Deprecated; + /** * @author:luck @@ -679,6 +680,7 @@ protected String getAudioPath(Intent data) { /** * start to camera、preview、crop */ + @Deprecated(message = "startActivityForResult Deprecated") protected void startOpenCameraImage() { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (cameraIntent.resolveActivity(getPackageManager()) != null) { @@ -724,10 +726,55 @@ protected void startOpenCameraImage() { } } + protected void startOpenCameraImage(ActivityResultLauncher resultLauncher) { + Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (cameraIntent.resolveActivity(getPackageManager()) != null) { + Uri imageUri; + String cameraFileName = null; + String imageFormat = TextUtils.isEmpty(config.cameraImageFormat) ? config.suffixType : config.cameraImageFormat; + int chooseMode = config.chooseMode == PictureConfig.TYPE_ALL ? PictureConfig.TYPE_IMAGE : config.chooseMode; + if (!TextUtils.isEmpty(config.cameraFileName)) { + boolean isSuffixOfImage = PictureMimeType.isSuffixOfImage(config.cameraFileName); + config.cameraFileName = !isSuffixOfImage ? StringUtils.renameSuffix(config.cameraFileName, PictureMimeType.JPG) : config.cameraFileName; + cameraFileName = config.camera ? config.cameraFileName : StringUtils.rename(config.cameraFileName); + } + if (SdkVersionUtils.checkedAndroid_Q()) { + if (TextUtils.isEmpty(config.outPutCameraPath)) { + imageUri = MediaUtils.createImageUri(this, config.cameraFileName, imageFormat); + } else { + File cameraFile = PictureFileUtils.createCameraFile(this, + chooseMode, cameraFileName, imageFormat, config.outPutCameraPath); + config.cameraPath = cameraFile.getAbsolutePath(); + imageUri = PictureFileUtils.parUri(this, cameraFile); + } + if (imageUri != null) { + config.cameraPath = imageUri.toString(); + } + } else { + File cameraFile = PictureFileUtils.createCameraFile(this, chooseMode, cameraFileName, imageFormat, config.outPutCameraPath); + config.cameraPath = cameraFile.getAbsolutePath(); + imageUri = PictureFileUtils.parUri(this, cameraFile); + } + if (imageUri == null) { + ToastUtils.s(getContext(), "open is camera error,the uri is empty "); + if (config.camera) { + exit(); + } + return; + } + config.cameraMimeType = PictureMimeType.ofImage(); + if (config.isCameraAroundState) { + cameraIntent.putExtra(PictureConfig.CAMERA_FACING, PictureConfig.CAMERA_BEFORE); + } + cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); + resultLauncher.launch(cameraIntent); + } + } /** * start to camera、video */ + @Deprecated(message = "startActivityForResult Deprecated") protected void startOpenCameraVideo() { Intent cameraIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); if (cameraIntent.resolveActivity(getPackageManager()) != null) { @@ -775,9 +822,60 @@ protected void startOpenCameraVideo() { } } + /** + * start to camera、video + */ + protected void startOpenCameraVideo(ActivityResultLauncher resultLauncher) { + Intent cameraIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + if (cameraIntent.resolveActivity(getPackageManager()) != null) { + Uri videoUri; + String cameraFileName = null; + String videoFormat = TextUtils.isEmpty(config.cameraVideoFormat) ? config.suffixType : config.cameraVideoFormat; + int chooseMode = config.chooseMode == PictureConfig.TYPE_ALL ? PictureConfig.TYPE_VIDEO : config.chooseMode; + if (!TextUtils.isEmpty(config.cameraFileName)) { + boolean isSuffixOfImage = PictureMimeType.isSuffixOfImage(config.cameraFileName); + config.cameraFileName = isSuffixOfImage ? StringUtils.renameSuffix(config.cameraFileName, PictureMimeType.MP4) : config.cameraFileName; + cameraFileName = config.camera ? config.cameraFileName : StringUtils.rename(config.cameraFileName); + } + if (SdkVersionUtils.checkedAndroid_Q()) { + if (TextUtils.isEmpty(config.outPutCameraPath)) { + videoUri = MediaUtils.createVideoUri(this, config.cameraFileName, videoFormat); + } else { + File cameraFile = PictureFileUtils.createCameraFile(this, chooseMode, cameraFileName, videoFormat, config.outPutCameraPath); + config.cameraPath = cameraFile.getAbsolutePath(); + videoUri = PictureFileUtils.parUri(this, cameraFile); + } + if (videoUri != null) { + config.cameraPath = videoUri.toString(); + } + } else { + File cameraFile = PictureFileUtils.createCameraFile(this, chooseMode, cameraFileName, videoFormat, config.outPutCameraPath); + config.cameraPath = cameraFile.getAbsolutePath(); + videoUri = PictureFileUtils.parUri(this, cameraFile); + } + if (videoUri == null) { + ToastUtils.s(getContext(), "open is camera error,the uri is empty "); + if (config.camera) { + exit(); + } + return; + } + config.cameraMimeType = PictureMimeType.ofVideo(); + cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri); + if (config.isCameraAroundState) { + cameraIntent.putExtra(PictureConfig.CAMERA_FACING, PictureConfig.CAMERA_BEFORE); + } + cameraIntent.putExtra(PictureConfig.EXTRA_QUICK_CAPTURE, config.isQuickCapture); + cameraIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, config.recordVideoSecond); + cameraIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, config.videoQuality); + resultLauncher.launch(cameraIntent); + } + } + /** * start to camera audio */ + @Deprecated(message = "startActivityForResult Deprecated") public void startOpenCameraAudio() { try { if (PermissionChecker.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)) { @@ -809,7 +907,41 @@ public void startOpenCameraAudio() { e.printStackTrace(); ToastUtils.s(getContext(), e.getMessage()); } + } + /** + * start to camera audio + */ + public void startOpenCameraAudio(ActivityResultLauncher resultLauncher) { + try { + if (PermissionChecker.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)) { + Intent cameraIntent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); + if (cameraIntent.resolveActivity(getPackageManager()) != null) { + config.cameraMimeType = PictureMimeType.ofAudio(); + String audioFormat = TextUtils.isEmpty(config.cameraAudioFormat) ? config.suffixType : config.cameraAudioFormat; + if (SdkVersionUtils.checkedAndroid_Q()) { + Uri audioUri = MediaUtils.createAudioUri(this, audioFormat); + if (audioUri == null) { + ToastUtils.s(getContext(), "open is audio error,the uri is empty "); + if (config.camera) { + exit(); + } + return; + } + config.cameraPath = audioUri.toString(); + cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, audioUri); + } + resultLauncher.launch(cameraIntent); + } else { + ToastUtils.s(getContext(), "System recording is not supported"); + } + } else { + PermissionChecker.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PictureConfig.APPLY_AUDIO_PERMISSIONS_CODE); + } + } catch (Exception e) { + e.printStackTrace(); + ToastUtils.s(getContext(), e.getMessage()); + } } /** @@ -859,8 +991,7 @@ protected void showPromptDialog(String content) { if (!isFinishing()) { if (PictureSelectionConfig.onChooseLimitCallback != null) { PictureSelectionConfig.onChooseLimitCallback.onChooseLimit(getContext(), content); - } - else { + } else { new AlertDialog.Builder(getContext()) .setMessage(content) .setPositiveButton(R.string.picture_know, (dialog, which) -> { diff --git a/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java b/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java index 720c33d67..f85673428 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java +++ b/picture_library/src/main/java/com/luck/picture/lib/config/PictureSelectionConfig.java @@ -90,7 +90,6 @@ public final class PictureSelectionConfig implements Parcelable { public boolean isMultipleRecyclerAnimation; public boolean isMultipleSkipCrop; public boolean isWeChatStyle; - public boolean isDoctalkStyle; public boolean isUseCustomCamera; public boolean zoomAnim; public boolean isCompress; From c002df111a3b8f5f8abe630b9c50a6d319db75a4 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Thu, 16 Dec 2021 12:22:11 +0900 Subject: [PATCH 07/11] jitpack.yml add --- jitpack.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 jitpack.yml diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 000000000..46c852919 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,2 @@ +jdk: + - openjdk11 \ No newline at end of file From b3fbea15728fe291a86cda0b44b950b9ae4f2ce5 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Thu, 16 Dec 2021 12:29:58 +0900 Subject: [PATCH 08/11] =?UTF-8?q?gradle=20=EB=B2=84=EC=A0=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- picture_library/build.gradle | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 9fe1dd3dd..deca82ae2 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:7.0.4' + classpath 'com.android.tools.build:gradle:4.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7cecca866..f6d4cc062 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/picture_library/build.gradle b/picture_library/build.gradle index f8a23ab2b..93f490222 100644 --- a/picture_library/build.gradle +++ b/picture_library/build.gradle @@ -6,6 +6,8 @@ android { defaultConfig { minSdkVersion cfgs.minSdkVersion targetSdkVersion cfgs.targetSdkVersion + versionCode cfgs.versionCode + versionName cfgs.versionName vectorDrawables.useSupportLibrary = true } @@ -38,6 +40,6 @@ dependencies { implementation "androidx.exifinterface:exifinterface:${cfgs.androidx_exifinterface_version}" implementation "androidx.localbroadcastmanager:localbroadcastmanager:${cfgs.localbroadcastmanager}" implementation "androidx.camera:camera-view:${cfgs.camerax_view}" - implementation "androidx.camera:camera-lifecycle:${cfgs.camerax_version}" implementation "androidx.transition:transition:${cfgs.androidx_transition_version}" + implementation "androidx.camera:camera-lifecycle:${cfgs.camerax_version}" } From 43c0642225c3ee91ae04899071bed4cb1494bcaa Mon Sep 17 00:00:00 2001 From: JG Pak Date: Thu, 16 Dec 2021 13:43:23 +0900 Subject: [PATCH 09/11] =?UTF-8?q?=EC=82=AD=EC=A0=9C=EB=90=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../picture/lib/PictureSelectionModel.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java index 10f9055db..155fa3e61 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java @@ -1741,6 +1741,36 @@ public void forResult (Intent intent, OnResultCallbackListener liste } } + /** + * Doctalk 사용 + * @param intent + * @param listener + */ + public void forResult (Intent intent, OnResultCallbackListener listener) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (activity == null || selectionConfig == null) { + return; + } + if (PictureSelectionConfig.imageEngine == null){ + throw new NullPointerException("api imageEngine is null,Please implement ImageEngine"); + } + // 绑定回调监听 + PictureSelectionConfig.listener = new WeakReference<>(listener).get(); + selectionConfig.isCallbackMode = true; + Fragment fragment = selector.getFragment(); + if (fragment != null) { + fragment.startActivity(intent); + } + else { + activity.startActivity(intent); + } + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition( + windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + /** * Start to select media and wait for result. * @@ -1792,6 +1822,27 @@ public void forResult(Intent intent, ActivityResultLauncher launcher) { } } + /** + * Start to select media and wait for result. + * + * @param launcher + */ + public void forResult(Intent intent, ActivityResultLauncher launcher) { + if (!DoubleUtils.isFastDoubleClick()) { + Activity activity = selector.getActivity(); + if (launcher == null || activity == null || selectionConfig == null) { + return; + } + if (PictureSelectionConfig.imageEngine == null){ + throw new NullPointerException("api imageEngine is null,Please implement ImageEngine"); + } + selectionConfig.isCallbackMode = false; + launcher.launch(intent); + PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; + activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); + } + } + /** * Start to select media and wait for result. * From e7f5b65cbdf2e443986b40507506d29e71c2cc2b Mon Sep 17 00:00:00 2001 From: JG Pak Date: Thu, 16 Dec 2021 16:44:23 +0900 Subject: [PATCH 10/11] =?UTF-8?q?UCrop=20ActivityResultLauncher=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 +- .../picture/lib/PictureSelectionModel.java | 51 ---------- .../picture/lib/manager/UCropManager.java | 75 ++++++++++++++ .../main/java/com/yalantis/ucrop/UCrop.java | 98 ++++++++++++++++--- 4 files changed, 161 insertions(+), 67 deletions(-) diff --git a/config.gradle b/config.gradle index bda15b57a..483093d4b 100644 --- a/config.gradle +++ b/config.gradle @@ -12,13 +12,13 @@ ext { //open version control androidSupportVersion : "27.0.2", version_recyclerview : "1.2.1", - version_appcompat : "1.4.0", + version_appcompat : "1.3.1", localbroadcastmanager : "1.0.0", activity_version : "1.3.1", fragment_version : "1.3.6", camerax_view : "1.0.0-alpha28", - camerax_version : "1.1.0-alpha11", + camerax_version : "1.1.0-alpha08", camera_core_version : "1.0.0-rc04", experimental_version : "1.1.0", futures_version : "1.1.0", diff --git a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java index 155fa3e61..10f9055db 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java +++ b/picture_library/src/main/java/com/luck/picture/lib/PictureSelectionModel.java @@ -1741,36 +1741,6 @@ public void forResult (Intent intent, OnResultCallbackListener liste } } - /** - * Doctalk 사용 - * @param intent - * @param listener - */ - public void forResult (Intent intent, OnResultCallbackListener listener) { - if (!DoubleUtils.isFastDoubleClick()) { - Activity activity = selector.getActivity(); - if (activity == null || selectionConfig == null) { - return; - } - if (PictureSelectionConfig.imageEngine == null){ - throw new NullPointerException("api imageEngine is null,Please implement ImageEngine"); - } - // 绑定回调监听 - PictureSelectionConfig.listener = new WeakReference<>(listener).get(); - selectionConfig.isCallbackMode = true; - Fragment fragment = selector.getFragment(); - if (fragment != null) { - fragment.startActivity(intent); - } - else { - activity.startActivity(intent); - } - PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; - activity.overridePendingTransition( - windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); - } - } - /** * Start to select media and wait for result. * @@ -1822,27 +1792,6 @@ public void forResult(Intent intent, ActivityResultLauncher launcher) { } } - /** - * Start to select media and wait for result. - * - * @param launcher - */ - public void forResult(Intent intent, ActivityResultLauncher launcher) { - if (!DoubleUtils.isFastDoubleClick()) { - Activity activity = selector.getActivity(); - if (launcher == null || activity == null || selectionConfig == null) { - return; - } - if (PictureSelectionConfig.imageEngine == null){ - throw new NullPointerException("api imageEngine is null,Please implement ImageEngine"); - } - selectionConfig.isCallbackMode = false; - launcher.launch(intent); - PictureWindowAnimationStyle windowAnimationStyle = PictureSelectionConfig.windowAnimationStyle; - activity.overridePendingTransition(windowAnimationStyle.activityEnterAnimation, R.anim.picture_anim_fade_in); - } - } - /** * Start to select media and wait for result. * diff --git a/picture_library/src/main/java/com/luck/picture/lib/manager/UCropManager.java b/picture_library/src/main/java/com/luck/picture/lib/manager/UCropManager.java index 2bf7aacf8..7581c7bdd 100644 --- a/picture_library/src/main/java/com/luck/picture/lib/manager/UCropManager.java +++ b/picture_library/src/main/java/com/luck/picture/lib/manager/UCropManager.java @@ -2,10 +2,13 @@ import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.text.TextUtils; +import androidx.activity.result.ActivityResultLauncher; + import com.luck.picture.lib.R; import com.luck.picture.lib.config.PictureMimeType; import com.luck.picture.lib.config.PictureSelectionConfig; @@ -87,6 +90,33 @@ public static void ofCrop(Activity activity, String originalPath, String mimeTyp .startAnimationActivity(activity, PictureSelectionConfig.windowAnimationStyle.activityCropEnterAnimation); } + /** + * 裁剪 + * + * @param activity 上下文 + * @param originalPath 文件源路径 + * @param mimeType 文件类型 + */ + public static void ofCrop(Activity activity, String originalPath, String mimeType, ActivityResultLauncher launcher) { + if (DoubleUtils.isFastDoubleClick()) { + return; + } + if (TextUtils.isEmpty(originalPath)) { + ToastUtils.s(activity.getApplicationContext(), activity.getString(R.string.picture_not_crop_data)); + return; + } + PictureSelectionConfig config = PictureSelectionConfig.getInstance(); + boolean isHttp = PictureMimeType.isHasHttp(originalPath); + String suffix = mimeType.replace("image/", "."); + File file = new File(PictureFileUtils.getDiskCacheDir(activity.getApplicationContext()), + TextUtils.isEmpty(config.renameCropFileName) ? DateUtils.getCreateFileName("IMG_CROP_") + suffix : config.renameCropFileName); + Uri uri = isHttp || PictureMimeType.isContent(originalPath) ? Uri.parse(originalPath) : Uri.fromFile(new File(originalPath)); + UCrop.Options options = UCropManager.basicOptions(activity); + UCrop.of(uri, Uri.fromFile(file)) + .withOptions(options) + .startAnimationActivity(activity, launcher, PictureSelectionConfig.windowAnimationStyle.activityCropEnterAnimation); + } + /** * 裁剪 * @@ -132,6 +162,51 @@ public static void ofCrop(Activity activity, ArrayList list) { } } + /** + * 裁剪 + * + * @param activity 上下文 + * @param list 待裁剪图片集合 + */ + public static void ofCrop(Activity activity, ArrayList list, ActivityResultLauncher launcher) { + if (DoubleUtils.isFastDoubleClick()) { + return; + } + if (list == null || list.size() == 0) { + ToastUtils.s(activity.getApplicationContext(), activity.getString(R.string.picture_not_crop_data)); + return; + } + PictureSelectionConfig config = PictureSelectionConfig.getInstance(); + UCrop.Options options = UCropManager.basicOptions(activity); + options.setCutListData(list); + int size = list.size(); + int index = 0; + if (config.chooseMode == PictureMimeType.ofAll() && config.isWithVideoImage) { + String mimeType = size > 0 ? list.get(index).getMimeType() : ""; + boolean isHasVideo = PictureMimeType.isHasVideo(mimeType); + if (isHasVideo) { + for (int i = 0; i < size; i++) { + LocalMedia cutInfo = list.get(i); + if (cutInfo != null && PictureMimeType.isHasImage(cutInfo.getMimeType())) { + index = i; + break; + } + } + } + } + if (index < size) { + LocalMedia info = list.get(index); + boolean isHttp = PictureMimeType.isHasHttp(info.getPath()); + Uri uri = isHttp || PictureMimeType.isContent(info.getPath()) ? Uri.parse(info.getPath()) : Uri.fromFile(new File(info.getPath())); + String suffix = info.getMimeType().replace("image/", "."); + File file = new File(PictureFileUtils.getDiskCacheDir(activity), + TextUtils.isEmpty(config.renameCropFileName) ? DateUtils.getCreateFileName("IMG_CROP_") + + suffix : config.camera || size == 1 ? config.renameCropFileName : StringUtils.rename(config.renameCropFileName)); + UCrop.of(uri, Uri.fromFile(file)).withOptions(options) + .startAnimationMultipleCropActivity(activity, PictureSelectionConfig.windowAnimationStyle.activityCropEnterAnimation, launcher); + } + } + /** * basicOptions diff --git a/picture_library/src/main/java/com/yalantis/ucrop/UCrop.java b/picture_library/src/main/java/com/yalantis/ucrop/UCrop.java index 3922c6b46..e36a3c62c 100755 --- a/picture_library/src/main/java/com/yalantis/ucrop/UCrop.java +++ b/picture_library/src/main/java/com/yalantis/ucrop/UCrop.java @@ -8,6 +8,7 @@ import android.os.Bundle; import android.os.Parcelable; +import androidx.activity.result.ActivityResultLauncher; import androidx.annotation.AnimRes; import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; @@ -26,6 +27,8 @@ import java.util.Arrays; import java.util.Locale; +import kotlin.Deprecated; + /** * Created by Oleksii Shliama (https://github.com/shliama). *

@@ -137,27 +140,63 @@ public void startAnimationActivity(@NonNull Activity activity, @AnimRes int acti } } + /** + * Send the crop Intent from animation an Activity + * + * @param activity Activity to receive result + */ + public void startAnimationActivity(@NonNull Activity activity, ActivityResultLauncher launcher, @AnimRes int activityCropEnterAnimation) { + if (activityCropEnterAnimation != 0) { + start(activity, launcher, activityCropEnterAnimation); + } else { + start(activity, launcher); + } + } + /** * Send the crop Intent from an Activity with a custom request code or animation * * @param activity Activity to receive result * @param requestCode requestCode for result */ + @Deprecated(message = "startActivityForResult deprecated") public void start(@NonNull Activity activity, int requestCode, @AnimRes int activityCropEnterAnimation) { activity.startActivityForResult(getIntent(activity), requestCode); activity.overridePendingTransition(activityCropEnterAnimation, R.anim.ucrop_anim_fade_in); } + /** + * Send the crop Intent from an Activity with a custom request code or animation + * + * @param activity Activity to receive result + * @param launcher result launcher + */ + public void start(@NonNull Activity activity, ActivityResultLauncher launcher, @AnimRes int activityCropEnterAnimation) { + launcher.launch(getIntent(activity)); + activity.overridePendingTransition(activityCropEnterAnimation, R.anim.ucrop_anim_fade_in); + } + /** * Send the crop Intent from an Activity with a custom request code * * @param activity Activity to receive result * @param requestCode requestCode for result */ + @Deprecated(message = "startActivityForResult deprecated") public void start(@NonNull Activity activity, int requestCode) { activity.startActivityForResult(getIntent(activity), requestCode); } + /** + * Send the crop Intent from an Activity with a custom request code + * + * @param activity Activity to receive result + * @param launcher result launcher + */ + public void start(@NonNull Activity activity, ActivityResultLauncher launcher) { + launcher.launch(getIntent(activity)); + } + /** * Send the crop Intent from an Activity * @@ -173,27 +212,19 @@ public void start(@NonNull AppCompatActivity activity) { * @param activity Activity to receive result * @param requestCode requestCode for result */ + @Deprecated(message = "startActivityForResult deprecated") public void start(@NonNull AppCompatActivity activity, int requestCode) { activity.startActivityForResult(getIntent(activity), requestCode); } /** - * Send the crop Intent from a Fragment - * - * @param fragment Fragment to receive result - */ - public void start(@NonNull Context context, @NonNull Fragment fragment) { - start(context, fragment, REQUEST_CROP); - } - - /** - * Send the crop Intent with a custom request code + * Send the crop Intent from an Activity with a custom request code * - * @param fragment Fragment to receive result - * @param requestCode requestCode for result + * @param activity Activity to receive result + * @param launcher result launcher */ - public void start(@NonNull Context context, @NonNull Fragment fragment, int requestCode) { - fragment.startActivityForResult(getIntent(context), requestCode); + public void start(@NonNull AppCompatActivity activity, ActivityResultLauncher launcher) { + launcher.launch(getIntent(activity)); } @@ -244,6 +275,45 @@ public void startMultiple(@NonNull Activity activity, int requestCode) { activity.startActivityForResult(getMultipleIntent(activity), requestCode); } + + /** + * 多图裁剪 + */ + /** + * Send the crop Intent from animation an Multiple Activity + * + * @param activity Activity to receive result + */ + public void startAnimationMultipleCropActivity(@NonNull Activity activity, + @AnimRes int activityCropEnterAnimation, ActivityResultLauncher launcher) { + if (activityCropEnterAnimation != 0) { + startMultiple(activity, launcher, activityCropEnterAnimation); + } else { + startMultiple(activity, launcher); + } + } + + /** + * Send the crop Intent from an Activity with a custom request code or animation + * + * @param activity Activity to receive result + * @param launcher requestCode for result + */ + public void startMultiple(@NonNull Activity activity, ActivityResultLauncher launcher, @AnimRes int activityCropEnterAnimation) { + launcher.launch(getMultipleIntent(activity)); + activity.overridePendingTransition(activityCropEnterAnimation, R.anim.ucrop_anim_fade_in); + } + + /** + * Send the crop Intent from an Activity with a custom request code + * + * @param activity Activity to receive result + * @param launcher requestCode for result + */ + public void startMultiple(@NonNull Activity activity, ActivityResultLauncher launcher) { + launcher.launch(getMultipleIntent(activity)); + } + /** * Get Intent to start {@link PictureMultiCuttingActivity} * From 0147e21a6ea2beb74be4aaed025ee89ac48af5d8 Mon Sep 17 00:00:00 2001 From: JG Pak Date: Fri, 18 Mar 2022 10:24:45 +0900 Subject: [PATCH 11/11] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6258129ba..04b8a1bca 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +# 수정사항 +1. Doctalk Service에 맞게 커스텀 +2. 디자인 수정 +3. 코드 정리 + # PictureSelector 2.0 A Picture Selector for Android platform, support from the album to obtain pictures, video, audio & photo, support crop (single picture or multi-picture crop), compression, theme custom configuration and other functions, support dynamic access & adapt to Android 5.0+ system of open source picture selection framework。