Android 截屏的原理:获取具体需要截屏的区域的 Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途
在截屏功能中,有时需要截取全屏的内容,有时需要截取超过一屏的内容(比如:Listview,Scrollview,RecyclerView)。下面介绍各种场景获取 Bitmap 的方法
获取当前 Window 的 DrawingCache 的方式,即 decorView 的 DrawingCache
- /**
- * shot the current screen ,with the status but the status is trans *
- *
- * @param ctx current activity
- */
- public static Bitmap shotActivity(Activity ctx) {
- View view = ctx.getWindow().getDecorView();
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
- Bitmap bp = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
- view.setDrawingCacheEnabled(false);
- view.destroyDrawingCache();
- return bp;
- }
获取当前 View 的 DrawingCache
- public static Bitmap getViewBp(View v) {
- if (null == v) {
- return null;
- }
- v.setDrawingCacheEnabled(true);
- v.buildDrawingCache();
- if (Build.VERSION.SDK_INT >= 11) {
- v.measure(MeasureSpec.makeMeasureSpec(v.getWidth(),
- MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
- v.getHeight(), MeasureSpec.EXACTLY));
- v.layout((int) v.getX(), (int) v.getY(),
- (int) v.getX() + v.getMeasuredWidth(),
- (int) v.getY() + v.getMeasuredHeight());
- } else {
- v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
- }
- Bitmap b = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
- v.setDrawingCacheEnabled(false);
- v.destroyDrawingCache();
- return b;
- }
在滚动视图中,如果当前 View 并没有在视图中全部绘制出来,我们可以利用 View 的 ScrollTo() 和 ScrollBy() 方法来移动画布,同时获取当前 View 的可视部分的 DrawingCache,最后进行拼接得到其 Bitmap,参考: PGSSoft/scrollscreenshot@[Github] 。
三个截屏中,ScrollView 最简单,因为 ScrollView 只有一个 childView,虽然没有全部显示在界面上,但是已经全部渲染绘制,因此可以直接 调用
来完成截图
- scrollView.draw(canvas)
- public static Bitmap shotScrollView(ScrollView scrollView) {
- int h = 0;
- Bitmap bitmap = null;
- for (int i = 0; i < scrollView.getChildCount(); i++) {
- h += scrollView.getChildAt(i).getHeight();
- scrollView.getChildAt(i).setBackgroundColor(Color.parseColor("#ffffff"));
- }
- bitmap = Bitmap.createBitmap(scrollView.getWidth(), h, Bitmap.Config.RGB_565);
- final Canvas canvas = new Canvas(bitmap);
- scrollView.draw(canvas);
- return bitmap;
- }
而 ListView 就是会回收与重用 Item,并且只会绘制在屏幕上显示的 ItemView,根据 stackoverflow 上大神的建议,采用一个 List 来存储 Item 的视图,这种方案依然不够好,当 Item 足够多的时候,可能会发生 oom。
- public static Bitmap shotListView(ListView listview) {
- ListAdapter adapter = listview.getAdapter();
- int itemscount = adapter.getCount();
- int allitemsheight = 0;
- List < Bitmap > bmps = new ArrayList < Bitmap > ();
- for (int i = 0; i < itemscount; i++) {
- View childView = adapter.getView(i, null, listview);
- childView.measure(View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
- childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
- childView.setDrawingCacheEnabled(true);
- childView.buildDrawingCache();
- bmps.add(childView.getDrawingCache());
- allitemsheight += childView.getMeasuredHeight();
- }
- Bitmap bigbitmap = Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight, Bitmap.Config.ARGB_8888);
- Canvas bigcanvas = new Canvas(bigbitmap);
- Paint paint = new Paint();
- int iHeight = 0;
- for (int i = 0; i < bmps.size(); i++) {
- Bitmap bmp = bmps.get(i);
- bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
- iHeight += bmp.getHeight();
- bmp.recycle();
- bmp = null;
- }
- return bigbitmap;
- }
我们都知道,在新的 Android 版本中,已经可以用 RecyclerView 来代替使用 ListView 的场景,相比较 ListView,RecyclerView 对 Item View 的缓存支持的更好。可以采用和 ListView 相同的方案,这里也是在 stackoverflow 上看到的方案。
- public static Bitmap shotRecyclerView(RecyclerView view) {
- RecyclerView.Adapter adapter = view.getAdapter();
- Bitmap bigBitmap = null;
- if (adapter != null) {
- int size = adapter.getItemCount();
- int height = 0;
- Paint paint = new Paint();
- int iHeight = 0;
- final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
- // Use 1/8th of the available memory for this memory cache.
- final int cacheSize = maxMemory / 8;
- LruCache < String,
- Bitmap > bitmaCache = new LruCache < >(cacheSize);
- for (int i = 0; i < size; i++) {
- RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
- adapter.onBindViewHolder(holder, i);
- holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
- holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
- holder.itemView.setDrawingCacheEnabled(true);
- holder.itemView.buildDrawingCache();
- Bitmap drawingCache = holder.itemView.getDrawingCache();
- if (drawingCache != null) {
- bitmaCache.put(String.valueOf(i), drawingCache);
- }
- height += holder.itemView.getMeasuredHeight();
- }
- bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);
- Canvas bigCanvas = new Canvas(bigBitmap);
- Drawable lBackground = view.getBackground();
- if (lBackground instanceof ColorDrawable) {
- ColorDrawable lColorDrawable = (ColorDrawable) lBackground;
- int lColor = lColorDrawable.getColor();
- bigCanvas.drawColor(lColor);
- }
- for (int i = 0; i < size; i++) {
- Bitmap bitmap = bitmaCache.get(String.valueOf(i));
- bigCanvas.drawBitmap(bitmap, 0f, iHeight, paint);
- iHeight += bitmap.getHeight();
- bitmap.recycle();
- }
- }
- return bigBitmap;
- }
上面的方法在截取存在异步加载图片的 RecyclerView 时候会出现加载不出图片的情况, 这里再补充一种滚动式截屏的方法
- public static void screenShotRecycleView(final RecyclerView mRecyclerView, final RecycleViewRecCallback callBack) {
- if (mRecyclerView == null) {
- return;
- }
- BaseListFragment.MyAdapter adapter = (BaseListFragment.MyAdapter) mRecyclerView.getAdapter();
- final Paint paint = new Paint();
- final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
- // Use 1/8th of the available memory for this memory cache.
- final int cacheSize = maxMemory / 8;
- LruCache < String,
- Bitmap > bitmaCache = new LruCache < >(cacheSize);
- final int oneScreenHeight = mRecyclerView.getMeasuredHeight();
- int shotHeight = 0;
- if (adapter != null && adapter.getData().size() > 0) {
- int headerSize = adapter.getHeaderLayoutCount();
- int dataSize = adapter.getData().size();
- for (int i = 0; i < headerSize + dataSize; i++) {
- BaseViewHolder holder = (BaseViewHolder) adapter.createViewHolder(mRecyclerView, adapter.getItemViewType(i));
- if (i >= headerSize) adapter.startConvert(holder, adapter.getData().get(i - headerSize));
- holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(mRecyclerView.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
- holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
- holder.itemView.setDrawingCacheEnabled(true);
- holder.itemView.buildDrawingCache();
- Bitmap drawingCache = holder.itemView.getDrawingCache();
- //holder.itemView.destroyDrawingCache();//释放缓存占用的资源
- if (drawingCache != null) {
- bitmaCache.put(String.valueOf(i), drawingCache);
- }
- shotHeight += holder.itemView.getHeight();
- if (shotHeight > 12000) {
- //设置截图最大值
- if (callBack != null) callBack.onRecFinished(null);
- return;
- }
- }
- //添加底部高度(加载更多或loading布局高度,此处为固定值:)
- final int footHight = Util.dip2px(mRecyclerView.getContext(), 42);
- shotHeight += footHight;
- //返回到顶部
- while (mRecyclerView.canScrollVertically( - 1)) {
- mRecyclerView.scrollBy(0, -oneScreenHeight);
- }
- //绘制截图的背景
- final Bitmap bigBitmap = Bitmap.createBitmap(mRecyclerView.getMeasuredWidth(), shotHeight, Bitmap.Config.ARGB_8888);
- final Canvas bigCanvas = new Canvas(bigBitmap);
- Drawable lBackground = mRecyclerView.getBackground();
- if (lBackground instanceof ColorDrawable) {
- ColorDrawable lColorDrawable = (ColorDrawable) lBackground;
- int lColor = lColorDrawable.getColor();
- bigCanvas.drawColor(lColor);
- }
- final int[] drawOffset = {
- 0
- };
- final Canvas canvas = new Canvas();
- if (shotHeight <= oneScreenHeight) {
- //仅有一页
- Bitmap bitmap = Bitmap.createBitmap(mRecyclerView.getWidth(), mRecyclerView.getHeight(), Bitmap.Config.ARGB_8888);
- canvas.setBitmap(bitmap);
- mRecyclerView.draw(canvas);
- if (callBack != null) callBack.onRecFinished(bitmap);
- } else {
- //超过一页
- final int finalShotHeight = shotHeight;
- mRecyclerView.postDelayed(new Runnable() {@Override public void run() {
- if ((drawOffset[0] + oneScreenHeight < finalShotHeight)) {
- //超过一屏
- Bitmap bitmap = Bitmap.createBitmap(mRecyclerView.getWidth(), mRecyclerView.getHeight(), Bitmap.Config.ARGB_8888);
- canvas.setBitmap(bitmap);
- mRecyclerView.draw(canvas);
- bigCanvas.drawBitmap(bitmap, 0, drawOffset[0], paint);
- drawOffset[0] += oneScreenHeight;
- mRecyclerView.scrollBy(0, oneScreenHeight);
- try {
- bitmap.recycle();
- } catch(Exception ex) {
- ex.printStackTrace();
- }
- mRecyclerView.postDelayed(this, 10);
- } else {
- //不足一屏时的处理
- int leftHeight = finalShotHeight - drawOffset[0] - footHight;
- mRecyclerView.scrollBy(0, leftHeight);
- int top = oneScreenHeight - (finalShotHeight - drawOffset[0]);
- if (top > 0 && leftHeight > 0) {
- Bitmap bitmap = Bitmap.createBitmap(mRecyclerView.getWidth(), mRecyclerView.getHeight(), Bitmap.Config.ARGB_8888);
- canvas.setBitmap(bitmap);
- mRecyclerView.draw(canvas);
- //截图,只要补足的那块图
- bitmap = Bitmap.createBitmap(bitmap, 0, top, bitmap.getWidth(), leftHeight, null, false);
- bigCanvas.drawBitmap(bitmap, 0, drawOffset[0], paint);
- try {
- bitmap.recycle();
- } catch(Exception ex) {
- ex.printStackTrace();
- }
- }
- if (callBack != null) callBack.onRecFinished(bigBitmap);
- }
- }
- },
- 10);
- }
- }
- }
- public interface RecycleViewRecCallback {
- void onRecFinished(Bitmap bitmap);
- }
相信有不少小伙伴用 BRVH 第三方库来做 recycleview 的适配器的。使用这个库的话再用上面的方法会报角标越界的错误,看了 BRVH 的源码
- public void onBindViewHolder(ViewHolder holder, int positions) {
- int viewType = holder.getItemViewType();
- switch (viewType) {
- case 0:
- this.convert((BaseViewHolder) holder, this.mData.get(holder.getLayoutPosition() - this.getHeaderLayoutCount()));
- case 273:
- case 819:
- case 1365:
- break;
- case 546:
- this.addLoadMore(holder);
- break;
- default:
- this.convert((BaseViewHolder) holder, this.mData.get(holder.getLayoutPosition() - this.getHeaderLayoutCount()));
- this.onBindDefViewHolder((BaseViewHolder) holder, this.mData.get(holder.getLayoutPosition() - this.getHeaderLayoutCount()));
- }
- }
在调用
时,因为里面的 position 参数未使用,里面用的计算
- adapter.onBindViewHolder
的值一直是 - 1 导致角标越界报错。
- holder.getLayoutPosition() - this.getHeaderLayoutCount()
本人理解,RecyclerView 的截屏原理是,首先构造每个 item 的 ViewHolder,然后调用具体设置数据到每个 item 的方法,此时 cache 中就存有 item 的内容,此时绘制就能获取到完整的内容。采用 v7 包中的 onBindViewHolder 方法即可,或者是 BRVH 的 convert 方法,可以看到 BRVH 中没有暴露出这个方法,而且唯一暴露出的 onBindViewHolder 还会报角标越界错误,此时我们就需要在 BRVH 的基础上暴露出 convert 即可,代码如下
- public class MyAdapter extends BaseQuickAdapter < T > {
- public MyAdapter() {
- super(getItemLayoutResId(), datas);
- }
- /**
- * 用于对外暴露convert方法,构造缓存视图(截屏用)
- * @param viewHolder
- * @param t
- */
- public void startConvert(BaseViewHolder viewHolder, T t) {
- convert(viewHolder, t);
- }
- @Override protected void convert(BaseViewHolder viewHolder, T t) {
- bindView(viewHolder, t);
- }
- }
然后将上面所述的获取 Bitmap 方法修改一下
- /**
- * 截取recycler view
- */
- public static Bitmap getRecyclerViewScreenshot(RecyclerView view) {
- BaseListFragment.MyAdapter adapter = (BaseListFragment.MyAdapter) view.getAdapter();
- Bitmap bigBitmap = null;
- if (adapter != null) {
- int size = adapter.getData().size();
- int height = 0;
- Paint paint = new Paint();
- int iHeight = 0;
- final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
- // Use 1/8th of the available memory for this memory cache.
- final int cacheSize = maxMemory / 8;
- LruCache < String,
- Bitmap > bitmaCache = new LruCache < >(cacheSize);
- for (int i = 0; i < size; i++) {
- BaseViewHolder holder = (BaseViewHolder) adapter.createViewHolder(view, adapter.getItemViewType(i));
- //此处需要调用convert方法,否则绘制出来的都是空的item
- adapter.startConvert(holder, adapter.getData().get(i));
- holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
- holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
- holder.itemView.setDrawingCacheEnabled(true);
- holder.itemView.buildDrawingCache();
- Bitmap drawingCache = holder.itemView.getDrawingCache();
- if (drawingCache != null) {
- bitmaCache.put(String.valueOf(i), drawingCache);
- }
- height += holder.itemView.getMeasuredHeight();
- }
- bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);
- Canvas bigCanvas = new Canvas(bigBitmap);
- Drawable lBackground = view.getBackground();
- if (lBackground instanceof ColorDrawable) {
- ColorDrawable lColorDrawable = (ColorDrawable) lBackground;
- int lColor = lColorDrawable.getColor();
- bigCanvas.drawColor(lColor);
- }
- for (int i = 0; i < size; i++) {
- Bitmap bitmap = bitmaCache.get(String.valueOf(i));
- bigCanvas.drawBitmap(bitmap, 0f, iHeight, paint);
- iHeight += bitmap.getHeight();
- bitmap.recycle();
- }
- }
- return bigBitmap;
- }
比如四张合成一张
- /**
- * 将四张图拼成一张
- *
- * @param pic1 图一
- * @param pic2 图二
- * @param pic3 图三
- * @param pic4 图四
- * @return only_bitmap
- * 详情见说明:{@link com.bertadata.qxb.util.ScreenShotUtils}
- */
- public static Bitmap combineBitmapsIntoOnlyOne(Bitmap pic1, Bitmap pic2, Bitmap pic3, Bitmap pic4, Activity context) {
- int w_total = pic2.getWidth();
- int h_total = pic1.getHeight() + pic2.getHeight() + pic3.getHeight() + pic4.getHeight();
- int h_pic1 = pic1.getHeight();
- int h_pic4 = pic4.getHeight();
- int h_pic12 = pic1.getHeight() + pic2.getHeight();
- //此处为防止OOM需要对高度做限制
- if (h_total > HEIGHTLIMIT) {
- return null;
- }
- Bitmap only_bitmap = Bitmap.createBitmap(w_total, h_total, Bitmap.Config.ARGB_4444);
- Canvas canvas = new Canvas(only_bitmap);
- canvas.drawColor(ContextCompat.getColor(context, R.color.color_content_bg));
- canvas.drawBitmap(pic1, 0, 0, null);
- canvas.drawBitmap(pic2, 0, h_pic1, null);
- canvas.drawBitmap(pic3, 0, h_pic12, null);
- canvas.drawBitmap(pic4, 0, h_total - h_pic4, null);
- return only_bitmap;
- }
- /**
- * 将传入的Bitmap合理压缩后输出到系统截屏目录下
- * 命名格式为:Screenshot+时间戳+启信宝报名.jpg
- * 同时通知系统重新扫描系统文件
- *
- * @param pic1 图一 标题栏截图
- * @param pic2 图二 scrollview截图
- * @param context 用于通知重新扫描文件系统,为提升性能可去掉
- * 详情见说明:{@link com.bertadata.qxb.util.ScreenShotUtils}
- */
- public static void savingBitmapIntoFile(final Bitmap pic1, final Bitmap pic2, final Activity context, final BitmapAndFileCallBack callBack) {
- if (context == null || context.isFinishing()) {
- return;
- }
- Thread thread = new Thread(new Runnable() {@Override public void run() {
- String fileReturnPath = "";
- int w = pic1.getWidth();
- Bitmap bottom = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_picture_combine_bottom);
- Bitmap top_banner = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_picture_combine_top);
- Bitmap bitmap_bottom = anyRatioCompressing(bottom, (float) w / bottom.getWidth(), (float) w / bottom.getWidth());
- Bitmap bitmap_top = anyRatioCompressing(top_banner, (float) w / bottom.getWidth(), (float) w / bottom.getWidth());
- final Bitmap only_bitmap = combineBitmapsIntoOnlyOne(bitmap_top, pic1, pic2, bitmap_bottom, context);
- // 获取当前时间
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-ms", Locale.getDefault());
- String data = sdf.format(new Date());
- // 获取内存路径
- // 设置图片路径+命名规范
- // 声明输出文件
- String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
- String fileTitle = "Screenshot_" + data + "_com.bertadata.qxb.biz_info.jpg";
- String filePath = storagePath + "/DCIM/";
- final String fileAbsolutePath = filePath + fileTitle;
- File file = new File(fileAbsolutePath);
- /**
- * 质压与比压结合
- * 分级压缩
- * 输出文件
- */
- if (only_bitmap != null) {
- try {
- // 首先,对原图进行一步质量压缩,形成初步文件
- FileOutputStream fos = new FileOutputStream(file);
- only_bitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos);
- // 另建一个文件other_file预备输出
- String other_fileTitle = "Screenshot_" + data + "_com.bertadata.qxb.jpg";
- String other_fileAbsolutePath = filePath + other_fileTitle;
- File other_file = new File(other_fileAbsolutePath);
- FileOutputStream other_fos = new FileOutputStream(other_file);
- // 其次,要判断质压之后的文件大小,按文件大小分级进行处理
- long file_size = file.length() / 1024; // size of file(KB)
- if (file_size < 0 || !(file.exists())) {
- // 零级: 文件判空
- throw new NullPointerException();
- } else if (file_size > 0 && file_size <= 256) {
- // 一级: 直接输出
- deleteFile(other_file);
- // 通知刷新文件系统,显示最新截取的图文件
- fileReturnPath = fileAbsolutePath;
- context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + fileAbsolutePath)));
- } else if (file_size > 256 && file_size <= 768) {
- // 二级: 简单压缩:压缩为原比例的3/4,质压为50%
- anyRatioCompressing(only_bitmap, (float) 3 / 4, (float) 3 / 4).compress(Bitmap.CompressFormat.JPEG, 40, other_fos);
- deleteFile(file);
- // 通知刷新文件系统,显示最新截取的图文件
- fileReturnPath = other_fileAbsolutePath;
- context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + other_fileAbsolutePath)));
- } else if (file_size > 768 && file_size <= 1280) {
- // 三级: 中度压缩:压缩为原比例的1/2,质压为40%
- anyRatioCompressing(only_bitmap, (float) 1 / 2, (float) 1 / 2).compress(Bitmap.CompressFormat.JPEG, 40, other_fos);
- deleteFile(file);
- // 通知刷新文件系统,显示最新截取的图文件
- fileReturnPath = other_fileAbsolutePath;
- context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + other_fileAbsolutePath)));
- } else if (file_size > 1280 && file_size <= 2048) {
- // 四级: 大幅压缩:压缩为原比例的1/3,质压为40%
- anyRatioCompressing(only_bitmap, (float) 1 / 3, (float) 1 / 3).compress(Bitmap.CompressFormat.JPEG, 40, other_fos);
- deleteFile(file);
- // 通知刷新文件系统,显示最新截取的图文件
- fileReturnPath = other_fileAbsolutePath;
- context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + other_fileAbsolutePath)));
- } else if (file_size > 2048) {
- // 五级: 中度压缩:压缩为原比例的1/2,质压为40%
- anyRatioCompressing(only_bitmap, (float) 1 / 2, (float) 1 / 2).compress(Bitmap.CompressFormat.JPEG, 40, other_fos);
- deleteFile(file);
- // 通知刷新文件系统,显示最新截取的图文件
- fileReturnPath = other_fileAbsolutePath;
- context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + other_fileAbsolutePath)));
- }
- // 注销fos;
- fos.flush();
- other_fos.flush();
- other_fos.close();
- fos.close();
- //callback用于回传保存成功的路径以及Bitmap
- callBack.onSuccess(only_bitmap, fileReturnPath);
- } catch(Exception e) {
- e.printStackTrace();
- }
- } else callBack.onSuccess(null, "");
- }
- });
- thread.start();
- }
- /**
- * 可实现任意宽高比例压缩(宽高压比可不同)的压缩方法(主要用于微压)
- *
- * @param bitmap 源图
- * @param width_ratio 宽压比(float)(0<&&<1)
- * @param height_ratio 高压比(float)(0<&&<1)
- * @return 目标图片
- * <p>
- */
- public static Bitmap anyRatioCompressing(Bitmap bitmap, float width_ratio, float height_ratio) {
- Matrix matrix = new Matrix();
- matrix.postScale(width_ratio, height_ratio);
- return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
- }
本文参考 http://www.cnblogs.com/BoBoMEe/p/4556917.html,并结合自己实际项目操作完成
来源: https://juejin.im/post/5a33403b6fb9a045132abdb6