权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
添加依赖
maven { url 'https://jitpack.io' }
implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0'
避免报错
然后因为PictureSelector需要项目minSdkVersion要大于或者等于19
然后最好添加
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
如果出现限制dex大小添加
multiDexEnabled true
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
applicationId "com.wd.circlesharingdemo"
minSdkVersion 19
targetSdkVersion 30
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
基本使用
PictureSelector.create(activity)
.openGallery(PictureMimeType.ofImage())//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
//.theme()//主题样式(不设置为默认样式) 也可参考demo values/styles下 例如:R.style.picture.white.style
.maxSelectNum(maxSize)// 最大图片选择数量 int
.minSelectNum(1)// 最小选择数量 int
.imageEngine(GlideEngine.createGlideEngine())
.imageSpanCount(3)// 每行显示个数 int
.isCamera(true)// 是否显示拍照按钮 true or false
.isZoomAnim(true)// 图片列表点击 缩放效果 默认true
.isEnableCrop(true)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.minimumCompressSize(100)// 小于100kb的图片不压缩
.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
更多使用(按需添加)
PictureSelector.create(activity)
.openGallery(PictureMimeType.ofImage())//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
//.theme()//主题样式(不设置为默认样式) 也可参考demo values/styles下 例如:R.style.picture.white.style
.maxSelectNum(maxSize)// 最大图片选择数量 int
.minSelectNum(1)// 最小选择数量 int
.imageSpanCount(3)// 每行显示个数 int
.imageEngine(GlideEngine.createGlideEngine())
//.selectionMode()// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
//.isPreviewImage(true)// 是否可预览图片 true or false
//.isPreviewVideo()// 是否可预览视频 true or false
//.freeStyleCropEnabled() // 是否可播放音频 true or false
.isCamera(false)// 是否显示拍照按钮 true or false
//.imageFormat(PictureMimeType.PNG)// 拍照保存图片格式后缀,默认jpeg
.isZoomAnim(true)// 图片列表点击 缩放效果 默认true
//.setOutputCameraPath("/CustomPath")// 自定义拍照保存路径,可不填
.isEnableCrop(true)// 是否裁剪 true or false
//.isCompress(true)// 是否压缩 true or false
//.withAspectRatio()// int 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
//.hideBottomControls()// 是否显示uCrop工具栏,默认不显示 true or false
//.isGif(false)// 是否显示gif图片 true or false
//.compressSavePath(getPath())//压缩图片保存地址
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
//.circleDimmedLayer()// 是否圆形裁剪 true or false
//.showCropFrame()// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
//.showCropGrid()// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
//.isOpenClickSound(false)// 是否开启点击声音 true or false
//.selectionData()// 是否传入已选图片 List<LocalMedia> list
//.isPreviewEggs()// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) true or false
//.cutOutQuality(90)// 裁剪压缩质量 默认90 int
.minimumCompressSize(100)// 小于100kb的图片不压缩
//.synOrAsy(true)//同步true或异步false 压缩 默认同步
//.cropImageWideHigh()// 裁剪宽高比,设置如果大于图片本身宽高则无效 int
//.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
//.videoQuality()// 视频录制质量 0 or 1 int
//.videoMaxSecond(15)// 显示多少秒以内的视频or音频也可适用 int
//.videoMinSecond(10)// 显示多少秒以内的视频or音频也可适用 int
//.recordVideoSecond()//视频秒数录制 默认60s int
.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
然后在onActivityResult里面获取图片集合
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
// 结果回调
List<LocalMedia> selectList = PictureSelector.obtainMultipleResult(data);
//在这里补充一下因为现在的数据格式是LocalMedia需要进行转化不能强转这样会找不到路径的
showSelectPic(selectList);
}
}
经过测试拍照上传时会出现上传不上去的情况我还进行一次压缩,拍照成功上传
/**
* 关于图片的工具类压缩等
*/
public class BitmapUtil {
private static String PHOTO_FILE_NAME = "PMSManagerPhoto";
/**
* 获取图片的旋转角度
*
* @param filePath
* @return
*/
public static int getRotateAngle(String filePath) {
int rotate_angle = 0;
try {
ExifInterface exifInterface = new ExifInterface(filePath);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotate_angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate_angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate_angle = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return rotate_angle;
}
/**
* 旋转图片角度
*
* @param angle
* @param bitmap
* @return
*/
public static Bitmap setRotateAngle(int angle, Bitmap bitmap) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postRotate(angle);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
//转换为圆形状的bitmap
public static Bitmap createCircleImage(Bitmap source) {
int length = source.getWidth() < source.getHeight() ? source.getWidth() : source.getHeight();
Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);
canvas.drawCircle(length / 2, length / 2, length / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
return target;
}
/**
* 图片压缩-质量压缩
*
* @param filePath 源图片路径
* @return 压缩后的路径
*/
public static String compressImage(String filePath) {
//原文件
File oldFile = new File(filePath);
//压缩文件路径 照片路径/
String targetPath = oldFile.getPath();
int quality = 50;//压缩比例0-100
Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
int degree = getRotateAngle(filePath);//获取相片拍摄角度
if (degree != 0) {//旋转照片角度,防止头像横着显示
bm = setRotateAngle(degree,bm);
}
File outputFile = new File(targetPath);
try {
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
//outputFile.createNewFile();
} else {
outputFile.delete();
}
FileOutputStream out = new FileOutputStream(outputFile);
bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
return filePath;
}
return outputFile.getPath();
}
/**
* 根据路径获得图片信息并按比例压缩,返回bitmap
*/
public static Bitmap getSmallBitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高
BitmapFactory.decodeFile(filePath, options);
// 计算缩放比(在上传图片的时候可能你会感觉图片有些模糊可以调节缩放比例到适合)
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// 完整解析图片返回bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
/**
* 质量压缩Bitmap方法
* @param image
* @return
*/
public static Bitmap compressImage1(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 90;
while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset(); // 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
return bitmap;
}
/**
* 以下是bitmap转file(带压缩转换
* @param context
* @param bitmap
* @param kb
* @return
*/
/*
* bitmap转file(带压缩转换 可以自己设定 默认100kb) 上传服务器的时候使用
*/
public static String bitmapToFileWhithCompress(Context context , Bitmap bitmap , int kb) {
String sdPath = getDiskCacheDir(context);
String name = new DateFormat().format("yyyyMMddhhmmss",
Calendar.getInstance(Locale.CHINA)) + ".jpg";
String picPath = sdPath + "/" + name;
File outImage = new File(picPath);
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(outImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//调用了下面封装好的压缩方法返回已经压缩的bitmap 然后再调用cmpress 输出流把bitmap转走 100不再压缩 因为已经压缩好了
compressImage(bitmap,kb).compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
//返回一个压缩图片绝对路径
return picPath;
}
/**
* 获取缓存文件夹的相对路径
*/
public static String getDiskCacheDir(Context ctx) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = ctx.getExternalCacheDir().getPath();
} else {
cachePath = ctx.getCacheDir().getPath();
}
return cachePath;
}
//无回调有返回值的压缩方法
public static Bitmap compressImage(Bitmap image , int kb) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > kb) { //循环判断如果压缩后图片是否大于设定的kb,大于继续压缩
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
options -= 10;//每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
return bitmap;
}
/**
* file转bitmap(进行压缩,防止内存泄漏)
*/
public static Bitmap fileToBitmap(String imagePath,int kb) {
Bitmap bitmap = null;
try {
File file = new File(imagePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
FileInputStream fis = new FileInputStream(file);
bitmap = BitmapFactory.decodeStream(fis, null, options);
//将bitmap进行压缩防止内存泄漏
bitmap = compressImage(bitmap,kb);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
/*
* bitmap转file(原图转换)
*/
public static String bitmapToFile(Context context,Bitmap bitmap) {
String sdPath = getDiskCacheDir(context);
String name = new DateFormat().format("yyyyMMddhhmmss",
Calendar.getInstance(Locale.CHINA)) + ".jpg";
String picPath = sdPath + "/" + name;
File outImage = new File(picPath);
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(outImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
//返回一个图片路径
return picPath;
}
}
private void showSelectPic(List<LocalMedia> result) {
fileList = new ArrayList<>();
for (int i = 0; i < result.size(); i++) {
String path;
//判断是否10.0以上
if (Build.VERSION.SDK_INT >= 29) {
path = result.get(i).getAndroidQToPath();
} else {
path = result.get(i).getPath();
}
newPath = BitmapUtil.compressImage(path);//压缩
fileList.add(new File(newPath));//将路径放到File集合里面去传到接口
Log.e(TAG, "图片链接: " + path);
//请求网络上传图片
okRE.getInstance().postMoreImage(urls,headmap,map,fileList, new okRE.NetCallBack() {
@Override
public void onSuccess(String string) {
Toast.makeText(MainActivity.this, string+"", Toast.LENGTH_SHORT).show();
}
@Override
public void onFail(String string) {
Toast.makeText(MainActivity.this, string+"", Toast.LENGTH_SHORT).show();
}
});
}
图片预览
//图片选择器自带预览
PictureSelector.create(MainActivity.this)
.themeStyle(R.style.picture_default_style)
.isNotPreviewDownload(true)//是否显示保存弹框
.imageEngine(GlideEngine.createGlideEngine()) // 选择器展示不出图片则添加
.openExternalPreview(position, “选择的图片集合”);
使用方法
private List<LocalMedia> selectList = new ArrayList<>();
private List<String> Listss = new ArrayList<>();//比如这个是网络请求图片集合
private List<String> List = new ArrayList<>();//后台返回多图数据切割后集合
//注意如果多图切割
String[] split = picture.split(",");
List.add(split[i]) //看后台返回数据情况也可不进行切割
for (int i = 0; i < List.size(); i++) {
LocalMedia localMedia = new LocalMedia();
localMedia.setPath(list.get(i));
selectList.add(localMedia);
}
PictureSelector.create(MainActivity.this)
.themeStyle(R.style.picture_default_style)
.isNotPreviewDownload(true)//是否显示保存弹框
.imageEngine(GlideEngine.createGlideEngine())
.openExternalPreview(position, selectList);
=============================================
注意不要忘记动态权限不加就崩了
implementation 'com.github.tbruyelle:rxpermissions:0.9.0'
final RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
rxPermissions.request(Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE
,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE)
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean granted) {
if (granted) { // 在android 6.0之前会默认返回true
} else {
}
}
});
============================================================
正题
以上就是PictureSelector的简单使用如果需要项目demo
PictureSelector的使用demo
感谢观看