BitmapRegionDecoder
Android加载大图——BitmapRegionDecoder(转)
BitmapRegionDecoder,从API10就引入了。如下图:

看官方文档的说明,这个类就是用来显示指定区域的图像,当原始图像大,你只需要部分图像时,BitmapRegionDecoder特别有用。
二、使用

最主要的就是BitmapRegionDecode.newInstance(...)获取一个对象,然后通过这个对象去调用decodeRegion(...)得到bitmap,最后就可以显示在屏幕上了。考虑到用户可以触摸移动图像,我们用手势控制器GestureDetector来控制图片显示的区域。
public class LargeImageView extends View implements GestureDetector.OnGestureListener {
private static final String TAG = "LargeImageView";
private BitmapRegionDecoder mDecoder;
//绘制的区域
private volatile Rect mRect = new Rect();
private int mScaledTouchSlop;
// 分别记录上次滑动的坐标
private int mLastX = 0;
private int mLastY = 0;
//图片的宽度和高度
private int mImageWidth, mImageHeight;
//手势控制器
private GestureDetector mGestureDetector;
private BitmapFactory.Options options;
public LargeImageView(Context context) {
super(context);
init(context, null);
}
public LargeImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public LargeImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
//设置显示图片的参数,如果对图片质量有要求,就选择ARGB_8888模式
options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
mScaledTouchSlop = ViewConfiguration.get(getContext())
.getScaledTouchSlop();
Log.d(TAG, "sts:" + mScaledTouchSlop);
//初始化手势控制器
mGestureDetector = new GestureDetector(context, this);
//获取图片的宽高
InputStream is = null;
try {
is = context.getResources().getAssets().open("timg.jpg");
//初始化BitmapRegionDecode,并用它来显示图片
mDecoder = BitmapRegionDecoder
.newInstance(is, false);
BitmapFactory.Options tmpOptions = new BitmapFactory.Options();
// 设置为true则只获取图片的宽高等信息,不加载进内存
tmpOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, tmpOptions);
mImageWidth = tmpOptions.outWidth;
mImageHeight = tmpOptions.outHeight;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//把触摸事件交给手势控制器处理
return mGestureDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
mLastX = (int) e.getRawX();
mLastY = (int) e.getRawY();
return true;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
int x = (int) e2.getRawX();
int y = (int) e2.getRawY();
move(x, y);
return true;
}
/**
* 移动的时候更新图片显示的区域
*
* @param x
* @param y
*/
private void move(int x, int y) {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
Log.d(TAG, "move, deltaX:" + deltaX + " deltaY:" + deltaY);
//如果图片宽度大于屏幕宽度
if (mImageWidth > getWidth()) {
//移动rect区域
mRect.offset(-deltaX, 0);
//检查是否到达图片最右端
if (mRect.right > mImageWidth) {
mRect.right = mImageWidth;
mRect.left = mImageWidth - getWidth();
}
//检查左端
if (mRect.left < 0) {
mRect.left = 0;
mRect.right = getWidth();
}
invalidate();
}
//如果图片高度大于屏幕高度
if (mImageHeight > getHeight()) {
mRect.offset(0, -deltaY);
//是否到达最底部
if (mRect.bottom > mImageHeight) {
mRect.bottom = mImageHeight;
mRect.top = mImageHeight - getHeight();
}
if (mRect.top < 0) {
mRect.top = 0;
mRect.bottom = getHeight();
}
//重绘
invalidate();
}
mLastX = x;
mLastY = y;
}
@Override
public void onLongPress(MotionEvent e) {
mLastX = (int) e.getRawX();
mLastY = (int) e.getRawY();
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int x = (int) e2.getRawX();
int y = (int) e2.getRawY();
move(x, y);
return true;
}
@Override
protected void onDraw(Canvas canvas) {
//显示图片
Bitmap bm = mDecoder.decodeRegion(mRect, options);
canvas.drawBitmap(bm, 0, 0, null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int imageWidth = mImageWidth;
int imageHeight = mImageHeight;
//默认显示图片的中心区域,开发者可自行选择
mRect.left = imageWidth / 2 - width / 2;
mRect.top = imageHeight / 2 - height / 2;
mRect.right = mRect.left + width;
mRect.bottom = mRect.top + height;
}
}
BitmapRegionDecoder的更多相关文章
- Android 高清加载巨图方案 拒绝压缩图片
Android 高清加载巨图方案 拒绝压缩图片 转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/49300989: 本文出自:[张 ...
- Android 高清加载巨图方案, 拒绝压缩图片
源地址:http://blog.csdn.net/lmj623565791/article/details/49300989 一.概述 距离上一篇博客有段时间没更新了,主要是最近有些私事导致的,那么就 ...
- Android Framework 其中A记录
一个简短的引论 以往的研究太偏应用层的功能,实现了,原则上不进入非常理解,现在,研究人员framework该框架层. 创纪录的 1.下载源代码,文件夹例如以下: 2.Android系统的层次例如以下: ...
- Android开发技巧——大图裁剪
本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...
- 说一说关于破解支付宝AR红包的事
当朋友圈的你们才开始分享支付宝AR红包的消息的时候,我已经对它动了一二三四次歪脑筋了,虽然事实证明并不是那么顺利,至今我也只在电脑前识别出5个不知道在哪里的红包,其中一个还因为定位信息不符开不了. 昨 ...
- Android Framework 学习和需要学习的内容
1. 之前的研究太偏向应用层功能实现了,很多原理不了解没有深究,现在研究framework面存一些资料待有空查看. 2.Android系统的层次如下: 3.项目目录简单分析如下: 4.telphony ...
- android 自定义相机
老规矩,先上一下项目地址:GitHub:https://github.com/xiangzhihong/CameraDemo 方式: 调用Camera API 自定义相机 调用系统相机 由于需求不同, ...
- 年底Android面试整理(附答案)
面试,无非都是问上面这些问题(挺多的 - -!),聘请中高级的安卓开发会往深的去问,并且会问一延伸二.以下我先提出几点重点,是面试官基本必问的问题,请一定要去了解! 基础知识 – 四大组件(生命周期, ...
- Android&Java面试题大全—金九银十面试必备
声明本文由作者:Man不经心授权转载,转载请联系原文作者原文链接:https://www.jianshu.com/p/375ad14096b3, 类加载过程 Java 中类加载分为 3 个步骤:加载. ...
随机推荐
- Docker镜像构建文件Dockerfile及相关命令介绍
使用docker build命令或使用Docker Hub的自动构建功能构建Docker镜像时,都需要一个Dockerfile文件.Dockerfile文件是一个由一系列构建指令组成的文本文件,doc ...
- 工作总结 select sum(A+B) from table select (A+B) from table
select IsTop,ActivityGlXs from ActivityGlInfo 其他类似 可以在 原理 先字段值 相加 根据值 再聚合运算 其他聚合函数类似 总结: 表字段是 可以相加,相 ...
- Shell脚本case语句
case语句格式 case 变量 in PAT1) 执行语句 ;; PAT2) 执行语句 ;; *) 默认执行语句 ;; esac 使用示例: 编写一个shell脚本,通过提示用户输入信息,输出cpu ...
- odoo xml中添加数据的数字代表含义
参考原文:https://alanhou.org/odoo12-import-export-data/ <?xml version="1.0"?> <odoo n ...
- 基于UDS的BootLoader
bootloader程序架构略有简化的bootloader图 这张图和恒润教程中的BootLoader流程大体是一致的. 疑问点 Q:图中的烧写顺序是34-36-34-36-34-36-37,但另一些 ...
- AD软件中可视栅格 捕捉栅格 电气栅格的功能和设置详解
AD16的栅格设置 AD16系统共有3种栅格:可视栅格.电气栅格.捕捉栅格. Snap:捕获栅格,如果设定值是10mil,鼠标的光标拖动零件引脚,距离可视栅格在10mil范围之内时,零件引脚自动的准确 ...
- 移动端css适配
/* iphoneX.iphoneXs */ @media only screen and (device-width: 375px) and (device-height: 812px) and ( ...
- django虚拟环境搭建
windows建立Django项目(建立虚拟环境,安装virtualenv,安装Django,创建项目) 目的:为每一个项目单独配置一个环境例如:项目一使用django1.10, 项目二使用djang ...
- JQuery 中each的使用方法
JQuery中的each函数在1.3.2的官方文档中的描述如下: each(callback) 以每一个匹配的元素作为上下文来执行一个函数. 意味着,每次执行传递进来的函数时,函数中的this关键字都 ...
- Linux通过秘钥远程连接
1. 秘钥生成命令 ssh-keygen 执行完上述的命令就会在root目录下生成公钥跟私钥文件 /root/.ssh/.id_rsa 私钥 /root/.ssh/.id_rsa.pub 公钥 ...