在Android上点击按钮时如何将图像 "放大/缩小"?

6
我是Android的新手。我已经遵循了这个问题,并成功地缩放了一张图片,这段代码正在很好地运行,请问有人能帮助我编写按钮单击时的缩放代码吗?我不知道如何完成这个任务。
这是我遵循的教程Tutorial Zoom Image,并且也关注了"Salman's Ayub Answer"。
它可以正常工作,但我无法在图像的缩放中应用比例因子。

你有兴趣通过 XML 来完成这项工作吗? - user1644532
我不想使用XML,我已经提到了我想通过定义比例来完成的教程。 - user3233280
请检查答案,谢谢。 - Salman Khakwani
3个回答

7

您需要将以下两个方法添加到您的TouchImageView类中:

public void zoomIn() {
    oldScale = saveScale;

    if(saveScale<=maxScale)
    {
        saveScale += .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }

        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}

public void zoomOut() {

    if(saveScale>=minScale)
    {
        saveScale -= .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }
        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}

以下是完整的TouchImageView类代码,以及这两个方法:

下面是完整的TouchImageView类代码,以及这两个方法:

public class TouchImageView extends ImageView {

public Matrix matrix = new Matrix();

// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int CLICK = 3;
int mode = NONE;
float oldScale = 1.0f;

// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 4f;
float[] m;

float redundantXSpace, redundantYSpace;   
float width, height;
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_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    Log.d("******", "ZOOM OR 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);
                }else if(mode == DRAG && saveScale == minScale) {
                    Log.d("******", "DRAG");
                }
                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 = detector.getScaleFactor();//(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 =  width / bmWidth;
    float scaleY = height / bmHeight;
    scale = Math.min(scaleX, scaleY);
    matrix.setScale(scale, scale);
    setImageMatrix(matrix);
    saveScale = 1f;

    // Center the image
    redundantYSpace = height - (scale * bmHeight) ;
    redundantXSpace = width - (scale * bmWidth);
    redundantYSpace /= 2;
    redundantXSpace /= 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);
}

public TouchImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    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_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    Log.d("******", "ZOOM OR 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);
                }else if(mode == DRAG && saveScale == minScale) {
                    Log.d("******", "DRAG");
                }
                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
        }

    });
}

public TouchImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    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_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    Log.d("******", "ZOOM OR 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);
                }else if(mode == DRAG && saveScale == minScale) {
                    Log.d("******", "DRAG");
                }
                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
        }

    });
}

public void zoomIn() {
    oldScale = saveScale;

    if(saveScale<=maxScale)
    {
        saveScale += .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }

        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}

public void zoomOut() {

    if(saveScale>=minScale)
    {
        saveScale -= .5;
        matrix.setScale(saveScale, saveScale);
        setImageMatrix(matrix);
        invalidate();

        // Center the image
        if(bmHeight>bmWidth)
        {
        redundantXSpace = width - (saveScale * bmWidth);
        redundantXSpace /= 2;
        }
        else 
        {
            redundantYSpace = height - (saveScale * bmHeight) ;
            redundantYSpace /= 2;
        }
        matrix.postTranslate(redundantXSpace , redundantYSpace );
        setImageMatrix(matrix);
        invalidate();
    }
}
} 

以下是您如何在缩放按钮中使用它们的方法:
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.LAYOUT_NAME);

    Button zoonIn = (Button)findViewById(R.id.ZOOM_IN_BUTTON_ID);
    Button zoonOut = (Button)findViewById(R.id.ZOOM_OUT_BUTTON_ID);

    final TouchImageView touch = (TouchImageView)findViewById(R.id.YOUR_TOUCH_IMAGE_VIEW_)ID);

    Bitmap bImage = BitmapFactory.decodeResource(this.getResources(), R.drawable.DRAWABLE_ID);

    touch.setImageBitmap(bImage);

    touch.setMaxZoom(4f); //change the max level of zoom, default is 3f


    zoonIn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            touch.zoomIn();
        }
    });


    zoonOut.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            touch.zoomOut();
        }
    });

}

我希望这会对您有所帮助。

你能帮我吗?我想要在滚动视图中放置“ImageView”,同时固定页眉和页脚。我已经做了这个,但有时我的ImageView太短,页脚会消失。 - user3233280
这是我的 XML,请您编辑一下,以便更清晰地显示图像,但页眉和页脚应该固定。 - user3233280
这里的触摸imageView非常小,且显示在中心位置。 - user3233280
@MrSMAK,你能帮我吗?我该如何编写分页的放大缩小按钮代码?我正在使用分页,在每个页面上都会有一张图片和放大缩小按钮。我应该在哪里编写放大缩小按钮的代码?我需要在这个方法中编写放大缩小按钮的功能吗:public Object instantiateItem(ViewGroup container, int position) {} - Erum
@MrSMAK,你能帮我一下关于TouchImageView的放大和缩小吗?我的问题是在哪里应该写放大和缩小按钮的代码,是在这个方法中:public View instantiateItem(ViewGroup container, int position) { PhotoView photoView = new PhotoView(container.getContext()); - Erum
显示剩余7条评论

4

在按钮上放大/缩小图片的最简单方法是将其显示在webView中,这样您就可以使用webView提供的所有功能。

将您的图像复制到assets文件夹中,然后在onCreate中加载它:

WebView mWebView = (WebView) findViewById(R.id.webView1);
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mWebView.setBackgroundColor(Color.parseColor("#ffffff"));
mWebView.loadUrl("file:///android_asset/image.png");
mWebView.getSettings().setBuiltInZoomControls(true);
mWebView.setInitialScale(50);

如何设置最大和最小缩放级别? - user3233280
通过使用webView支持的内置(-/+)缩放控制器,可以实现缩放功能。以下是一个示例链接:link。或者,如果您想要设置初始缩放级别,请使用以下方法:mWebView.setInitialScale(50),其中输入值介于0-100%之间。 - Mohammed Alokshiya
它绝对有效,所以我会点赞,但请注意与在ImageView中显示图像的一些区别:1)ImageView中的图像会自动调整大小以适应视图的大小,2)在ImageView中有轻松的选项来居中图像。 - Software Prophets

1

尝试使用PhotoView。我认为它可以直接满足您的需求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接