今天逛github,偶然发现了一个bilibili的开源图片选择项目 -- boxing
地址:https://github.com/Bilibili/boxing
难受,花了一个多小时,将源码项目的单图选择和单图的选择+裁剪功能给扣了下来,特此与大家分享,便于快速集成!!!
boxing支持三种主流图片加载框架 Glide Fresco Picasso,这里我选择的是 Glide,同时它的裁剪是通过com.yalantis:ucrop:2.2.0实现的。
implementation 'com.github.bumptech.glide:glide:3.7.0'
implementation 'com.bilibili:boxing-impl:1.0.4'
implementation('com.yalantis:ucrop:2.2.0') {
exclude group: 'com.android.support'
exclude group: 'com.squareup.okio'
exclude group: 'com.squareup.okhttp3'
}
申明权限
申明com.yalantis.ucrop.UCropActivity
public class Main5Activity extends AppCompatActivity {
private static final String TAG = "Main5Activity";
private static final int COMPRESS_REQUEST_CODE = 2048;
private static final int REQUEST_CODE = 1024;
private ImageView im;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main5);
im = findViewById(R.id.image8);
//选择glide加载框架 BoxingGlideLoader是自定义实现
IBoxingMediaLoader loader = new BoxingGlideLoader();
BoxingMediaLoader.getInstance().init(loader);
//初始化裁剪功能 BoxingUcrop是自定义实现
BoxingCrop.getInstance().init(new BoxingUcrop());
Button button = findViewById(R.id.main_btn5);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//调用图片单选功能
BoxingConfig singleImgConfig = new BoxingConfig(BoxingConfig.Mode.SINGLE_IMG).withMediaPlaceHolderRes(R.drawable.home);
Boxing.of(singleImgConfig).withIntent(Main5Activity.this, BoxingActivity.class).start(Main5Activity.this, COMPRESS_REQUEST_CODE);
}
});
Button button2 = findViewById(R.id.main_btn6);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取缓存的存储路径
String cachePath = BoxingFileHelper.getCacheDir(Main5Activity.this);
if (TextUtils.isEmpty(cachePath)) {
Toast.makeText(getApplicationContext(),"设备存储读取出错或暂不可用,请稍候重试", Toast.LENGTH_SHORT).show();
return;
}
Uri destUri = new Uri.Builder()
.scheme("file")
.appendPath(cachePath)
.appendPath(String.format(Locale.US, "%s.png", System.currentTimeMillis()))
.build();
//调用图片单选+裁剪功能
BoxingConfig singleCropImgConfig = new BoxingConfig(BoxingConfig.Mode.SINGLE_IMG).withCropOption(new BoxingCropOption(destUri))
.withMediaPlaceHolderRes(R.drawable.images);
Boxing.of(singleCropImgConfig).withIntent(Main5Activity.this, BoxingActivity.class).start(Main5Activity.this, REQUEST_CODE);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
//通过回调获取返回结果
final ArrayList medias = Boxing.getResult(data);
if (requestCode == COMPRESS_REQUEST_CODE) {
BaseMedia media = medias.get(0);
String path;
if (media instanceof ImageMedia) {
path = ((ImageMedia) media).getThumbnailPath();
} else {
path = media.getPath();
}
BoxingMediaLoader.getInstance().displayThumbnail(im, path, 200, 200);
} else if (requestCode == REQUEST_CODE) {
BaseMedia media = medias.get(0);
String path;
if (media instanceof ImageMedia) {
path = ((ImageMedia) media).getThumbnailPath();
} else {
path = media.getPath();
}
BoxingMediaLoader.getInstance().displayThumbnail(im, path, 200, 200);
}
}
}
}
BoxingUcrop.java
package com.example.fyf.myfragment.utils;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import com.bilibili.boxing.loader.IBoxingCrop;
import com.bilibili.boxing.model.config.BoxingCropOption;
import com.yalantis.ucrop.UCrop;
public class BoxingUcrop implements IBoxingCrop {
@Override
public void onStartCrop(Context context, Fragment fragment, @NonNull BoxingCropOption cropConfig,
@NonNull String path, int requestCode) {
Uri uri = new Uri.Builder()
.scheme("file")
.appendPath(path)
.build();
UCrop.Options crop = new UCrop.Options();
// do not copy exif information to crop pictures
// because png do not have exif and png is not Distinguishable
crop.setCompressionFormat(Bitmap.CompressFormat.PNG);
crop.withMaxResultSize(cropConfig.getMaxWidth(), cropConfig.getMaxHeight());
crop.withAspectRatio(cropConfig.getAspectRatioX(), cropConfig.getAspectRatioY());
UCrop.of(uri, cropConfig.getDestination())
.withOptions(crop)
.start(context, fragment, requestCode);
}
@Override
public Uri onCropFinish(int resultCode, Intent data) {
if (data == null) {
return null;
}
Throwable throwable = UCrop.getError(data);
if (throwable != null) {
return null;
}
return UCrop.getOutput(data);
}
}
BoxingGlideLoader.java
public class BoxingGlideLoader implements IBoxingMediaLoader {
@Override
public void displayThumbnail(@NonNull ImageView img, @NonNull String absPath, int width, int height) {
String path = "file://" + absPath;
try {
// https://github.com/bumptech/glide/issues/1531
Glide.with(img.getContext()).load(path).placeholder(R.drawable.images).crossFade().centerCrop().override(width, height).into(img);
} catch(IllegalArgumentException ignore) {
}
}
@Override
public void displayRaw(@NonNull final ImageView img, @NonNull String absPath, int width, int height, final IBoxingCallback callback) {
String path = "file://" + absPath;
BitmapTypeRequest request = Glide.with(img.getContext())
.load(path)
.asBitmap();
if (width > 0 && height > 0) {
request.override(width, height);
}
request.listener(new RequestListener() {
@Override
public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
if (callback != null) {
callback.onFail(e);
return true;
}
return false;
}
@Override
public boolean onResourceReady(Bitmap resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
if (resource != null && callback != null) {
img.setImageBitmap(resource);
callback.onSuccess();
return true;
}
return false;
}
}).into(img);
}
}
demo展示:
我们是大自然的搬运工:参考 https://github.com/Bilibili/boxing/blob/master/README_CN.md