項(xiàng)目中需要用到家在大圖吁系,圖片長度大概40000像素德召,直接加載會(huì)拋異常,所以準(zhǔn)備自己寫一個(gè)大圖的加載view,
需要實(shí)現(xiàn)的功能包括
1.加載出大圖
2.可以滑動(dòng)汽纤,需要處理邊界
3.支持手勢(shì)的縮放
1加載大圖
這里主要使用了 BitmapRegionDecoder 這個(gè)類上岗,初始化需要一個(gè)bitmap的inputStream, 可以根據(jù)添加的矩形區(qū)域,獲取到當(dāng)前bitmap在該區(qū)域的bitmap,然后繪制到view中蕴坪,
而Bitmap的獲取肴掷,需要注意要復(fù)用bitmap內(nèi)存敬锐,每次都不需要獲取新的內(nèi)存空間,避免內(nèi)存的分配與回收
需要注意的是:
api19以前格式只為jpg,png呆瞻,同等寬高台夺,inSampleSize為1才能復(fù)用
api19以后復(fù)用復(fù)用的bitmap的內(nèi)存 必須大于等于需要申請(qǐng)的bitmap的內(nèi)存
主要代碼:
try {
mBitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);
} catch (IOException e) {
e.printStackTrace();
}
//這里mRect是需要截取的矩形區(qū)域,mBitmap是截取到的bitmap
mBitmap = mBitmapRegionDecoder.decodeRegion(mRect, mOptions);
canvas.drawBitmap(mBitmap, matrix, null);
滑動(dòng)痴脾,普通手勢(shì)處理邊界颤介;慣性手勢(shì);雙擊縮放
滑動(dòng)主要是使用 GestureDetector 赞赖,
OnGestureListener滚朵,Scroller
//通過Scroller可以實(shí)現(xiàn)View在一定時(shí)間間隔內(nèi)的彈性滑動(dòng)
基本使用
//1.
mGesture = new GestureDetector(context,OnGestureListener);
@Override
public boolean onTouch(View v, MotionEvent event) {
// 2,直接將事件傳遞給手勢(shì)事件處理
mGesture.onTouchEvent(event);
return true;
}
//OnGestureListener中
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
/**
*e1 就是開始事件前域,手指按下去辕近,獲取坐標(biāo)
*e2 當(dāng)前事件;
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//3 拿到拖動(dòng)事件话侄,并修改矩形位置亏推,重新繪制
// 上下移動(dòng)的時(shí)候,mRect需要改變顯示區(qū)域
mRect.offset((int)distanceX,(int)distanceY);
// 移動(dòng)時(shí)年堆,處理到達(dá)頂部和底部的情況
if(mRect.bottom > mImageHeight){
mRect.bottom = mImageHeight;
mRect.top = mImageHeight-(int)(mViewHeight/mScale);
}
if(mRect.top < 0){
mRect.top = 0;
mRect.bottom = (int)(mViewHeight/mScale);
}
if(mRect.right > mImageWidth){
mRect.right = mImageWidth;
mRect.left = mImageWidth-(int)(mViewWidth/mScale);
}
if(mRect.left < 0 ){
mRect.left = 0;
mRect.right = (int)(mViewWidth/mScale);
}
invalidate();
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
/**
* @param e1 在手抬起來的時(shí)候回調(diào)的
* @param e2
* @param velocityX x方向速度吞杭;
* @param velocityY y方向速度;
* @return
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//將慣性事件交給mScroller
mScroller.fling(mRect.left, mRect.top,
(int) -velocityX, (int) -velocityY,
0, viewWidth,
0, viewHeight
);
return false;
}
// 處理結(jié)果 view的方法变丧;
@Override
public void computeScroll() {
if(mScroller.isFinished()){
return;
}
if(mScroller.computeScrollOffset()){
mRect.top = mScroller.getCurrY();
mRect.bottom = mRect.top+(int)(mViewHeight/mScale);
invalidate();
}
}
手勢(shì)可以添加雙擊手勢(shì)
OnDoubleTapListener芽狗,(雙擊手勢(shì))
mGestureDetector.setOnDoubleTapListener(this);
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
// 雙擊事件
if(mScale < originalScale*1.5){
mScale = originalScale*3;
}else{
mScale = originalScale;
}
mRect.right = mRect.left+(int)(mViewWidth/mScale);
mRect.bottom = mRect.top+(int)(mViewHeight/mScale);
// 移動(dòng)時(shí),處理到達(dá)頂部和底部的情況
if(mRect.bottom > mImageHeight){
mRect.bottom = mImageHeight;
mRect.top = mImageHeight-(int)(mViewHeight/mScale);
}
if(mRect.top < 0){
mRect.top = 0;
mRect.bottom = (int)(mViewHeight/mScale);
}
if(mRect.right > mImageWidth){
mRect.right = mImageWidth;
mRect.left = mImageWidth-(int)(mViewWidth/mScale);
}
if(mRect.left < 0 ){
mRect.left = 0;
mRect.right = (int)(mViewWidth/mScale);
}
invalidate();
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
3.縮放手勢(shì)
mScaleGestureDetector = new ScaleGestureDetector(context,new ScaleGesture());
// 5:處理點(diǎn)擊事件
@Override
public boolean onTouch(View v, MotionEvent event) {
// 直接將時(shí)間傳遞給手勢(shì)事件處理
mScaleGestureDetector.onTouchEvent(event);
return true;
}
// 處理縮放的回調(diào)事件
class ScaleGesture extends ScaleGestureDetector.SimpleOnScaleGestureListener{
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = mScale;
scale += detector.getScaleFactor() -1;
if(scale <= originalScale){
scale = originalScale;
}else if(scale > originalScale*5){
scale = originalScale*5;
}
mRect.right = mRect.left + (int)(mViewWidth/scale);
mRect.bottom = mRect.top + (int)(mViewHeight/scale);
mScale = scale;
invalidate();
return true;
}
}