下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】要优雅!Android中这样加载大图片和长图片
我们在做开发的时候总是会不可避免的遇到加载图片的情况,当图片的尺寸小于ImageView的尺寸的时候,我们当然可以很happy的去直接加载展示。但是如果我们要加载的图片远远大于ImageView的大小,直接用ImageView去展示的话,就会带来不好的视觉效果,也会占用太多的内存和性能开销。甚至这张图片足够大到导致程序oom崩溃。这个时候我们就需要对图片进行特殊的处理了:图片太大,那我就想办法把它压缩变小呗。老铁,这思路完全没毛病。BitmapFactory这个类就提供了多个解析方法(decodeResource、decodeStream、decodeFile等)用于创建Bitmap。我们可以根据图片的来源来选择解析方法。BitmapFactory为这些方法都提供了一个可选的参数BitmapFactory.Options,用来辅助我们解析图片。这个参数有一个属性inSampleSize,这个属性可以帮助我们来进行图片的压缩。为了解释inSampleSize的效果,我们可以举个栗子。
比如我们有一张2048
1536的图片,设置inSampleSize的值为4,就可以把这张图片压缩为512384,长短各缩小了4倍,所占内存就缩小了16倍。
这就明了了,inSampleSize的作用就是可以把图片的长短缩小inSampleSize倍,所占内存缩小inSampleSize的平方。
官方文档对于inSampleSize的值也做了一些要求,那就是inSampleSize的值必须大于等于1,如果给定的值小于1,那就默认为1。
而且inSampleSize的值需要是2的倍数,如果不是的话,就会自动变为离这个值向下最近的2的倍数的值,比如给定的值是3,那么最终inSampleSize的值会是2。当然了,这个inSampleSize的值我们也不可能随便就给,最好使我们能获取到照片的原始大小,再根据需要进行压缩。别急,谷歌都帮我们想好了!BitmapFactory.Options有一个属性inJustDecodeBounds,这个属性当为true的时候,表明我们当前只是为了获取当前图片的边界的大小,此时BitmapFactory的解析图片方法的返回值为null,该方法是一个十分轻量级的方法。这样我们就可以很愉快的拿到图片大小了,代码如下:BitmapFactory.Options
options
=
new
BitmapFactory.Options();
options.inJustDecodeBounds
=
true;
//
当前只为获取图片的边界大小BitmapFactory.decodeResource(getResources(),
R.drawable.bigpic,
options);int
outHeight
=
options.outHeight;int
outWidth
=
options.outWidth;
String
outMimeType
=
options.outMimeType;拿到了图片的大小,我们就可以根据需要计算出所需要压缩的大小了:private
int
caculateSampleSize(BitmapFactory.Options
options,
int
reqWidth,
int
reqHeight)
{
int
sampleSize
=
1;
int
picWidth
=
options.outWidth;
int
picHeight
=
options.outHeight;
if
(picWidth
>
reqWidth
||
picHeight
>
reqHeight)
{
int
halfPicWidth
=
picWidth
/
2;
int
halfPicHeight
=
picHeight
/
2;
while
(halfPicWidth
/
sampleSize
>
reqWidth
||
halfPicHeight
/
sampleSize
>
reqHeight)
{
sampleSize
*=
2;
}
}
return
sampleSize;
}下面就是完整的代码:
mIvBigPic
=
findViewById(R.id.iv_big_pic);
BitmapFactory.Options
options
=
new
BitmapFactory.Options();
options.inJustDecodeBounds
=
true;
//
当前只为获取图片的边界大小
BitmapFactory.decodeResource(getResources(),
R.drawable.bigpic,
options);
int
outHeight
=
options.outHeight;
int
outWidth
=
options.outWidth;
String
outMimeType
=
options.outMimeType;
System.out.println("outHeight
=
"
+
outHeight
+
"
outWidth
=
"
+
outWidth
+
"
outMimeType
=
"
+
outMimeType);
options.inJustDecodeBounds
=
false;
options.inSampleSize
=
caculateSampleSize(options,
getScreenWidth(),
getScreenHeight());
Bitmap
bitmap
=
BitmapFactory.decodeResource(getResources(),
R.drawable.bigpic,
options);
mIvBigPic.setImageBitmap(bitmap);这样图片压缩到这里就差不多结束了。有时候我们通过压缩可以取得很好的效果,但有时候效果就不那么美好了,例如长图像清明上河图,像这类的长图,如果我们直接压缩展示的话,这张图完全看不清,很影响体验。这时我们就可以采用局部展示,然后滑动查看的方式去展示图片。Android里面是利用BitmapRegionDecoder来局部展示图片的,展示的是一块矩形区域。为了完成这个功能那么就需要一个方法设置图片,另一个方法设置展示的区域。初始化
BitmapRegionDecoder提供了一系列的newInstance来进行初始化,支持传入文件路径,文件描述符和文件流InputStream等例如:mRegionDecoder=BitmapRegionDecoder.newInstance(inputStream,false);
上面这个方法解决了传入图片,接下来就要去设置展示区域了。Bitmapbitmap=mRegionDecoder.decodeRegion(mRect,sOptions);
参数一是一个Rect,参数二是BitmapFactory.Options,可以用来控制inSampleSize,inPreferredConfig等。下面是一个简单的例子,展示图片最前面屏幕大的部分:try
{
BitmapRegionDecoder
regionDecoder
=
BitmapRegionDecoder.newInstance(inputStream,
false);
BitmapFactory.Options
options1
=
new
BitmapFactory.Options();
options1.inPreferredConfig
=
Bitmap.Config.ARGB_8888;
Bitmap
bitmap
=
regionDecoder.decodeRegion(new
Rect(0,
0,
getScreenWidth(),
getScreenHeight()),
options1);
mIvBigPic.setImageBitmap(bitmap);
}
catch
(IOException
e)
{
e.printStackTrace();
}当然了,这只是最简单的用法,对于我们想要完全展示图片并没什么用!客官,稍安勿躁,前途已经明了!既然我们可以实现区域展示,那我们可不可以自定义一个View,可以随着我们的手指滑动展示图片的不同区域。yes!ofcourse。那么我们就继续吧!根据上面的分析,我们自定义控件的思路就很明白了:提供一个设置图片的路口;
重写onTouchEvent,根据用户移动的手势,修改图片显示的区域;
每次更新区域参数后,调用invalidate,onDraw里面去regionDecoder.decodeRegion拿到bitmap,去draw
废话不多说,直接上代码:public
class
BigImageView
extends
View
{
private
static
final
String
TAG
=
"BigImageView";
private
BitmapRegionDecoder
mRegionDecoder;
private
int
mImageWidth,
mImageHeight;
private
Rect
mRect
=
new
Rect();
private
static
BitmapFactory.Options
sOptions
=
new
BitmapFactory.Options();
{
sOptions.inPreferredConfig
=
Bitmap.Config.ARGB_8888;
}
public
BigImageView(Context
context)
{
this(context,
null);
}
public
BigImageView(Context
context,
@Nullable
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
BigImageView(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
}
public
void
setInputStream(InputStream
inputStream)
{
try
{
mRegionDecoder
=
BitmapRegionDecoder.newInstance(inputStream,
false);
BitmapFactory.Options
options
=
new
BitmapFactory.Options();
options.inJustDecodeBounds
=
false;
BitmapFactory.decodeStream(inputStream,
null,
options);
mImageHeight
=
options.outHeight;
mImageWidth
=
options.outWidth;
requestLayout();
invalidate();
}
catch
(IOException
e)
{
e.printStackTrace();
}
}
int
downX
=
0;
int
downY
=
0;
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
switch
(event.getAction())
{
case
MotionEvent.ACTION_DOWN:
downX
=
(int)
event.getX();
downY
=
(int)
event.getY();
break;
case
MotionEvent.ACTION_MOVE:
int
curX
=
(int)
event.getX();
int
curY
=
(int)
event.getY();
int
moveX
=
curX
-
downX;
int
moveY
=
curY
-
downY;
onMove(moveX,
moveY);
System.out.println(TAG
+
"
moveX
=
"
+
moveX
+
"
curX
=
"
+
curX
+
"
downX
=
"
+
downX);
downX
=
curX;
downY
=
curY;
break;
case
MotionEvent.ACTION_UP:
break;
}
return
true;
}
private
void
onMove(int
moveX,
int
moveY)
{
if
(mImageWidth
>
getWidth())
{
mRect.offset(-moveX,
0);
checkWidth();
invalidate();
}
if
(mImageHeight
>
getHeight())
{
mRect.offset(0,
-moveY);
checkHeight();
invalidate();
}
}
private
void
checkWidth()
{
Rect
rect
=
mRect;
if
(rect.right
>
mImageWidth)
{
rect.right
=
mImageWidth;
rect.left
=
mImageWidth
-
getWidth();
}
if
(rect.left
<
0)
{
rect.left
=
0;
rect.right
=
getWidth();
}
}
private
void
checkHeight()
{
Rect
rect
=
mRect;
if
(rect.bottom
>
mImageHeight)
{
rect.bottom
=
mImageHeight;
rect.top
=
mImageHeight
-
getHeight();
}
if
(rect.top
<
0)
{
rect.top
=
0;
rect.bottom
=
getWidth();
}
}
@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onM
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 轨缝计算及调整
- 动力电申请书范文
- 制造业企业供应链管理的优化策略
- 2024年吉林省辽源市龙山区《高等数学(一)》(专升本)模拟试题含解析
- 2024年关岭布依族苗族自治县《高等数学(一)》(专升本)模拟预测试卷含解析
- 2024年乐亭县《高等数学(一)》(专升本)模拟试题含解析
- 信息技术在汽车中的若干应用探析
- 文言文翻译的六个关键点
- 委托储存合同-范本
- ④当客代理商合作协议书(官方版)
- 消防员留队申请书
- (完整word版)种羊场系谱档案
- 景观园林设计的收费标准
- 2022公务员录用体检操作手册(试行)
- 食品安全风险管控清单
- 课程思政教学展示-计算机基础课程
- 2023年中考数学真题汇编详解23:矩形、菱形、正方形
- 6年级-数学老师-班主任-家长会
- 中央民族大学岗位设置与聘用管理暂行办法
- 政绩观存在的问题及整改措施范文(7篇)
- 【企业应收账款管理研究的国内外文献综述】
评论
0/150
提交评论