Android 仿微信图片选择器 PictureSelector3.0 的使用

在做项目时经常会遇到图片选着,选择单张图片还好,但类似于微信发朋友圈时可以多图选择的时候,就有点手足无措。然后在网上看了很多类似的项目,也尝试过将他们用于自己的项目,比如 知乎开源图片选择库 Matisse 等。但对比之下,PictureSelector 对我这种小白来说是更不错的选择。

  1. 如何引用
dependencies {
    
    
  // PictureSelector 基础 (必须)
  implementation 'io.github.lucksiege:pictureselector:v3.0.9'

  // 图片压缩 (按需引入)
  implementation 'io.github.lucksiege:compress:v3.0.9'

  // 图片裁剪 (按需引入)
  implementation 'io.github.lucksiege:ucrop:v3.0.9'

  // 自定义相机 (按需引入)
  implementation 'io.github.lucksiege:camerax:v3.0.9'
}
  1. 添加权限 (按需添加)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
Android 11 使用相机,需要再AndroidManifest.xm 添加如下代码:

<queries package="${applicationId}">
    <intent>
        <action android:name="android.media.action.IMAGE_CAPTURE">

        </action>
    </intent>
    <intent>
        <action android:name="android.media.action.ACTION_VIDEO_CAPTURE">

        </action>
    </intent>
</queries>
  1. 图片加载策略, 框架默认提供的是Glide, 在使用的过程中,Glide的版本太高或者太低都有可能造成在调用PictureSelector方法时闪退。 我用的都是目前的最新版本4.13.0
 implementation 'com.github.bumptech.glide:glide:4.13.0'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
	/**
	* 在项目中创建一个GlideEngine类
	* Glide加载引擎
	*/
	public class GlideEngine implements ImageEngine {
    
    
	
	    /**
	     * 加载图片
	     *
	     * @param context   上下文
	     * @param url       资源url
	     * @param imageView 图片承载控件
	     */
	    @Override
	    public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
    
    
	        if (!ActivityCompatHelper.assertValidRequest(context)) {
    
    
	            return;
	        }
	        Glide.with(context)
	                .load(url)
	                .into(imageView);
	    }
	
	    /**
	     * 加载指定url并返回bitmap
	     *
	     * @param context   上下文
	     * @param url       资源url
	     * @param maxWidth  资源最大加载尺寸
	     * @param maxHeight 资源最大加载尺寸
	     * @param call      回调接口
	     */
	    @Override
	    public void loadImageBitmap(@NonNull Context context, @NonNull String url, int maxWidth, int maxHeight, OnCallbackListener<Bitmap> call) {
    
    
	        if (!ActivityCompatHelper.assertValidRequest(context)) {
    
    
	            return;
	        }
	        Glide.with(context)
	                .asBitmap()
	                .override(maxWidth, maxHeight)
	                .load(url)
	                .into(new CustomTarget<Bitmap>() {
    
    
	
	                    @Override
	                    public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
    
    
	                        if (call != null) {
    
    
	                            call.onCall(resource);
	                        }
	                    }
	
	                    @Override
	                    public void onLoadFailed(@Nullable Drawable errorDrawable) {
    
    
	                        if (call != null) {
    
    
	                            call.onCall(null);
	                        }
	                    }
	
	                    @Override
	                    public void onLoadCleared(@Nullable Drawable placeholder) {
    
    
	
	                    }
	
	                });
	    }
	
	    /**
	     * 加载相册目录封面
	     *
	     * @param context   上下文
	     * @param url       图片路径
	     * @param imageView 承载图片ImageView
	     */
	    @Override
	    public void loadAlbumCover(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
    
    
	        if (!ActivityCompatHelper.assertValidRequest(context)) {
    
    
	            return;
	        }
	        Glide.with(context)
	                .asBitmap()
	                .load(url)
	                .override(180, 180)
	                .sizeMultiplier(0.5f)
	                .transform(new CenterCrop(), new RoundedCorners(8))
	                .placeholder(R.drawable.ps_image_placeholder)
	                .into(imageView);
	    }
	
	
	    /**
	     * 加载图片列表图片
	     *
	     * @param context   上下文
	     * @param url       图片路径
	     * @param imageView 承载图片ImageView
	     */
	    @Override
	    public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
    
    
	        if (!ActivityCompatHelper.assertValidRequest(context)) {
    
    
	            return;
	        }
	        Glide.with(context)
	                .load(url)
	                .override(200, 200)
	                .centerCrop()
	                .placeholder(R.drawable.ps_image_placeholder)
	                .into(imageView);
	    }
	
	    @Override
	    public void pauseRequests(Context context) {
    
    
	        Glide.with(context).pauseRequests();
	    }
	
	    @Override
	    public void resumeRequests(Context context) {
    
    
	        Glide.with(context).resumeRequests();
	    }
	
	    private GlideEngine() {
    
    
	    }
	
	    private static GlideEngine instance;
	
	    public static GlideEngine createGlideEngine() {
    
    
	        if (null == instance) {
    
    
	            synchronized (GlideEngine.class) {
    
    
	                if (null == instance) {
    
    
	                    instance = new GlideEngine();
	                }
	            }
	        }
	        return instance;
	    }
	}
  1. 了解一下3.0版本的各个api的使用, 与2.0版本还是有蛮大区别的, 根据自己需求设置
.setSelectorUIStyle(); 设置相册主题
.setLanguage(); 设置相册语言
.setImageEngine(); 设置相册图片加载引擎
.setCompressEngine(); 设置相册压缩引擎
.setCropEngine(); 设置相册裁剪引擎
.setSandboxFileEngine(); 设置相册沙盒目录拷贝引擎
.setOriginalFileEngine(); 设置相册图片原图处理引擎
.setExtendLoaderEngine(); 设置相册数据源加载引擎
.setCameraInterceptListener(); 拦截相机事件,实现自定义相机
.setEditMediaInterceptListener(); 拦截资源编辑事件,实现自定义编辑
.setPermissionsInterceptListener(); 拦截相册权限处理事件,实现自定义权限
.setSelectLimitTipsListener();拦截选择限制事件,可实现自定义提示
.setSelectFilterListener();拦截不支持的选择项
.isCameraForegroundService(); 拍照时是否开启一个前台服务 
.setRequestedOrientation(); 设置屏幕旋转方向
.setSelectedData(); 相册已选数据
.setRecyclerAnimationMode(); 相册列表动画效果
.setImageSpanCount(); 相册列表每行显示个数
.isDisplayCamera(); 是否显示相机入口
.isPageStrategy(); 是否开启分页模式
.selectionMode(); 单选或是多选
.setMaxSelectNum(); 图片最大选择数量
.setMinSelectNum(); 图片最小选择数量
.setMaxVideoSelectNum(); 视频最大选择数量
.setMinVideoSelectNum(); 视频最小选择数量
.setRecordVideoMaxSecond(); 视频录制最大时长
.setRecordVideoMinSecond(); 视频录制最小时长
.setFilterVideoMaxSecond(); 过滤视频最大时长
.setFilterVideoMinSecond(); 过滤视频最小时长
.setSelectMaxDurationSecond(); 选择最大时长视频或音频
.setSelectMinDurationSecond(); 选择最小时长视频或音频
.setVideoQuality(); 系统相机录制视频质量
.isQuickCapture(); 使用系统摄像机录制后,是否支持使用系统播放器立即播放视频
.isPreviewAudio(); 是否支持音频预览
.isPreviewImage(); 是否支持预览图片
.isPreviewVideo(); 是否支持预览视频
.isPreviewFullScreenMode(); 预览点击全屏效果
.isEmptyResultReturn(); 支持未选择返回
.isWithSelectVideoImage(); 是否支持视频图片同选
.isSelectZoomAnim(); 选择缩略图缩放效果
.isOpenClickSound(); 是否开启点击音效
.isCameraAroundState(); 是否开启前置摄像头;系统相机 只支持部分机型
.isCameraRotateImage(); 拍照是否纠正旋转图片
.isGif(); 是否显示gif文件
.isWebp(); 是否显示webp文件
.isBmp(); 是否显示bmp文件
.isHidePreviewDownload(); 是否隐藏预览下载功能
.isAutoScalePreviewImage(); 预览图片自动放大充满屏幕
.setOfAllCameraType(); isWithSelectVideoImage模式下相机优先使用权
.isMaxSelectEnabledMask(); 达到最大选择数是否开启禁选蒙层
.isSyncCover(); isPageModel模式下是否强制同步封面,默认false
.isAutomaticTitleRecyclerTop(); 点击相册标题是否快速回到第一项
.isFastSlidingSelect(); 快速滑动选择
.isDirectReturnSingle(); 单选时是否立即返回
.setCameraImageFormat(); 拍照图片输出格式
.setCameraImageFormatForQ(); 拍照图片输出格式,Android Q以上 
.setCameraVideoFormat(); 拍照视频输出格式
.setCameraVideoFormatForQ(); 拍照视频输出格式,Android Q以上
.setOutputCameraDir(); 使用相机输出路径
.setOutputAudioDir();使用录音输出路径
.setOutputCameraImageFileName(); 图片输出文件名
.setOutputCameraVideoFileName(); 视频输出文件名
.setOutputAudioFileName(); 录音输出文件名
.setQuerySandboxDir(); 查询指定目录下的资源
.isOnlyObtainSandboxDir(); 是否只查询指定目录下的资源
.setFilterMaxFileSize(); 过滤最大文件
.setFilterMinFileSize(); 过滤最小文件
.setSelectMaxFileSize(); 最大可选文件大小
.setSelectMinFileSize(); 最小可选文件大小
.setQueryOnlyMimeType(); 查询指定文件类型
.setSkipCropMimeType(); 跳过不需要裁剪的类型
  1. 最后差不多就可以开始用了,建议大家把源码下下来看看作者是怎么用的
// 进入相册
PictureSelector.create(this)
        .openGallery(SelectMimeType.ofImage())
        .setImageEngine(GlideEngine.createGlideEngine()) // 这里就是设置图片加载引擎
        .setMaxSelectNum(maxSelectNum)
        .setSelectedData(adapter.getData()) // 设置已被选中的数据
        .forResult(PictureConfig.CHOOSE_REQUEST);


/**
* 图片选择器回调
 */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
    
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
    
    
        if (requestCode == PictureConfig.CHOOSE_REQUEST || requestCode == PictureConfig.REQUEST_CAMERA) {
    
    
            ArrayList<LocalMedia> result = PictureSelector.obtainSelectorList(data);
            analyticalSelectResults(result);
        }
    } else if (resultCode == RESULT_CANCELED) {
    
    
        Log.i("TAG", "onActivityResult PictureSelector Cancel");
    }
}

/**
 * 处理选择结果
 *
 * @param result
 */
private void analyticalSelectResults(ArrayList<LocalMedia> result) {
    
    
    for (LocalMedia media : result) {
    
    
        if (media.getWidth() == 0 || media.getHeight() == 0) {
    
    
            if (PictureMimeType.isHasImage(media.getMimeType())) {
    
    
                MediaExtraInfo imageExtraInfo = MediaUtils.getImageSize(this, media.getPath());
                media.setWidth(imageExtraInfo.getWidth());
                media.setHeight(imageExtraInfo.getHeight());
            } else if (PictureMimeType.isHasVideo(media.getMimeType())) {
    
    
                MediaExtraInfo videoExtraInfo = MediaUtils.getVideoSize(this, media.getPath());
                media.setWidth(videoExtraInfo.getWidth());
                media.setHeight(videoExtraInfo.getHeight());
            }
        }
//            Log.i(TAG, "文件名: " + media.getFileName());
//            Log.i(TAG, "是否压缩:" + media.isCompressed());
//            Log.i(TAG, "压缩:" + media.getCompressPath());
//            Log.i(TAG, "初始路径:" + media.getPath());
//            Log.i(TAG, "绝对路径:" + media.getRealPath());
//            Log.i(TAG, "是否裁剪:" + media.isCut());
//            Log.i(TAG, "裁剪:" + media.getCutPath());
//            Log.i(TAG, "是否开启原图:" + media.isOriginal());
//            Log.i(TAG, "原图路径:" + media.getOriginalPath());
//            Log.i(TAG, "沙盒路径:" + media.getSandboxPath());
//            Log.i(TAG, "水印路径:" + media.getWatermarkPath());
//            Log.i(TAG, "视频缩略图:" + media.getVideoThumbnailPath());
//            Log.i(TAG, "原始宽高: " + media.getWidth() + "x" + media.getHeight());
//            Log.i(TAG, "裁剪宽高: " + media.getCropImageWidth() + "x" + media.getCropImageHeight());
//            Log.i(TAG, "文件大小: " + media.getSize());



        mImageList.add(new File(media.getRealPath())); // 接收已选图片地址,用于接口上传图片
    }
}

把源码下载下来,看看demo是怎么写的。
参考文章:图片选择器:PictureSelector

猜你喜欢

转载自blog.csdn.net/qq_43227422/article/details/124313686