1. 程式人生 > >載入巨圖不壓縮(BitmapRegionDecoder, DestureDetetor)

載入巨圖不壓縮(BitmapRegionDecoder, DestureDetetor)

若僅在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();
        }
        ...

效果:

這裡寫圖片描述