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 个步骤:加载. ...
随机推荐
- Oracle 11.2.0.1 ADG环境MRP进程遭遇ORA
环境:Linux + Oracle 11.2.0.1 ADG现象:发现备库没有应用日志 1. 数据库查询备库目前状态发现备库目前没有应用日志,apply lag已经显示备库有3天21小时多没有应用日志 ...
- Scrapy - 第一个爬虫和我的博客
第一个爬虫 这里我用官方文档的第一个例子:爬取http://quotes.toscrape.com来作为我的首个scrapy爬虫,我没有找到scrapy 1.5的中文文档,后续内容有部分是我按照官方文 ...
- flex整页布局
使用flex进行整页的三列布局,flex:1下的子元素无法铺满父级.给flex:1元素,添加stretch拉伸 display: flex; align-content: stretch; align ...
- MySQL通过 LOAD DATA INFILE 批量导入数据
LOAD DATA INFILE 语句用法 参考手册 本文语句参数使用默认值 PHP: TP框架环境 // 定义文件路径$file_path = 'LOAD_DATA_LOCAL_INFILE.tx ...
- Hadoop_10_HDFS 的 DataNode工作机制
1.DataNode的工作机制: 1.DataNode工作职责:存储管理用户的文件块数据 定期向namenode汇报自身所持有的block信息(通过心跳信息上报) (这点很重要,因为,当集群中发生某 ...
- 第八章 watch监听 86 watch、computed、methods的对比
- Java 转发和重定向的区别
转发是服务器行为,重定向是客户端行为 1.转发在服务器端完成的;重定向是在客户端完成的 2.转发的速度快;重定向速度慢 3.转发的是同一次请求;重定向是两次不同请求 4.转发不会执行转发后的代码;重定 ...
- Luogu P3804 【模板】后缀自动机
注意空间开两倍 #include <bits/stdc++.h> using namespace std; typedef long long LL; template<class ...
- PHP基础之如何调试PHP程序(HBuilder)
先到这里下载HBuilder(HBuilder是最棒的PHPIDE,可以参考PHP是世界上最棒的编程语言),运行后界面如下: 打开WAMP的调试选项(XDebug):,每开启一个Xdebug选项,WA ...
- 题解 [USACO Mar08] 奶牛跑步
[USACO Mar08] 奶牛跑步 Description Bessie准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚. Bessie也不想跑得太远,所 ...