Android 如何加载大图片

第一步:创建手势基类:

public abstract class BaseGuestureDetector {

    /** 进行中的手势   */
    protected boolean mIsGestureMoving;
    /** 先前的事件    */
    protected MotionEvent mPreMotionEvent;
    /** 当前的事件    */
    protected MotionEvent mCurrentMotionEvent;

    public Context mContext;

    public BaseGuestureDetector(Context context){
        mContext = context;
    }

    public boolean onTouchEvent(MotionEvent event){
        if (!mIsGestureMoving) {
            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;
        }
        mIsGestureMoving = false;
    }
}

第二步:根据基类创建手势类

public class MoveGestureDetector extends BaseGuestureDetector {
    /** 当前的手指位置 */
    private PointF mCurrentPointF;
    /** 上次的手指位置 */
    private PointF mPrePointF;
    /** 用于记录最终结果,并返回 */
    private PointF mExtenalPointer = new PointF();

    private OnMoveGestureListener mListener;

    public MoveGestureDetector(Context context, OnMoveGestureListener listener) {
        super(context);
        this.mListener = listener;
    }

    /**
     * 处理正在进行的动作
     */
    @Override
    protected void handleInProgressEvent(MotionEvent event) {
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        switch (action) {
        // 手指弹起与离开时
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            mListener.onMoveEnd(this);
            resetState();
            break;
        // 手指移动
        case MotionEvent.ACTION_MOVE:
            updateStateByEvent(event);
            boolean move = mListener.onMove(this);
            if (move) {
                mPreMotionEvent.recycle();
                mPreMotionEvent = MotionEvent.obtain(event);
            }
            break;

        default:
            break;
        }

    }

    /**
     * 处理开始的事件
     */
    @Override
    protected void handleStartProgressEvent(MotionEvent event) {
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            // 防止没有接收到CANCEL or UP ,保险起见
            resetState();
            // 初始化
            mPreMotionEvent = MotionEvent.obtain(event);
            updateStateByEvent(event);
            break;

        case MotionEvent.ACTION_MOVE:
            mIsGestureMoving = mListener.onMoveBegin(this);
            break;
        default:
            break;
        }
    }

    @Override
    protected void updateStateByEvent(MotionEvent event) {
        final MotionEvent prev = mPreMotionEvent;
        // 计算开始点的位置
        mPrePointF = caculateFocalPointer(prev);
        mCurrentPointF = caculateFocalPointer(event);

        Log.e("TAG", mPrePointF.toString() + " ,  " + mCurrentPointF);
        // 是否跳过这个点,如果前后手指数不一样
        boolean mSkipThisMoveEvent = prev.getPointerCount() != event.getPointerCount();
        // 如果是无效的设置为0
        mExtenalPointer.x = mSkipThisMoveEvent ? 0 : mCurrentPointF.x - mPrePointF.x;
        mExtenalPointer.y = mSkipThisMoveEvent ? 0 : mCurrentPointF.y - mPrePointF.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 = x / count;
        y = y / count;
        return new PointF(x, y);
    }

    /**
     * 向外暴露的两个方法,获得移动中的位置
     * 
     * @return
     */
    public float getMoveX() {
        return mExtenalPointer.x;
    }

    public float getMoveY() {
        return mExtenalPointer.y;
    }

    /**
     * 回调函数
     * 
     * @Project App_View
     * @Package com.android.view.largeimageview
     * @author chenlin
     * @version 1.0
     * @Note TODO
     */
    public interface OnMoveGestureListener {
        /**
         * 手指开始移动
         * 
         * @param detector
         * @return
         */
        public boolean onMoveBegin(MoveGestureDetector detector);

        /**
         * 手指移动中
         * 
         * @param detector
         * @return
         */
        public boolean onMove(MoveGestureDetector detector);

        /**
         * 移动结束
         * 
         * @param 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) {
        }
    }

}

第三步:自定义LargeImageView

public class LargeImageView extends View {
    /**图片的选择的区域 */
    private BitmapRegionDecoder mDecoder;
    /**图片的宽度和高度  */
    private int mImageWidth, mImageHeight;
    /**绘制的区域*/
    private volatile Rect mRect = new Rect();
    /**移动时手势*/
    private MoveGestureDetector mDetector;
    /**
     * Creates Bitmap objects from various sources, including files, streams,
     * and byte-arrays.
     */
    private static final BitmapFactory.Options options = new BitmapFactory.Options();
    static{
        /*设置让解码器以最佳方式解码*/
        options.inPreferredConfig = Bitmap.Config.RGB_565;
    }

    public LargeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public LargeImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public LargeImageView(Context context) {
        super(context);
        init();
    }

    //初始化手势
    private void init() {
        mDetector = new MoveGestureDetector(getContext(), new SimpleMoveGestureDetector(){
            @Override
            public boolean onMove(MoveGestureDetector detector) {
                // 移动时
                int moveX = (int) detector.getMoveX();
                int moveY = (int) detector.getMoveY();

                Logger.i("large", "moveX == " + moveX);
                Logger.i("large", "moveY == " + moveY);

                //如果图片的宽度>view的宽度
                if (mImageWidth > getWidth()) {
                    //向左移动
                    mRect.offset(-moveX, 0);
                    checkWidth();
                    //重构
                    invalidate();
                }
                if (mImageHeight > getHeight()) {
                    //向上移动
                    mRect.offset(0, -moveY);
                    checkHeight();
                    //重构
                    invalidate();
                }
                return true;
            }
        });
    }


//  private OnMoveGestureListener listener = new OnMoveGestureListener(){
//
//      @Override
//      public boolean onMoveBegin(MoveGestureDetector detector) {
//          //Toast.makeText(getContext(), "开始移动", 1).show();
//          return false;
//      }
//
//      @Override
//      public boolean onMove(MoveGestureDetector detector) {
//          // 移动时
//          int moveX = (int) detector.getMoveX();
//          int moveY = (int) detector.getMoveY();
//          //如果图片的宽度>view的宽度
//          if (mImageWidth > getWidth()) {
//              //向左移动
//              mRect.offset(-moveX, 0);
//              checkWidth();
//              //重构
//              invalidate();
//          }
//          if (mImageHeight > getHeight()) {
//              //向上移动
//              mRect.offset(0, -moveY);
//              checkHeight();
//              //重构
//              invalidate();
//          }
//          return true;
//      }
//
//      @Override
//      public void onMoveEnd(MoveGestureDetector detector) {
//          //Toast.makeText(getContext(), "移动停止", 1).show();
//      }
//      
//  };

    /**
     * 把图片的宽度归位
     */
    protected void checkWidth() {
        Rect rect = mRect;
        int width = mImageWidth;

        //图片的右边 > view
        if (rect.right > width) {
            rect.right = width;
            //左边 = 图片的宽度 - 视图宽度
            rect.left = width - getWidth();
        }

        //在屏幕外
        if (rect.left < 0) {
            rect.left  = 0;
            //右边 = 视图宽度
            rect.right = getWidth();
        }

    }

    /**
     * 图片的高度归位
     */
    protected void checkHeight() {
        Rect rect = mRect;
        int height = mImageHeight;

        if (rect.bottom > height) {
            rect.bottom = height;
            rect.top = height - getHeight();
        }

        if (rect.top < 0) {
            rect.top = 0;
            rect.bottom = getHeight();
        }
    }

    /**
     * 第一步:加载图片后,显示图片的中心位置
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //指的是视图的测量宽度
        int widthMeasure = getMeasuredWidth();
        int heightMeasure = getMeasuredHeight();

        //图片实际的宽度
        int imageWidth = mImageWidth;
        int imageHeight = mImageHeight;

        //默认直接显示图片的中心区域,可以自己去调节        
        mRect.left = (imageWidth - widthMeasure)/2;
        mRect.top = (imageHeight - heightMeasure)/2;

        mRect.right = mRect.left + widthMeasure;
        mRect.bottom = mRect.top + heightMeasure;

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 第二步:把图片的事件交由手势来处理
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //touchevent事件有手势来处理
        mDetector.onTouchEvent(event);
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Bitmap bm = mDecoder.decodeRegion(mRect, options);
        //从左上角度开始画
        canvas.drawBitmap(bm, 0, 0, null);
        super.onDraw(canvas);
    }

    /**
     * 向外提供加载图片后得到的输入流
     * @param is
     * @return
     */
    protected void setInputStream(InputStream is){
        try {
            //得到要加载显示的图片区域
            mDecoder = BitmapRegionDecoder.newInstance(is, false);
            BitmapFactory.Options tmpOptions = new BitmapFactory.Options();
            tmpOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(is, null, tmpOptions);

            //获得图片的宽高
            mImageHeight = tmpOptions.outHeight;
            mImageWidth = tmpOptions.outWidth;

        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

第四步:实现

public class MainActivity extends Activity {
    private LargeImageView mImageview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_largeimage);

        mImageview = (LargeImageView) findViewById(R.id.largeImage);

        loadImage();
    }

    /**
     * 从asset文件夹里加载图片 
     */
    private void loadImage() {
        try {
            InputStream is = getAssets().open("22.jpg");
            mImageview.setInputStream(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

activity_largeimage.xml文件


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.android.view.largeimageview.LargeImageView
        android:id="@+id/largeImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    com.android.view.largeimageview.LargeImageView>

RelativeLayout>

—————————————————————————————————————————————————–

JAVA(SSM、SSH等)20项目视频教程,共134G

下载地址:

https://item.taobao.com/item.htm?id=558680925808

———————-课程目录——————————

第01项目:OA办公自动化项目(四套)
第02项目:CRM客户关系管理项目(两套)
第03项目:宅急送项目
第04项目:杰信商贸SSH版
第05项目:电力项目(两套)
第06项目:校内网项目
第07项目:Java邮件开发教程
第08项目:java网上在线支付实战视频
第09项目:俄罗斯方块游戏开发_视频教程
第10项目:交通灯管理系统视频教程
第11项目:银行业务调度系统视频教程
第12项目:供应链系统视频教程
第13项目:网上商城项目
第14项目:药品集中采购系统视频教程
第15项目:杰信商贸SSM版
第16项目:国家税务协同平台项目
第17项目:javaWeb聊天室
第18项目:点餐系统
第19项目:网上书店
第20项目:手机进销存系统
—————————————————————————————————————————————————–

你可能感兴趣的:(android,高级技术,android,手势,加载大图片,BaseGuestu)