載入巨圖不壓縮(BitmapRegionDecoder, DestureDetetor)
阿新 • • 發佈:2019-01-31
若僅在xml使用src獲得巨圖,ImageView將不會顯示,得在程式碼裡用輸入流的方式獲得資源。使用ImageView時,如果要載入的圖片大於螢幕尺寸,則會壓縮圖片至螢幕的尺寸。
簡單載入巨圖(會壓縮圖片)
ivLargeImage = (ImageView) findViewById(R.id.iv_lar);
//壓縮圖
try {
InputStream in = getAssets().open("qingming.jpg");
//獲得圖片的寬高
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, bfo);
int width = bfo.outWidth;//圖片的寬
int height = bfo.outHeight;//圖片的高
//設定圖片的中心區域
BitmapRegionDecoder brd = BitmapRegionDecoder.newInstance (in, false);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bm = brd.decodeRegion(new Rect(0, 0, width, height), options);
ivLargeImage.setImageBitmap(bm);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace ();
}
效果:
自定義View, 不壓縮載入巨圖
LargeImageView.java
package com.example.day0202.ui.view;
import java.io.IOException;
import java.io.InputStream;
import com.example.day0202.gesturedetector.MoveGestureDetector;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class LargeImageView extends View{
private BitmapRegionDecoder mBitmapRegionDecoder;
private int screenHeight;
private int width;
private int height;
private MoveGestureDetector mGestureDetector;
private volatile Rect mRect = new Rect();
private static BitmapFactory.Options options = new BitmapFactory.Options();
static {
options.inPreferredConfig = Bitmap.Config.RGB_565;
}
public LargeImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mGestureDetector = new MoveGestureDetector(getContext(), new MoveGestureDetector.SimpleMoveGestureDetector(){
@Override
public boolean onMove(MoveGestureDetector detector) {
int moveX = (int) detector.getMoveX();
if (width > getWidth())
{
mRect.offset(-moveX, 0);
checkWidth();
invalidate();
}
return true;
}
});
}
protected void checkWidth() {
Rect rect = mRect;
int imageWidth = width;
if (rect.right > imageWidth)
{
rect.right = imageWidth;
rect.left = imageWidth - getWidth();
}
if (rect.left < 0)
{
rect.left = 0;
rect.right = getWidth();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return mGestureDetector.onToucEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap bm = mBitmapRegionDecoder.decodeRegion(mRect, options);
// Bitmap mBitmap = Bitmap.createScaledBitmap(bm, width, screenHeight, true);//滿鋪, 不過會卡
canvas.drawBitmap(bm, 0, 0, null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
screenHeight = height;
int imageWidth = this.width;
int imageHeight = this.height;
//左上角
mRect.left = 0;
mRect.top = 0;
mRect.right = width;
mRect.bottom = imageHeight;
}
public void setInputString(InputStream in) {
try {
mBitmapRegionDecoder = BitmapRegionDecoder.newInstance(in, false);
BitmapFactory.Options btmOptions = new BitmapFactory.Options();
btmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, btmOptions);
width = btmOptions.outWidth;
height = btmOptions.outHeight;
// requestLayout();
// invalidate();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
};
}
手勢識別
package com.example.day0202.gesturedetector;
import android.content.Context;
import android.graphics.PointF;
import android.view.MotionEvent;
public class MoveGestureDetector extends BaseGestureDetector
{
private PointF mCurrentPointer;
private PointF mPrePointer;
//僅僅為了減少建立記憶體
private PointF mDeltaPointer = new PointF();
//用於記錄最終結果,並返回
private PointF mExtenalPointer = new PointF();
private OnMoveGestureListener mListenter;
public MoveGestureDetector(Context context, OnMoveGestureListener listener)
{
super(context);
mListenter = listener;
}
@Override
protected void handleInProgressEvent(MotionEvent event)
{
int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
switch (actionCode)
{
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mListenter.onMoveEnd(this);
resetState();
break;
case MotionEvent.ACTION_MOVE:
updateStateByEvent(event);
boolean update = mListenter.onMove(this);
if (update)
{
mPreMotionEvent.recycle();
mPreMotionEvent = MotionEvent.obtain(event);
}
break;
}
}
@Override
protected void handleStartProgressEvent(MotionEvent event)
{
int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
switch (actionCode)
{
case MotionEvent.ACTION_DOWN:
resetState();//防止沒有接收到CANCEL or UP ,保險起見
mPreMotionEvent = MotionEvent.obtain(event);
updateStateByEvent(event);
break;
case MotionEvent.ACTION_MOVE:
mGestureInProgress = mListenter.onMoveBegin(this);
break;
}
}
protected void updateStateByEvent(MotionEvent event)
{
final MotionEvent prev = mPreMotionEvent;
mPrePointer = caculateFocalPointer(prev);
mCurrentPointer = caculateFocalPointer(event);
//Log.e("TAG", mPrePointer.toString() + " , " + mCurrentPointer);
boolean mSkipThisMoveEvent = prev.getPointerCount() != event.getPointerCount();
//Log.e("TAG", "mSkipThisMoveEvent = " + mSkipThisMoveEvent);
mExtenalPointer.x = mSkipThisMoveEvent ? 0 : mCurrentPointer.x - mPrePointer.x;
mExtenalPointer.y = mSkipThisMoveEvent ? 0 : mCurrentPointer.y - mPrePointer.y;
}
/**
* 根據event計算多指中心點
*
* @param event
* @return
*/
private PointF caculateFocalPointer(MotionEvent event)
{
final int count = event.getPointerCount();
float x = 0, y = 0;
for (int i = 0; i < count; i++)
{
x += event.getX(i);
y += event.getY(i);
}
x /= count;
y /= count;
return new PointF(x, y);
}
public float getMoveX()
{
return mExtenalPointer.x;
}
public float getMoveY()
{
return mExtenalPointer.y;
}
public interface OnMoveGestureListener
{
public boolean onMoveBegin(MoveGestureDetector detector);
public boolean onMove(MoveGestureDetector detector);
public void onMoveEnd(MoveGestureDetector detector);
}
public static class SimpleMoveGestureDetector implements OnMoveGestureListener
{
@Override
public boolean onMoveBegin(MoveGestureDetector detector)
{
return true;
}
@Override
public boolean onMove(MoveGestureDetector detector)
{
return false;
}
@Override
public void onMoveEnd(MoveGestureDetector detector)
{
}
}
}
package com.example.day0202.gesturedetector;
import android.content.Context;
import android.view.MotionEvent;
public abstract class BaseGestureDetector
{
protected boolean mGestureInProgress;
protected MotionEvent mPreMotionEvent;
protected MotionEvent mCurrentMotionEvent;
protected Context mContext;
public BaseGestureDetector(Context context)
{
mContext = context;
}
public boolean onToucEvent(MotionEvent event)
{
if (!mGestureInProgress)
{
handleStartProgressEvent(event);
} else
{
handleInProgressEvent(event);
}
return true;
}
protected abstract void handleInProgressEvent(MotionEvent event);
protected abstract void handleStartProgressEvent(MotionEvent event);
protected abstract void updateStateByEvent(MotionEvent event);
protected void resetState()
{
if (mPreMotionEvent != null)
{
mPreMotionEvent.recycle();
mPreMotionEvent = null;
}
if (mCurrentMotionEvent != null)
{
mCurrentMotionEvent.recycle();
mCurrentMotionEvent = null;
}
mGestureInProgress = false;
}
}
用法:
MainActivity.java
...
LargeImageView largeImageView = (LargeImageView) findViewById(R.id.liv);
try {
InputStream in = getAssets().open("qingming.jpg");
largeImageView.setInputString(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
...
效果: