如何TouchImageView工作的?工作、TouchImageView

2023-09-04 04:22:27 作者:心為誰碎淚為誰落

我有良好的工作TouchImageView,我想知道它是如何在一个code的工作: 我只是想要做的是能掐去放大,或使用双击放大任何ImageView的我选择,当我放大我回图像的原始大小。 TouchImageView.java:

 公共类TouchImageView扩展ImageView的{

字模=新的Matrix();

静态最终诠释无= 0;
静态最终诠释DRAG = 1;
静态最终诠释ZOOM = 2;
INT模式=无;

的PointF最后=新的PointF();
的PointF开始=新的PointF();
浮minScale = 1F;
浮maxScale = 3F;
浮动[]米;

浮redundantXSpace,redundantYSpace;

浮动宽度,高度;
静态最终诠释CLICK = 3;
浮saveScale = 1F;
浮动右,下,origWidth,origHeight,bmWidth,bmHeight;

ScaleGestureDetector mScaleDetector;

上下文语境;


公共TouchImageView(上下文的背景下){
超(上下文);
super.setClickable(真正的);
this.context =背景;
mScaleDetector =新ScaleGestureDetector(上下文,新ScaleListener());
matrix.setTranslate(1F,1F);
M =新的浮动[9];
setImageMatrix(矩阵);
setScaleType(ScaleType.MATRIX);

setOnTouchListener(新OnTouchListener(){

    @覆盖
    公共布尔onTouch(视图V,MotionEvent事件){
        mScaleDetector.onTouchEvent(事件);

        matrix.getValues​​(米);
        浮法X = M [Matrix.MTRANS_X]
        浮动Y = M [Matrix.MTRANS_Y]
        的PointF CURR =新的PointF(event.getX(),event.getY());

        开关(event.getAction()){
            案例MotionEvent.ACTION_DOWN:
                last.set(event.getX(),event.getY());
                start.set(最后一次);
                模式=阻力;
                打破;
            案例MotionEvent.ACTION_MOVE:
                如果(模式==拖动){
                    浮DELTAX = curr.x  -  last.x;
                    漂浮移动deltaY = curr.y  -  last.y;
                    浮scaleWidth = Math.round(origWidth * saveScale);
                    浮scaleHeight = Math.round(origHeight * saveScale);
                    如果(scaleWidth<宽度){
                        DELTAX = 0;
                        如果(Y +移动deltaY大于0)
                            移动deltaY = -y;
                        否则,如果(Y +移动deltaY<汉字)
                            移动deltaY =  - (Y +底部);
                    }否则如果(scaleHeight<高度){
                        移动deltaY = 0;
                        如果(X + DELTAX大于0)
                            DELTAX = -x;
                        否则,如果(X + DELTAX<右汉字)
                            DELTAX =  - (X +右);
                    } 其他 {
                        如果(X + DELTAX大于0)
                            DELTAX = -x;
                        否则,如果(X + DELTAX<右汉字)
                            DELTAX =  - (X +右);

                        如果(Y +移动deltaY大于0)
                            移动deltaY = -y;
                        否则,如果(Y +移动deltaY<汉字)
                            移动deltaY =  - (Y +底部);
                    }
                    matrix.postTranslate(DELTAX,移动deltaY);
                    last.set(curr.x,curr.y);
                }
                打破;

            案例MotionEvent.ACTION_UP:
                模式=无;
                INT xDiff =(INT)Math.abs(curr.x  -  start.x);
                INT yDiff =(INT)Math.abs(curr.y  -  start.y);
                如果(xDiff<点击&功放;&安培; yDiff<点击)
                    performClick();
                打破;

            案例MotionEvent.ACTION_POINTER_UP:
                模式=无;
                打破;
        }
        setImageMatrix(矩阵);
        无效();
        返回true; //表示事件已经被处理
    }

});
}

@覆盖
公共无效setImageBitmap(位图BM){
super.setImageBitmap(BM);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}

公共无效setMaxZoom(浮X)
{
maxScale = X;
}

私有类ScaleListener扩展ScaleGestureDetector.SimpleOnScaleGestureListener {
@覆盖
公共布尔onScaleBegin(ScaleGestureDetector检测器){
    模式=变焦;
    返回true;
}

@覆盖
公共布尔onScale(ScaleGestureDetector检测器){
    浮动mScaleFactor =(浮点)Math.min(Math.max(.95f,detector.getScaleFactor()),1.05);
    浮origScale = saveScale;
    saveScale * = mScaleFactor;
    如果(saveScale> maxScale){
        saveScale = maxScale;
        mScaleFactor = maxScale / origScale;
    }否则如果(saveScale< minScale){
        saveScale = minScale;
        mScaleFactor = minScale / origScale;
    }
    右=宽* saveScale  - 宽 - (2 * redundantXSpace * saveScale);
    底部=身高* saveScale  - 高 - (2 * redundantYSpace * saveScale);
    如果(origWidth * saveScale< =宽度|| origHeight * saveScale< =身高){
        matrix.postScale(mScaleFactor,mScaleFactor,宽/ 2,高度/ 2);
        如果(mScaleFactor&小于1){
            matrix.getValues​​(米);
            浮法X = M [Matrix.MTRANS_X]
            浮动Y = M [Matrix.MTRANS_Y]
            如果(mScaleFactor&小于1){
                如果(Math.round(origWidth * saveScale)<宽度){
                    如果(Y<汉字)
                        matrix.postTranslate(0, - (Y +底部));
                    否则如果(γ大于0)
                        matrix.postTranslate(0,-y);
                } 其他 {
                    如果(X<右汉字)
                        matrix.postTranslate( - (X +右),0);
                    否则如果(X 0)
                        matrix.postTranslate(-x,0);
                }
            }
        }
    } 其他 {
        matrix.postScale(mScaleFactor,mScaleFactor,detector.getFocusX(),detector.getFocusY());
        matrix.getValues​​(米);
        浮法X = M [Matrix.MTRANS_X]
        浮动Y = M [Matrix.MTRANS_Y]
        如果(mScaleFactor&小于1){
            如果(X<右汉字)
                matrix.postTranslate( - (X +右),0);
            否则如果(X 0)
                matrix.postTranslate(-x,0);
            如果(Y<汉字)
                matrix.postTranslate(0, - (Y +底部));
            否则如果(γ大于0)
                matrix.postTranslate(0,-y);
        }
    }
    返回true;

}
}

@覆盖
保护无效onMeasure(INT widthMeasureSpec,INT heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
宽度= MeasureSpec.getSize(widthMeasureSpec);
身高= MeasureSpec.getSize(heightMeasureSpec);
//适应屏幕。
浮规模;
浮动的scaleX =(浮点)宽/(浮点)bmWidth;
浮动的scaleY =(浮点)高度/(浮点)bmHeight;
规模= Math.min(将scaleX,的scaleY);
matrix.setScale(秤,秤);
setImageMatrix(矩阵);
saveScale = 1F;

//中心图像
redundantYSpace =(浮点)高度 - (规模*(浮点)bmHeight);
redundantXSpace =(浮点)宽度 - (规模*(浮点)bmWidth);
redundantYSpace / =(浮点)2;
redundantXSpace / =(浮点)2;

matrix.postTranslate(redundantXSpace,redundantYSpace);

origWidth =宽度 -  2 * redundantXSpace;
origHeight =身高 -  2 * redundantYSpace;
右=宽* saveScale  - 宽 - (2 * redundantXSpace * saveScale);
底部=身高* saveScale  - 高 - (2 * redundantYSpace * saveScale);
setImageMatrix(矩阵);
}

}
 

要使用的是我创建了一个私有类:

 私有类的createImage扩展的AsyncTask<字符串,太虚,可绘制> {
    在preExecute保护无效(){
    }

    受保护的可绘制doInBackground(字符串...网址){
        InputStream的是;
        绘制对象D = NULL;
        尝试 {
            为=(InputStream的)新的URL(网址[0])的getContent()。
            D = Drawable.createFromStream(是,图像);
            返回D组;
        }赶上(MalformedURLException异常E){
            // TODO自动生成的catch块
            e.printStackTrace();
        }赶上(IOException异常E){
            // TODO自动生成的catch块
            e.printStackTrace();
        }
        返回D组;
    }
    保护无效onPostExecute(可绘制D){
        touch.setMaxZoom(4F);
        touch.setImageDrawable(四);
        的setContentView(触摸);
    }
}
公共无效createUrlImage(字符串URL){
    新的createImage()执行(URL);
}
 

和在OnCreate(),我把createUrlImage(URL)。 我修改TouchImageView加入:

 公共无效setImageDrawable(可绘制DR){
super.setImageDrawable(DR);
bmWidth = dr.getIntrinsicWidth();
bmHeight = dr.getIntrinsicHeight();
}
 
苹果中国官网1月6日全线降价 ipad2促销价格优惠450元

解决方案

编辑:枪王变焦,一扔等功能已被添加到TouchImageView,因为我本来回答了这个问题。您可以检查它在github 这里。

我加了一些使用细节原来的职位here.在code已经拥有双指缩放和平移,以及边界。此外,缩小将返回到原始大小的图片。

添加枪王变焦将采取更多的工作。你必须使用一个GestureDetector并覆盖onDoubleTap和onSingleTapConfirmed。然后,你要确保你通过触摸事件gestureDetector,不与的code,其余的干扰(看看事件传递给mScaleDetector在onTouch的开始)。你想摆脱调用performClick()在ACTION_UP的,而是把它放在onSingleTapConfirmed。您可以检查this回答一些骨骼code,让你在执行GestureDetector开始。

让我知道如果你设法让双击缩放坚实的,我会加入您改动原来的职位和Github上回购。

I have good working TouchImageView and i want to know how does it work in a code : What i just want to do is be able to pinch to zoom, or use double tap to zoom on any imageview i choose, and when i zoom back i return to the original size of the image. TouchImageView.java :

public class TouchImageView extends ImageView {

Matrix matrix = new Matrix();

static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;

PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;

float redundantXSpace, redundantYSpace;

float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

ScaleGestureDetector mScaleDetector;

Context context;


public TouchImageView(Context context) {
super(context);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);

setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mScaleDetector.onTouchEvent(event);

        matrix.getValues(m);
        float x = m[Matrix.MTRANS_X];
        float y = m[Matrix.MTRANS_Y];
        PointF curr = new PointF(event.getX(), event.getY());

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = DRAG;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float scaleWidth = Math.round(origWidth * saveScale);
                    float scaleHeight = Math.round(origHeight * saveScale);
                    if (scaleWidth < width) {
                        deltaX = 0;
                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom); 
                    } else if (scaleHeight < height) {
                        deltaY = 0;
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);
                    } else {
                        if (x + deltaX > 0)
                            deltaX = -x;
                        else if (x + deltaX < -right)
                            deltaX = -(x + right);

                        if (y + deltaY > 0)
                            deltaY = -y;
                        else if (y + deltaY < -bottom)
                            deltaY = -(y + bottom);
                    }
                    matrix.postTranslate(deltaX, deltaY);
                    last.set(curr.x, curr.y);
                }
                break;

            case MotionEvent.ACTION_UP:
                mode = NONE;
                int xDiff = (int) Math.abs(curr.x - start.x);
                int yDiff = (int) Math.abs(curr.y - start.y);
                if (xDiff < CLICK && yDiff < CLICK)
                    performClick();
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
        }
        setImageMatrix(matrix);
        invalidate();
        return true; // indicate event was handled
    }

});
}

@Override
public void setImageBitmap(Bitmap bm) { 
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}

public void setMaxZoom(float x)
{
maxScale = x;
}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
    mode = ZOOM;
    return true;
}

@Override
public boolean onScale(ScaleGestureDetector detector) {
    float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
    float origScale = saveScale;
    saveScale *= mScaleFactor;
    if (saveScale > maxScale) {
        saveScale = maxScale;
        mScaleFactor = maxScale / origScale;
    } else if (saveScale < minScale) {
        saveScale = minScale;
        mScaleFactor = minScale / origScale;
    }
    right = width * saveScale - width - (2 * redundantXSpace * saveScale);
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
    if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
        matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
        if (mScaleFactor < 1) {
            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            if (mScaleFactor < 1) {
                if (Math.round(origWidth * saveScale) < width) {
                    if (y < -bottom)
                        matrix.postTranslate(0, -(y + bottom));
                    else if (y > 0)
                        matrix.postTranslate(0, -y);
                } else {
                    if (x < -right) 
                        matrix.postTranslate(-(x + right), 0);
                    else if (x > 0) 
                        matrix.postTranslate(-x, 0);
                }
            }
        }
    } else {
        matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
        matrix.getValues(m);
        float x = m[Matrix.MTRANS_X];
        float y = m[Matrix.MTRANS_Y];
        if (mScaleFactor < 1) {
            if (x < -right) 
                matrix.postTranslate(-(x + right), 0);
            else if (x > 0) 
                matrix.postTranslate(-x, 0);
            if (y < -bottom)
                matrix.postTranslate(0, -(y + bottom));
            else if (y > 0)
                matrix.postTranslate(0, -y);
        }
    }
    return true;

}
}

@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
//Fit to screen.
float scale;
float scaleX =  (float)width / (float)bmWidth;
float scaleY = (float)height / (float)bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;

// Center the image
redundantYSpace = (float)height - (scale * (float)bmHeight) ;
redundantXSpace = (float)width - (scale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;

matrix.postTranslate(redundantXSpace, redundantYSpace);

origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}

}

To use is i created a private class :

private class CreateImage extends AsyncTask<String, Void, Drawable> {
    protected void onPreExecute() {
    }

    protected Drawable doInBackground(String... urls) {
        InputStream is;
        Drawable d = null ;
        try {
            is = (InputStream)new URL(urls[0]).getContent();
            d = Drawable.createFromStream(is, "Image");
            return d;
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return d;
    }
    protected void onPostExecute(Drawable d) {
        touch.setMaxZoom(4f);
        touch.setImageDrawable(d);
        setContentView(touch);
    }
}
public void createUrlImage(String url){
    new CreateImage().execute(url);
}

and in the onCreate() i put createUrlImage(url). I modified TouchImageView by adding :

public void setImageDrawable(Drawable dr) { 
super.setImageDrawable(dr);
bmWidth = dr.getIntrinsicWidth();
bmHeight = dr.getIntrinsicHeight();
}

解决方案

EDIT: Double Tap Zoom, Fling and other features have been added to TouchImageView since I originally answered this question. You can check it out on github here.

I added some usage details to the original post here. The code already has pinch zoom and panning, along with boundaries. Also, zooming out will return you to the original sized image.

Adding double tap zoom will take more work. You'll have to use a GestureDetector and override onDoubleTap and onSingleTapConfirmed. You'll then want to make sure you pass your touch events to gestureDetector, without interfering with the rest of the code (see how events are passed to mScaleDetector at the beginning of onTouch). You'll want to get rid of the call to performClick() in ACTION_UP and instead place it in onSingleTapConfirmed. You can check this answer for some skeletal code to get you started in implementing GestureDetector.

Let me know if you manage to get double tap zoom solid and I'll add your changes to the original post and the Github repo.