超大图片显示,可任意缩放,移动,不用DiskLruCache
1.演示,代码
下载示例apk 下载项目 : https://gitee.com/xi/LImage.git

2.遇到的问题
- 想省内存,不太可能
- 只支持拖拽手势,不支持缩放相对简单,解码view对应的区域就可以。
- 不支持缩放好像说不过去,同时支持缩放+拖拽后变复杂,如转屏后的位置,指定锚点缩放,缩放后又移动,移动后又缩放。
- 用系统图库打开图片?直接打开超大图片不能正常显示.用图库打开图片所在目录?没有找到相关代码.
3.缩放,移动的思路
3.1 缩放思路
- 用一张解码区域是整张图片,但是inSampleSize大小适中的缩略图缩放.虽然图片是不清晰的,但是省内存,省解码时间.
- 缩小过程不需要高清的.
- 放大到100%的时候就重新解码当前view对应区域的位图,inSampleSize = 1 .
3.2 移动思路
- 当缩放比例小于100%时,就移动缩略图,
- 当缩放比例等于100%时,按当前view区域大小平移,重新解码对应的位图.
4.核心代码
4.1 解码
- BitmapRegionDecoder 可以指定一个区域(大图范围内,超出会抛异常)对一张大位图解码,解出一张小位图.然后在view上显示这个小位图.
- BitmapFactory.Options 解码选项,下面是常用的几个重要选项:
| inSampleSize | 缩略大小,值为2的n次幂(n为自然数).其它值无意义 |
|
inPreferredConfig |
色彩模式,决定一个像素占用的字节数 |
|
inBitmap |
指定复用的位图..不用在申请内存. |
- 代码
private BitmapRegionDecoder mDecoder;
private BitmapFactory.Options mOptions;
private Rect mDecodeRegion;
void initRegionDecoder(){
try {
InputStream fs = getResources().getAssets().open("world_map.jpg");
mDecoder = BitmapRegionDecoder.newInstance(fs,false);
mBitmapWidth = mDecoder.getWidth();
mBitmapHeight = mDecoder.getHeight();
mOptions = new BitmapFactory.Options();
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
mOptions.inSampleSize = ;
} catch (IOException e) {
e.printStackTrace();
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//...
mDecodeRegion = new Rect(left,top,left + viewWidth ,top + viewHeight );
// mDecodeRegion = new Rect(0,0,mBitmapWidth ,mBitmapHeight);
mOptions.inSampleSize = calculateInSampleSize(mDecodeRegion.width(),mDecodeRegion.height(),viewWidth,viewHeight);
// mOptions.inSampleSize = 2;
long begin,end;
begin = SystemClock.elapsedRealtime();
mBitmap = mDecoder.decodeRegion(mDecodeRegion,mOptions);
end = SystemClock.elapsedRealtime();
//..
}
4.2 手势
- ScaleGestureDetector 缩放手势识别器
- GestureDetectorCompat 移动手势识别器
这两个比较简单,先构造,然后在 public boolean onTouchEvent(MotionEvent event) 里接收触摸事件,最后在相应的手势回调方法处理手势就可以.
4.3 变形
缩放: 用变形矩阵.小于100%时移动也用变形矩阵,等于100%时自己计算.
@Override
protected void onDraw(Canvas canvas) {
if (mPercentage < 100.0f && mThumbnailBitmap != null){
canvas.drawBitmap(mThumbnailBitmap,mMatrix,mPaint);
}else if(mPercentage == 100.0f && mBitmap != null){
canvas.drawBitmap(mBitmap,mBitmapLeft,mBitmapTop,mPaint);
}
//...
}
4.4 LargeImageView.java
package com.example.ff.limage;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Parcelable;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.view.GestureDetectorCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import static android.os.Environment.isExternalStorageRemovable;
public class LargeImageView extends View {
private String TAG = "LargeImageView";
private Paint mPaint;
private BitmapRegionDecoder mDecoder;
private BitmapFactory.Options mOptions;
private Rect mDecodeRegion;
private static Bitmap mThumbnailBitmap;
private Bitmap mBitmap;
private Matrix mMatrix;
private float thumbnailWidth,thumbnailHeight;
private float mPercentage;
private float mThumbnailLeft,mThumbnailTop,mBitmapLeft,mBitmapTop;
private int mBitmapWidth,mBitmapHeight;
private Point mFocus;
private boolean mScaling = false;
private DiskLruCache mDiskLruCache;
public void destroyBitmaps(){
Log.e(TAG, "destroyBitmaps: release bitmaps" );
if (!mDecoder.isRecycled()) {
mDecoder.recycle();
}
if (!mBitmap.isRecycled()){
mBitmap.recycle();
mBitmap = null;
}
}
public void destroyThumbnailBitmap(){
if (!mThumbnailBitmap.isRecycled()){
mThumbnailBitmap.recycle();
mThumbnailBitmap = null;
}
}
public void createThumbnailBitmap(){
if (null == mThumbnailBitmap){
DecodeTask task = new DecodeTask();
task.execute(mDecodeRegion);
}
}
public void createBitmaps(){
}
private class DecodeTask extends AsyncTask<Rect,Void,Void>{
@Override
protected Void doInBackground(Rect... rects) {
Log.e(TAG, "doInBackground: " );
long begin,end;
mDecodeRegion = ,,mBitmapWidth,mBitmapHeight);
mOptions.inSampleSize = ;
begin = SystemClock.elapsedRealtime();
mThumbnailBitmap = mDecoder.decodeRegion(mDecodeRegion,mOptions);
end = SystemClock.elapsedRealtime();
Log.e(TAG, "doInBackground: decode mThumbnailBitmap need " + (end - begin) + " ms. " );
return null;
}
}
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
// 打印Matrix内数据
void showMatrix(Matrix matrix,String tag){
// 下面的代码是为了查看matrix中的元素
];
matrix.getValues(matrixValues);
String temp ;
; i < ; ++i) {
temp = "";
; j < ; ++j) {
temp += matrixValues[ * i + j] + "\t";
}
Log.e(tag, temp);
}
}
private void printThumbnailRect(){
float left = mThumbnailLeft;
float top = mThumbnailTop;
float right = mThumbnailLeft + thumbnailWidth;
float bottom = mThumbnailTop + thumbnailHeight;
Log.e(TAG, "printThumbnailRect: left = " + left + " top = " + top + " right = " + right + " bottom = " + bottom
+ " width = " + thumbnailWidth + " height = " + thumbnailHeight);
}
private ScaleGestureDetector scaleDetector;
private ScaleGestureDetector.SimpleOnScaleGestureListener scaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float factor = detector.getScaleFactor();
) return true;
&& factor > ){
return true;
}
if (thumbnailWidth * factor < mBitmapWidth){
if (thumbnailWidth * factor >= mBitmapWidth * 0.01f){
thumbnailWidth *= factor;
thumbnailHeight *= factor;
mMatrix.postScale(factor,factor,detector.getFocusX(),detector.getFocusY());
}
}else{
factor = mBitmapWidth / thumbnailWidth;
mMatrix.postScale(factor,factor,detector.getFocusX(),detector.getFocusY());
thumbnailWidth = mBitmapWidth;
thumbnailHeight = mBitmapHeight;
mPercentage = 100.0f;
];
mMatrix.getValues(matrix);
mThumbnailLeft = matrix[];
mThumbnailTop = matrix[];
float left = mThumbnailLeft;
float top = mThumbnailTop;
float right = mThumbnailLeft + thumbnailWidth;
float bottom = mThumbnailTop + thumbnailHeight;
int viewWith = getWidth();
int viewHeight = getHeight();
mBitmapLeft = ;
mBitmapTop = ;
){
mBitmapLeft = left;
mDecodeRegion.left = ;
mDecodeRegion.right = (int) (viewWith - left);
){
mBitmapTop = top;
mDecodeRegion.top = ;
mDecodeRegion.bottom = (int) (viewHeight - top);
}else if(bottom < viewHeight){
mDecodeRegion.bottom = mBitmapHeight;
mDecodeRegion.top = (int) (mBitmapHeight - bottom);
}else {
mDecodeRegion.top = (int) -top;
mDecodeRegion.bottom = mDecodeRegion.top + viewHeight;
}
}){
mBitmapTop = top;
mDecodeRegion.top = ;
mDecodeRegion.bottom = (int) (viewHeight - top);
if (right < viewWith){
mDecodeRegion.right = mBitmapWidth;
mDecodeRegion.left = (int) (mBitmapWidth - right);
}else{
mDecodeRegion.left = (int) -left;
mDecodeRegion.right = mDecodeRegion.left + viewWith;
}
}else if(right < viewWith ){
mDecodeRegion.right = mBitmapWidth;
mDecodeRegion.left = (int) (mBitmapWidth - right);
if(bottom < viewHeight){
mDecodeRegion.bottom = mBitmapHeight;
mDecodeRegion.top = (int) (mBitmapHeight - bottom);
}else{
mDecodeRegion.top = (int) -top;
mDecodeRegion.bottom = mDecodeRegion.top + viewHeight;
}
}else if(bottom < viewHeight){
mDecodeRegion.left = (int) -left;
mDecodeRegion.right = mDecodeRegion.left + viewWith;
mDecodeRegion.bottom = mBitmapHeight;
mDecodeRegion.top = (int) (mBitmapHeight - bottom);
}else{
mDecodeRegion.left = (int) -left;
mDecodeRegion.right = mDecodeRegion.left + viewWith;
mDecodeRegion.top = (int) -top;
mDecodeRegion.bottom = mDecodeRegion.top + viewHeight;
}
mOptions.inSampleSize = ;
&& mDecodeRegion.height() > ){
mBitmap = mDecoder.decodeRegion(mDecodeRegion,mOptions);
}else{
if (mBitmap != null && !mBitmap.isRecycled()){
mBitmap.recycle();
mBitmap = null;
}
}
}
BigDecimal bd = ).setScale(,BigDecimal.ROUND_HALF_UP);
mPercentage = bd.floatValue();
Log.i(TAG, "onScale: bitmap.w = " + mThumbnailBitmap.getWidth() + " bitmap.h = " + mThumbnailBitmap.getHeight()
+ " thumbnailWidth = " + thumbnailWidth + " thumbnailHeight = " + thumbnailHeight);
invalidate();
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mScaling = true;
float focusX = detector.getFocusX();
float focusY = detector.getFocusY();
mFocus = new Point((int)focusX,(int)focusY);
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
mScaling = false;
mFocus = null;
super.onScaleEnd(detector);
}
};
private GestureDetectorCompat scrollDetector;
private GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
&& Math.abs(distanceY) < ) return true;
];
mMatrix.getValues(matrix);
mThumbnailLeft = matrix[];
mThumbnailTop = matrix[];
int viewWith = getWidth();
int viewHeight = getHeight();
if (mThumbnailLeft <= viewWith && mThumbnailLeft >= -thumbnailWidth
&& mThumbnailTop <= viewHeight && mThumbnailTop >= -thumbnailHeight){
&& viewWith - mThumbnailLeft < -distanceX){
distanceX = -(viewWith - mThumbnailLeft);
} && mThumbnailLeft + thumbnailWidth < distanceX){
distanceX = mThumbnailLeft + thumbnailWidth;
}
&& viewHeight - mThumbnailTop < -distanceY){
distanceY = -(viewHeight - mThumbnailTop);
} && mThumbnailTop + thumbnailHeight < distanceY){
distanceY = mThumbnailTop + thumbnailHeight;
}
mMatrix.postTranslate(-distanceX,-distanceY);
if (mPercentage == 100.0f){
mMatrix.getValues(matrix);
mThumbnailLeft = matrix[];
mThumbnailTop = matrix[];
float left = mThumbnailLeft;
float top = mThumbnailTop;
float right = mThumbnailLeft + thumbnailWidth;
float bottom = mThumbnailTop + thumbnailHeight;
mBitmapLeft = ;
mBitmapTop = ;
){
mBitmapLeft = left;
mDecodeRegion.left = ;
mDecodeRegion.right = (int) (viewWith - left);
){
mBitmapTop = top;
mDecodeRegion.top = ;
mDecodeRegion.bottom = (int) (viewHeight - top);
}else if(bottom < viewHeight){
mDecodeRegion.bottom = mBitmapHeight;
mDecodeRegion.top = (int) (mBitmapHeight - bottom);
}else {
mDecodeRegion.top = (int) -top;
mDecodeRegion.bottom = mDecodeRegion.top + viewHeight;
}
}){
mBitmapTop = top;
mDecodeRegion.top = ;
mDecodeRegion.bottom = (int) (viewHeight - top);
if (right < viewWith){
mDecodeRegion.right = mBitmapWidth;
mDecodeRegion.left = (int) (mBitmapWidth - right);
}else{
mDecodeRegion.left = (int) -left;
mDecodeRegion.right = mDecodeRegion.left + viewWith;
}
}else if(right < viewWith ){
mDecodeRegion.right = mBitmapWidth;
mDecodeRegion.left = (int) (mBitmapWidth - right);
if(bottom < viewHeight){
mDecodeRegion.bottom = mBitmapHeight;
mDecodeRegion.top = (int) (mBitmapHeight - bottom);
}else{
mDecodeRegion.top = (int) -top;
mDecodeRegion.bottom = mDecodeRegion.top + viewHeight;
}
}else if(bottom < viewHeight){
mDecodeRegion.left = (int) -left;
mDecodeRegion.right = mDecodeRegion.left + viewWith;
mDecodeRegion.bottom = mBitmapHeight;
mDecodeRegion.top = (int) (mBitmapHeight - bottom);
}else{
mDecodeRegion.left = (int) -left;
mDecodeRegion.right = mDecodeRegion.left + viewWith;
mDecodeRegion.top = (int) -top;
mDecodeRegion.bottom = mDecodeRegion.top + viewHeight;
}
mOptions.inSampleSize = ;
Log.e(TAG, "onScroll: mDecodeRegion = " + mDecodeRegion );
&& mDecodeRegion.height() > ){
mBitmap = mDecoder.decodeRegion(mDecodeRegion,mOptions);
}else{
mBitmap = null;
}
}
invalidate();
}
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return true;
}
};
private void initGestureDetector() {
scrollDetector = new GestureDetectorCompat(getContext(), simpleOnGestureListener);
scaleDetector = new ScaleGestureDetector(getContext(), scaleGestureListener);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean ret = scaleDetector.onTouchEvent(event);
ret |= scrollDetector.onTouchEvent(event);
return ret || true;
}
* * ; // 256MB
private static final String DISK_CACHE_SUBDIR = "thumbnails";
void initCache(){
try {
Context context = getContext();
File cacheDir = context.getCacheDir();
cacheDir = context.getExternalCacheDir();
final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||!isExternalStorageRemovable()
? context.getExternalCacheDir().getPath()
: context.getCacheDir().getPath();
cacheDir = new File(cachePath + File.separator + DISK_CACHE_SUBDIR);
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), );
int appVersion = pi.versionCode;
;
mDiskLruCache = DiskLruCache.open(cacheDir, appVersion,valueCount,DISK_CACHE_SIZE);
} catch (IOException e) {
e.printStackTrace();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
void init(){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize();
setLayerType(View.LAYER_TYPE_SOFTWARE,mPaint);
// LinearGradient backGradient = new LinearGradient(0, 0, 0, mPaint.getTextSize(), new int[]{Color.BLACK, Color.GRAY ,Color.YELLOW}, null, Shader.TileMode.CLAMP);
// mPaint.setShader(backGradient);
mMatrix = new Matrix();
// initCache();
initGestureDetector();
initRegionDecoder();
}
void initRegionDecoder(){
try {
InputStream fs = getResources().getAssets().open("world_map.jpg");
mDecoder = BitmapRegionDecoder.newInstance(fs,false);
mBitmapWidth = mDecoder.getWidth();
mBitmapHeight = mDecoder.getHeight();
mOptions = new BitmapFactory.Options();
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
mOptions.inSampleSize = ;
} catch (IOException e) {
e.printStackTrace();
}
}
private void getAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LargeImageViewAttrs);
String file = ta.getString(R.styleable.LargeImageViewAttrs_src);
ta.recycle();
}
public LargeImageView(Context context) {
super(context);
init();
}
public LargeImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
getAttrs(context,attrs);
init();
}
public LargeImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
getAttrs(context,attrs);
init();
}
@SuppressLint("NewApi")
public LargeImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
getAttrs(context,attrs);
init();
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
public static int calculateInSampleSize(int width, int height, int reqWidth, int reqHeight) {
// Raw height and width of image
;
if (height > reqHeight || width > reqWidth) {
final ;
final ;
|| halfWidth <= ) return inSampleSize;
if (width > height) {
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= ;
}
} else {
while ((halfHeight / inSampleSize) >= reqHeight) {
inSampleSize *= ;
}
}
}
return inSampleSize;
}
@Override
protected void onDraw(Canvas canvas) {
if (mPercentage < 100.0f && mThumbnailBitmap != null){
canvas.drawBitmap(mThumbnailBitmap,mMatrix,mPaint);
}else if(mPercentage == 100.0f && mBitmap != null){
canvas.drawBitmap(mBitmap,mBitmapLeft,mBitmapTop,mPaint);
}
if (mFocus != null){
mPaint.setColor(Color.RED);
mPaint.setMaskFilter(, BlurMaskFilter.Blur.SOLID));
mPaint.setColor(Color.parseColor("#ff0000"));
canvas.drawCircle(mFocus.x,mFocus.y,,mPaint);
}
//draw percentage
String percentage = mPercentage + "%";
float textSize = mPaint.getTextSize();
float percentWidth = mPaint.measureText("100.0%");
float circleX = getWidth() - percentWidth ;
float circleY = percentWidth ;
mPaint.setColor(Color.parseColor("#7f7A378B"));
mPaint.setMaskFilter(, BlurMaskFilter.Blur.NORMAL));
canvas.drawCircle(circleX ,circleY,percentWidth * 0.66f,mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setMaskFilter(null);
percentWidth = mPaint.measureText(percentage);
circleY += textSize / ;
circleX -= percentWidth / ;
canvas.drawText(percentage,circleX ,circleY,mPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.e(TAG, "onMeasure: " );
int viewWidth = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
) viewWidth = ;
viewWidth = resolveSizeAndState(viewWidth, widthMeasureSpec, );
int viewHeight = getSuggestedMinimumHeight() + getPaddingBottom() + getPaddingTop();
) viewHeight = ;
//计算最佳值,在其中解析了 heightMeasureSpec
viewHeight = resolveSizeAndState(viewHeight, heightMeasureSpec, );
//将量算的结果保存到View的成员变量mMeasuredWidth 和mMeasuredHeight中。
setMeasuredDimension(viewWidth, viewHeight);
// 量算完成之后,View的父控件就可以通过调用
// getMeasuredWidth、getMeasuredState、getMeasuredWidthAndState
// 这三个方法获取View的量算结果。
mBitmapLeft = ;
mBitmapTop = ;
- viewWidth / ;
- viewHeight / ;
mDecodeRegion = new Rect(left,top,left + viewWidth ,top + viewHeight );
// mDecodeRegion = new Rect(0,0,mBitmapWidth ,mBitmapHeight);
mOptions.inSampleSize = calculateInSampleSize(mDecodeRegion.width(),mDecodeRegion.height(),viewWidth,viewHeight);
// mOptions.inSampleSize = 2;
long begin,end;
begin = SystemClock.elapsedRealtime();
mBitmap = mDecoder.decodeRegion(mDecodeRegion,mOptions);
end = SystemClock.elapsedRealtime();
thumbnailWidth = mBitmapWidth;
thumbnailHeight = mBitmapHeight;
BigDecimal bd = ).setScale(,BigDecimal.ROUND_HALF_UP);
mPercentage = bd.floatValue();
Log.e(TAG, "init region = " + mDecodeRegion + " ratio = " + (float) mDecodeRegion.width() / mDecodeRegion.height()
+ " bitmap.w = " + mBitmap.getWidth() + " bitmap.h = " + mBitmap.getHeight() + " ratio = " + (float) mBitmap.getWidth() / mBitmap.getHeight()
+ " need " + (end - begin) + " ms");
if (mThumbnailBitmap != null){
Log.e(TAG, "onMeasure : mThumbnailBitmap is ok.");
float width = mThumbnailBitmap.getWidth();
float height = mThumbnailBitmap.getHeight();
- width / ;
- height / ;
mMatrix.setTranslate(dx,dy);
float factor = mBitmapWidth / width;
mMatrix.postScale(factor,factor,viewWidth/ ,viewHeight /);
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
Log.e(TAG, "onFinishInflate: " );
createThumbnailBitmap();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.e(TAG, "onAttachedToWindow: " );
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.e(TAG, "onDetachedFromWindow: " );
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
Log.e(TAG, "onWindowVisibilityChanged : " + visibility);
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
Log.e(TAG, "onWindowFocusChanged: hasWindowFocus = " + hasWindowFocus );
}
Bitmap loadBitmapFromCache(String key){
Bitmap bitmap = null;
try {
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
if (snapshot != null) {
InputStream );
bitmap = BitmapFactory.decodeStream(is);
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
void pushToCache(String key, Bitmap value){
try {
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null){
OutputStream );
value.compress(Bitmap.CompressFormat.JPEG, , out);
out.flush();
editor.commit();
mDiskLruCache.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
超大图片显示,可任意缩放,移动,不用DiskLruCache的更多相关文章
- JS控制图片显示的大小(图片等比例缩放)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Java图片工具类,完成图片的截取和任意缩放
package com.common.util; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Renderin ...
- 【JS控制图片显示的大小(图片等比例缩放)】
效果: 代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- C++对于大型图片的加载缩放尝试
Qt对于图片的操作主要集中在这几个类 QImage ,QImageReader ,QPixmap 其中QImage这个类对图片的缩放有几个很不错的技巧,不过对于大图片却并不好使,当我们去看QImage ...
- C#图片处理示例(裁剪,缩放,清晰度,水印)
C#图片处理示例(裁剪,缩放,清晰度,水印) 吴剑 2011-02-20 原创文章,转载必需注明出处:http://www.cnblogs.com/wu-jian/ 前言 需求源自项目中的一些应用,比 ...
- wpf图片浏览器,实现缩放平移操作图片切换等功能
wpf经常要用到控件来查看图片,尤其是高清图片,于是做了一个例子: 1.定义图片的队列,用list来存. private readonly List<string> files; 2.切换 ...
- 实现图片的2次缩放后再进行candy边缘检测
//实现图片的2次缩放后再进行candy边缘检测//Author:SD//Date:2015-9-27#include "cv.h"#include "highgui.h ...
- VS2010 MFC GDI+ 实现PNG透明图片显示
网上找了一些资料学习了一下PNG图的显示,这里总结一下. 参考:http://blog.csdn.net/czyt1988/article/details/7965066 一.VS2010配置GDI+ ...
- 蚂蚁代理免费代理ip爬取(端口图片显示+token检查)
分析 蚂蚁代理的列表页大致是这样的: 端口字段使用了图片显示,并且在图片上还有各种干扰线,保存一个图片到本地用画图打开观察一下: 仔细观察蓝色的线其实是在黑色的数字下面的,其它的干扰线也是,所以这幅图 ...
随机推荐
- modifiers标量调节器插件的定义和使用
在插件目录plugins里新建文件 modifier.插件名.php文件(如 modifier.插件名.php)例:function smarty_modifier_test($utime, $for ...
- SQL2000中创建作业(定时查询,更新)(转)
出处:http://blog.csdn.net/xys_777/article/details/5683413 SQL2000中创建作业(定时查询,更新)企业管理器 --管理 --SQL Server ...
- java修饰符 protect public protected
1.private修饰词,表示成员是私有的,只有自身可以访问: 2.protected,表示受保护权限,体现在继承,即子类可以访问父类受保护成员(子类是可以访问父类的带protected修饰符的成员的 ...
- ES6语法的新特性
ES6 就是ECMAScript 6是新版本JavaScript语言的标准.虽然目前已经更新到ES7,但是很多浏览器还不知处ES7语法,该标准仍在更新中,但目前部门网站都指出ES6的语法.目前ES6也 ...
- [CentOS]使用yum命令报出Error: Cannot retrieve repository metadata (repomd.xml) for repository的解决方法
在一次错误的repo文件rpm -i 之后,执行yum就开始报出 Error: Cannot retrieve repository metadata (repomd.xml) for reposit ...
- [LeetCode 题解]: Container With Most Water
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...
- [Erlang11] 那些经历过的Erlang小坑11-20
11.每次重装系统时都会重新安装Erlang,Ubuntu安装sh秒杀一切. https://gist.github.com/zhongwencool/11174620 12. Erlang Shel ...
- GridView中文属性
GridControl的中文属性: 1 Appearance 外观 Appearance 外观设置 ColumnFilterButton 行过滤器按钮 BackerColor 背景色 Backe ...
- 【题解】 [NOI1999]生日蛋糕
题面 传送门 Solution 搜索每一层的半径和高度,然后加入一些剪枝就好了. #include<stdio.h> #include<stdlib.h> #include&l ...
- Centos6.9下PXE安装centos 7
一.简介 这篇文章是无kickstart下安装centos7的,本篇大部分内容同我另外一篇文章相似,只是Centos7 中的isolinux.cfg有一些不太一样需要说明一下. https://www ...