android 实现图片裁剪功能

今天逛github,偶然发现了一个bilibili的开源图片选择项目 -- boxing

地址:https://github.com/Bilibili/boxing

难受,花了一个多小时,将源码项目的单图选择和单图的选择+裁剪功能给扣了下来,特此与大家分享,便于快速集成!!!

使用步骤

(1)gradle

   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'
    }

(2)AndroidManifest.xml

   申明权限

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.CAMERA"/>

   申明com.yalantis.ucrop.UCropActivity

         <activity
            android:name="com.yalantis.ucrop.UCropActivity"
            android:screenOrientation="portrait"
            android:theme="@style/Boxing.AppTheme.NoActionBar"/>

(3)java代码调用

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<BaseMedia> 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<String> request = Glide.with(img.getContext())
                .load(path)
                .asBitmap();
        if (width > 0 && height > 0) {
            request.override(width, height);
        }
        request.listener(new RequestListener<String, Bitmap>() {
            @Override
            public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
                if (callback != null) {
                    callback.onFail(e);
                    return true;
                }
                return false;
            }

            @Override
            public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> 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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值