Android加载大图——BitmapRegionDecoder(转)

 

BitmapRegionDecoder,从API10就引入了。如下图:

 
NPONRY0T35GE$13{254X8Z1.png

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

二、使用

 
J1_7H5)MI{M2PV{){{3V97V.png
最主要的就是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的更多相关文章

  1. Android 高清加载巨图方案 拒绝压缩图片

    Android 高清加载巨图方案 拒绝压缩图片 转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/49300989: 本文出自:[张 ...

  2. Android 高清加载巨图方案, 拒绝压缩图片

    源地址:http://blog.csdn.net/lmj623565791/article/details/49300989 一.概述 距离上一篇博客有段时间没更新了,主要是最近有些私事导致的,那么就 ...

  3. Android Framework 其中A记录

    一个简短的引论 以往的研究太偏应用层的功能,实现了,原则上不进入非常理解,现在,研究人员framework该框架层. 创纪录的 1.下载源代码,文件夹例如以下: 2.Android系统的层次例如以下: ...

  4. Android开发技巧——大图裁剪

    本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...

  5. 说一说关于破解支付宝AR红包的事

    当朋友圈的你们才开始分享支付宝AR红包的消息的时候,我已经对它动了一二三四次歪脑筋了,虽然事实证明并不是那么顺利,至今我也只在电脑前识别出5个不知道在哪里的红包,其中一个还因为定位信息不符开不了. 昨 ...

  6. Android Framework 学习和需要学习的内容

    1. 之前的研究太偏向应用层功能实现了,很多原理不了解没有深究,现在研究framework面存一些资料待有空查看. 2.Android系统的层次如下: 3.项目目录简单分析如下: 4.telphony ...

  7. android 自定义相机

    老规矩,先上一下项目地址:GitHub:https://github.com/xiangzhihong/CameraDemo 方式: 调用Camera API 自定义相机 调用系统相机 由于需求不同, ...

  8. 年底Android面试整理(附答案)

    面试,无非都是问上面这些问题(挺多的 - -!),聘请中高级的安卓开发会往深的去问,并且会问一延伸二.以下我先提出几点重点,是面试官基本必问的问题,请一定要去了解! 基础知识 – 四大组件(生命周期, ...

  9. Android&Java面试题大全—金九银十面试必备

    声明本文由作者:Man不经心授权转载,转载请联系原文作者原文链接:https://www.jianshu.com/p/375ad14096b3, 类加载过程 Java 中类加载分为 3 个步骤:加载. ...

随机推荐

  1. Oracle 11.2.0.1 ADG环境MRP进程遭遇ORA

    环境:Linux + Oracle 11.2.0.1 ADG现象:发现备库没有应用日志 1. 数据库查询备库目前状态发现备库目前没有应用日志,apply lag已经显示备库有3天21小时多没有应用日志 ...

  2. Scrapy - 第一个爬虫和我的博客

    第一个爬虫 这里我用官方文档的第一个例子:爬取http://quotes.toscrape.com来作为我的首个scrapy爬虫,我没有找到scrapy 1.5的中文文档,后续内容有部分是我按照官方文 ...

  3. flex整页布局

    使用flex进行整页的三列布局,flex:1下的子元素无法铺满父级.给flex:1元素,添加stretch拉伸 display: flex; align-content: stretch; align ...

  4. MySQL通过 LOAD DATA INFILE 批量导入数据

    LOAD DATA INFILE 语句用法 参考手册 本文语句参数使用默认值 PHP:  TP框架环境 // 定义文件路径$file_path = 'LOAD_DATA_LOCAL_INFILE.tx ...

  5. Hadoop_10_HDFS 的 DataNode工作机制

    1.DataNode的工作机制: 1.DataNode工作职责:存储管理用户的文件块数据  定期向namenode汇报自身所持有的block信息(通过心跳信息上报) (这点很重要,因为,当集群中发生某 ...

  6. 第八章 watch监听 86 watch、computed、methods的对比

  7. Java 转发和重定向的区别

    转发是服务器行为,重定向是客户端行为 1.转发在服务器端完成的;重定向是在客户端完成的 2.转发的速度快;重定向速度慢 3.转发的是同一次请求;重定向是两次不同请求 4.转发不会执行转发后的代码;重定 ...

  8. Luogu P3804 【模板】后缀自动机

    注意空间开两倍 #include <bits/stdc++.h> using namespace std; typedef long long LL; template<class ...

  9. PHP基础之如何调试PHP程序(HBuilder)

    先到这里下载HBuilder(HBuilder是最棒的PHPIDE,可以参考PHP是世界上最棒的编程语言),运行后界面如下: 打开WAMP的调试选项(XDebug):,每开启一个Xdebug选项,WA ...

  10. 题解 [USACO Mar08] 奶牛跑步

    [USACO Mar08] 奶牛跑步 Description Bessie准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚. Bessie也不想跑得太远,所 ...