如何捏缩放工作,在Android中平移图像 [英] How does pinch zoom work with panning for image in Android

查看:143
本文介绍了如何捏缩放工作,在Android中平移图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


目标

这是活动是由观看图像,我们可以捏缩放或平移图像。图像在开始屏幕居中。捏变焦是在图像的中心居中,图像被摇摄别处在屏幕即使

用于显示从给定的URL下载,网址是从意图传递额外的启动图像的观看活动的形象。

捏变焦通过实施分频器(),由的postTranslate锅()


问题

某处平移图像后,将捏变焦中心仍然是在屏幕的中心。试图按照图像的中心,当它被移动到一个新的地方,但我的code不这样的。请给一些想法。

图片下载和平移工作做好。


code

activity_image_viewer_layout.xml

 <?XML版本=1.0编码=UTF-8&GT?;
<的FrameLayout
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT>    <的LinearLayout
        机器人:方向=垂直
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =FILL_PARENT
        机器人:比重=中心
        机器人:背景=@色/ MyPureBlack>        <的LinearLayout
          机器人:ID =@ + ID / progressbar_wrapper
            机器人:layout_width =FILL_PARENT
            机器人:layout_height =WRAP_CONTENT
            机器人:方向=垂直>            <进度
                机器人:ID =@ + ID /进度
                风格=机器人:ATTR / progressBarStyleHorizo​​ntal
                机器人:layout_width =FILL_PARENT
                机器人:layout_height =WRAP_CONTENT
                机器人:最大=100
                机器人:进度=0
                机器人:layout_marginLeft =20dp
                机器人:layout_marginRight =20dp
                机器人:layout_gravity =中心>
            < /进度>
        < / LinearLayout中>        < ImageView的
            机器人:ID =@ + ID / image_viewer
            机器人:知名度=水涨船高
            机器人:layout_width =FILL_PARENT
            机器人:layout_height =FILL_PARENT
            机器人:背景=@彩色/ MyPureBlack
            机器人:scaleType =黑客帝国>
        < / ImageView的>
    < / LinearLayout中>
< /&的FrameLayout GT;

ActivityImageViewer.java

包com.com2us.hubapp.android;进口java.io.BufferedInputStream中;
进口的java.io.File;
进口java.io.FileOutputStream中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.io.OutputStream中;
进口java.lang.reflect.InvocationTargetException;
进口的java.lang.reflect.Method;
进口的java.net.URL;
进口java.net.URLConnection中;进口org.apache.http.util.ByteArrayBuffer;进口android.app.Activity;
进口android.content.res.Configuration;
进口android.graphics.Bitmap;
进口android.graphics.BitmapFactory;
进口android.graphics.Matrix;
进口android.graphics.PointF;
进口android.graphics.Rect;
进口android.graphics.RectF;
进口android.graphics.drawable.BitmapDrawable;
进口android.graphics.drawable.Drawable;
进口android.net.Uri;
进口android.os.AsyncTask;
进口android.os.Bundle;
进口android.util.FloatMath;
进口android.util.Log;
进口android.view.KeyEvent;
进口android.view.MotionEvent;
进口android.view.View;
进口android.view.View.OnTouchListener;
进口android.view.ViewTreeObserver;
进口android.view.ViewTreeObserver.OnGlobalLayoutListener;
进口android.view.animation.AlphaAnimation;
进口android.widget.ImageView;
进口android.widget.LinearLayout;
进口android.widget.ProgressBar;公共类ActivityImageViewer延伸活动{
    文件镜像文件= NULL;    //为矩阵捏缩放和平移
    字模=新的Matrix();
    矩阵savedMatrix =新的Matrix();
    矩阵savedMatrixZoom =新的Matrix();    //移动事件的国家
    静态最终诠释NONE = 0;
    静态最终诠释潘= 1;
    静态最终诠释PINCH_ZOOM = 2;
    INT模式=无;    //第一个指针下降
    的PointF开始=新的PointF();    //图像的中心(无法跟踪它时,图像已被移动)
    的PointF centerOfImage =新的PointF();    //最早的是前两个指针之间的距离笛卡尔当第二指针下降
    浮oldDist = 1F;    // MIN_SCALE / MAX_SCALE是最小/最大比例因子
    私人最终浮动MIN_SCALE = 0.5F;
    私人最终浮动MAX_SCALE = 3.0F;    // TOUCH_SENSITIVE是前两个指针之间触发捏变焦最小笛卡尔距离
    私人最终浮动TOUCH_SENSITIVE = 10.0f;
    私人最终浮动SPACING_LEFT_AND_RIGHT = 30.0f;
    私人最终浮动SPACING_TOP_AND_BOTTOM = 30.0f;    //该ImageView的部件
    私人ImageView的image_viewer;    //进度条显示目前的进展是完成图像下载之前
    私人进度进度;
    私人的LinearLayout progressbar_wrapper;    //从给定的URL下载图像异步任务
    私人DownloadFilesTask downloadFilesTask;    私有类DownloadFilesTask扩展的AsyncTask<字符串,整数位图> {
        保护位图doInBackground(字符串的URL ...){
            输入的InputStream = NULL;
            OutputStream的输出= NULL;
            尝试{
                网址URL =新的URL(网址[0]);
                URLConnection的连接= url.openConnection();
                connection.connect();
                INT lenghtOfFile = connection.getContentLength();
                //下载文件
                InputStream为= connection.getInputStream();
                二BufferedInputStream为=新的BufferedInputStream(是,8190);                ByteArrayBuffer BAF =新ByteArrayBuffer(50);
                INT电流= 0;
                而((电流= bis.read())!= - 1){
                    baf.append((字节)电流);
                }
                字节[]为imageData = baf.toByteArray();
                BMP位图= BitmapFactory.de codeByteArray的(为imageData,0,imageData.length);                //最终诠释百分比=(INT)(总* 100 / lenghtOfFile);
                // publishProgress(百分比);
                // lenghtOfFile                返回BMP;
            }赶上(例外五){            } {最后
                尝试{
                    如果(输出!= NULL)
                        output.close();
                    输出= NULL;
                }赶上(IOException异常五){                }
                尝试{
                    如果(输入!= NULL)
                        input.close();
                    输入= NULL;
                }赶上(IOException异常五){                }            }
            返回null;
        } //保护位图doInBackground(字符串的URL ...){}        保护无效onProgressUpdate(整数...进度){
            progressbar.setProgress(进展[0]);
        }        保护无效onPostExecute(BMP位图){
            如果(BMP!= NULL){
                最后AlphaAnimation animationAfter =新AlphaAnimation(0.0,1.0F);
                animationAfter.setDuration(300);
                animationAfter.setFillEnabled(真);
                animationAfter.setFillAfter(真);
                image_viewer.setAnimation(animationAfter);
                image_viewer.setImageBitmap(BMP);
                ViewTreeObserver viewTreeObserver = image_viewer.getViewTreeObserver();
                viewTreeObserver.addOnGlobalLayoutListener(新OnGlobalLayoutListener(){
                    @覆盖
                    公共无效onGlobalLayout(){
                        可绘制可绘制= image_viewer.getDrawable();
                        INT DX =(image_viewer.getWidth() - drawable.getIntrinsicWidth())/ 2;
                        INT DY =(image_viewer.getHeight() - drawable.getIntrinsicHeight())/ 2;
                        matrix.postTranslate(DX,DY);
                        image_viewer.setImageMatrix(矩阵);
                    }
                });
                progressbar_wrapper.setVisibility(View.GONE);
                image_viewer.setVisibility(View.VISIBLE);
            }其他{
                android.os.Handler处理程序=新android.os.Handler();
                handler.postDelayed(新的Runnable(){
                    @覆盖
                    公共无效的run(){
                        完();
                    }
                },2000);
            }
        } //保护无效onPostExecute结束(BMP位图){}
    } //私有类DownloadFilesTask的一端延伸的AsyncTask<字符串,整数位图> {}    //这些活动的生命周期处理
    //的onCreate
    @覆盖
    公共无效的onCreate(捆绑savedInstanceState){
        //setTheme(R.style.HubTheme);
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_image_viewer);
        progressbar_wrapper =(的LinearLayout)findViewById(R.id.progressbar_wrapper);
        image_viewer =(ImageView的)findViewById(R.id.image_viewer);
        进度=(进度)findViewById(R.id.progressbar);
        image_viewer.setOnTouchListener(新MyOnTouchListener());
        最后弦乐uriForImage = getIntent()getStringExtra(URL)。
        downloadFilesTask =新DownloadFilesTask();
        downloadFilesTask.execute(uriForImage);
    }    //调用onStart
    @覆盖
    保护无效调用onStart(){
        super.onStart();
    }    // onResume
    @覆盖
    保护无效onResume(){
        super.onResume();
    }    //的onPause
    @覆盖
    保护无效的onPause(){
        super.onPause();
    }    //的onStop
    @覆盖
    保护无效的onStop(){
        super.onStop();
    }    // onRestart
    @覆盖
    保护无效onRestart(){
        super.onRestart();
    }    //的onDestroy
    @覆盖
    保护无效的onDestroy(){
        super.onDestroy();
        如果(镜像文件!= NULL){
            尝试{
                可绘制可绘制= image_viewer.getDrawable();
                BitmapDrawable bitmapDrawable =(BitmapDrawable)绘制;
                位图的位图= bitmapDrawable.getBitmap();
                bitmap.recycle();                可绘制= NULL;
                bitmapDrawable = NULL;
                位= NULL;            }赶上(NullPointerException异常五){
            }
        }
    }    //的onkeydown
    @覆盖
    公共布尔的onkeydown(INT键code,KeyEvent的事件){
        如果(键code == KeyEvent.KEY code_BACK){
            this.onBack pressed();
        }
        返回true;
    }    // onBack pressed
    公共无效onBack pressed(){
        完();
    }    // onConfigurationChanged
    @覆盖
    公共无效onConfigurationChanged(配置NEWCONFIG){        super.onConfigurationChanged(NEWCONFIG);
        如果(newConfig.equals(Configuration.ORIENTATION_LANDSCAPE)){        }否则如果(newConfig.equals(Configuration.ORIENTATION_PORTRAIT)){        }
    }    // onLowMemory
    @覆盖
    公共无效onLowMemory(){
        super.onLowMemory();
        完();
    }    //获取前两个指针之间的距离笛卡尔
    私人浮动间距(MotionEvent事件){
        浮X = 0;
        浮Y = 0;
        尝试{
            方法的getX = MotionEvent.class.getMethod(信息getX,Integer.TYPE);
            方法=的getY MotionEvent.class.getMethod(信息getX,Integer.TYPE);            // X = event.getX(0) - event.getX(1);
            // Y = event.getY(0) - event.getY(1);
            浮X1 =(浮动)getX.invoke(事件,0);
            浮X2 =(浮动)getX.invoke(事件1);
            X = X1 - X2;
            浮Y1 =(浮动)getY.invoke(事件,0);
            浮Y2 =(浮动)getY.invoke(事件1);
            Y = Y1 - Y2;        }赶上(SecurityException异常五){
        }赶上(NoSuchMethodException E){
        }赶上(抛出:IllegalArgumentException五){
        }赶上(IllegalAccessException E){
        }赶上(的InvocationTargetException E){
        }
        返回FloatMath.sqrt(X * X + Y * Y);
    }    //某些标志手动设置方便
    私人最终诠释MotionEvent_ACTION_MASK = 255; //这为0xFF或11111111
    私人最终诠释MotionEvent_ACTION_POINTER_DOWN = 5; //这是101
    私人最终诠释MotionEvent_ACTION_POINTER_UP = 6; //这是110    私有类MyOnTouchListener实现OnTouchListener {        // onTouch
        @覆盖
        公共布尔onTouch(视图V,MotionEvent事件){
            ImageView的观点=(ImageView的)V;
            可绘制可绘制= view.getDrawable();
            如果(绘制== NULL)
                返回true;
            开关(event.getAction()及MotionEvent_ACTION_MASK){
            案例MotionEvent.ACTION_DOWN:
                savedMatrix.set(矩阵);
                start.set(event.getX(),event.getY());
                模式= PAN;
                打破;
            案例MotionEvent_ACTION_POINTER_DOWN:
                oldDist =间距(事件);
                如果(oldDist> TOUCH_SENSITIVE){
                    savedMatrix.set(矩阵);
                    模式= PINCH_ZOOM;
                }
                打破;
            案例MotionEvent.ACTION_UP:
            案例MotionEvent_ACTION_POINTER_UP:
                模式=无;
                打破;
            案例MotionEvent.ACTION_MOVE:
                如果(==模式PAN){
                    // /////////////////////////////////////////
                    matrix.set(savedMatrix);
                    浮动[] = matrixValues​​新的浮动[9];
                    矩形viewRect =新的Rect(view.getLeft(),view.getTop(),view.getRight(),view.getBottom());
                    matrix.getValues​​(matrixValues​​);
                    浮currentY = matrixValues​​ [Matrix.MTRANS_Y]
                    浮currentX = matrixValues​​ [Matrix.MTRANS_X]
                    浮currentScale = matrixValues​​ [Matrix.MSCALE_X]
                    浮currentHeight = drawable.getIntrinsicHeight()* currentScale;
                    浮currentWidth = drawable.getIntrinsicWidth()* currentScale;
                    浮DX = event.getX() - start.x;
                    浮DY = event.getY() - start.y;
                    浮下一页末= currentX + DX;
                    浮newy指定= currentY + DY;                    RectF drawingRect =新RectF(下一页末,newy指定,下一页末+ currentWidth,newy指定+ currentHeight);
                    浮diffUp = Math.min(viewRect.bottom - drawingRect.bottom,viewRect.top - drawingRect.top) - SPACING_TOP_AND_BOTTOM;
                    浮diffDown = Math.max(viewRect.bottom - drawingRect.bottom,viewRect.top - drawingRect.top)+ SPACING_TOP_AND_BOTTOM;
                    浮diffLeft = Math.min(viewRect.left - drawingRect.left,v​​iewRect.right - drawingRect.right) - SPACING_LEFT_AND_RIGHT;
                    浮diffRight = Math.max(viewRect.left - drawingRect.left,v​​iewRect.right - drawingRect.right)+ SPACING_LEFT_AND_RIGHT;
                    如果(diffUp大于0){
                        DY + = diffUp;
                    }
                    如果(diffDown℃,){
                        DY + = diffDown;
                    }
                    如果(diffLeft大于0){
                        DX + = diffLeft;
                    }
                    如果(diffRight℃,){
                        DX + = diffRight;
                    }
                    matrix.postTranslate(DX,DY);
                }否则如果(==模式PINCH_ZOOM){
                    浮newDist =间距(事件);
                    如果(newDist> TOUCH_SENSITIVE){
                        matrix.set(savedMatrix);
                        浮规模= newDist / oldDist;                        //获取图像的中心。 (无法获取它时,图像已被移动)
                        矩形viewRect =新的Rect(view.getLeft(),view.getTop(),view.getRight(),view.getBottom());
                        centerOfImage.x = viewRect.centerX();
                        centerOfImage.y = viewRect.centerY();                        浮动[] F =新的浮动[9];
                        矩阵TMP =新的Matrix(矩阵);
                        tmp.postScale(规模化,规模化,centerOfImage.x,centerOfImage.y);
                        tmp.getValues​​(F);
                        漂浮的scaleX = F [Matrix.MSCALE_X]
                        如果(将scaleX< MIN_SCALE ||将scaleX> MAX_SCALE){
                            matrix.set(savedMatrixZoom);
                        }其他{
                            matrix.postScale(规模化,规模化,centerOfImage.x,centerOfImage.y);
                            savedMatrixZoom.set(矩阵);
                        }
                    }
                }
                打破;
            }
            view.setImageMatrix(矩阵);
            返回true;
        } //公共布尔onTouch(视图V,MotionEvent事件){结束}    } //私有类MyOnTouchListener年底实现OnTouchListener {}} //公共类ActivityImageViewer的一端延伸活动{}


解决方案

您可以使用捏缩放手势缩放探测器。而不是创建捏从头开始放大,你可以做这样的事情之后,

 公共类MyCustomView扩展视图{私人ScaleGestureDetector mScaleDetector;
私人浮动mScaleFactor = 1.F;公共MyCustomView(上下文mContext){
    ...
    //查看code到这里
    ...
    mScaleDetector =新ScaleGestureDetector(上下文,新ScaleListener());
}@覆盖
公共布尔onTouchEvent(MotionEvent EV){
    //让ScaleGestureDetector检查所有事件。
    mScaleDetector.onTouchEvent(EV);
    返回true;
}@覆盖
公共无效的onDraw(帆布油画){
    super.onDraw(画布);    canvas.save();
    canvas.scale(mScaleFactor,mScaleFactor);
    ...
    //的onDraw()code到这里
    ...
    canvas.restore();
}私有类ScaleListener
        扩展ScaleGestureDetector.SimpleOnScaleGestureListener {
    @覆盖
    公共布尔onScale(ScaleGestureDetector检测器){
        mScaleFactor * = detector.getScaleFactor();        //不要让对象获取过小或过大。
        mScaleFactor = Math.max(0.1F,Math.min(mScaleFactor,5.0F));        无效();
        返回true;
    }
}
}

请注意:你的翻译将驻留在的onDraw方法来缩放图像


Goal

An activity is made to view image, we can pinch zoom or pan the image. The image is centered in the screen in the beginning. Pinch zoom is centered at the center of the image, even after the image is panned somewhere else in the screen.

The image for displaying is downloaded from a given URL, and the URL is passed from extra of an intent to start the image viewing activity.

Pinch zoom is implemented by postScale(), pan by postTranslate().


Problem

After panning the image somewhere, the pinch-zoom center is still at the center of the screen. Tried to follow the center of the image when it's been moved to a new place but my code doesn't work that way. Please give some idea.

The image downloading and panning work well.


Code

activity_image_viewer_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:orientation="vertical" 
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:background="@color/MyPureBlack" >

        <LinearLayout
          android:id="@+id/progressbar_wrapper"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ProgressBar 
                android:id="@+id/progressbar"
                style="?android:attr/progressBarStyleHorizontal" 
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:max="100"
                android:progress="0"
                android:layout_marginLeft="20dp"
                android:layout_marginRight="20dp"
                android:layout_gravity="center" >
            </ProgressBar>
        </LinearLayout>

        <ImageView
            android:id="@+id/image_viewer" 
            android:visibility="gone"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" 
            android:background="@color/MyPureBlack"
            android:scaleType="matrix" >
        </ImageView>
    </LinearLayout>
</FrameLayout>

ActivityImageViewer.java

package com.com2us.hubapp.android;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;

import org.apache.http.util.ByteArrayBuffer;

import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

public class ActivityImageViewer extends Activity {
    File imageFile = null;

    // Matrices for pinch zoom and pan
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();
    Matrix savedMatrixZoom = new Matrix();

    // State of motion event
    static final int NONE = 0;
    static final int PAN = 1;
    static final int PINCH_ZOOM = 2;
    int mode = NONE;

    // The first pointer down
    PointF start = new PointF();

    // The center of the image (Failed to track it when the image has been moved)
    PointF centerOfImage = new PointF();

    // oldest is the Cartesian distance between first two pointers when the second pointer is down
    float oldDist = 1f;

    // MIN_SCALE/MAX_SCALE is the min/max scale factor
    private final float MIN_SCALE = 0.5f;
    private final float MAX_SCALE = 3.0f;

    // TOUCH_SENSITIVE is the minimum Cartesian distance between the first two pointers that triggers the pinch zoom
    private final float TOUCH_SENSITIVE = 10.0f;
    private final float SPACING_LEFT_AND_RIGHT = 30.0f;
    private final float SPACING_TOP_AND_BOTTOM = 30.0f;

    // The ImageView widget
    private ImageView image_viewer;

    // The progress bar shows what current progress is before the image downloading is completed
    private ProgressBar progressbar;
    private LinearLayout progressbar_wrapper;

    // An async task that downloads the image from a given URL
    private DownloadFilesTask downloadFilesTask;

    private class DownloadFilesTask extends AsyncTask<String, Integer, Bitmap> {
        protected Bitmap doInBackground(String... urls) {
            InputStream input = null;
            OutputStream output = null;
            try {
                URL url = new URL(urls[0]);
                URLConnection connection = url.openConnection();
                connection.connect();
                int lenghtOfFile = connection.getContentLength();
                // download the file
                InputStream is = connection.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is, 8190);

                ByteArrayBuffer baf = new ByteArrayBuffer(50);
                int current = 0;
                while ((current = bis.read()) != -1) {
                    baf.append((byte)current);
                }
                byte[] imageData = baf.toByteArray();
                Bitmap bmp = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);

                //final int percent = (int) (total * 100 / lenghtOfFile);
                //publishProgress(percent);
                //lenghtOfFile

                return bmp;
            } catch (Exception e) {

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

                }
                try {
                    if (input != null)
                        input.close();
                    input = null;
                } catch (IOException e) {

                }

            }
            return null;
        } // protected Bitmap doInBackground(String... urls) {}

        protected void onProgressUpdate(Integer... progress) {
            progressbar.setProgress(progress[0]);
        }

        protected void onPostExecute(Bitmap bmp) {
            if (bmp != null) {
                final AlphaAnimation animationAfter = new AlphaAnimation(0.0f, 1.0f);
                animationAfter.setDuration(300);
                animationAfter.setFillEnabled(true);
                animationAfter.setFillAfter(true);
                image_viewer.setAnimation(animationAfter);
                image_viewer.setImageBitmap(bmp);
                ViewTreeObserver viewTreeObserver = image_viewer.getViewTreeObserver();
                viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        Drawable drawable = image_viewer.getDrawable();
                        int dx = (image_viewer.getWidth() - drawable.getIntrinsicWidth()) / 2;
                        int dy = (image_viewer.getHeight() - drawable.getIntrinsicHeight()) / 2;
                        matrix.postTranslate(dx, dy);
                        image_viewer.setImageMatrix(matrix);
                    }
                });
                progressbar_wrapper.setVisibility(View.GONE);
                image_viewer.setVisibility(View.VISIBLE);
            } else {
                android.os.Handler handler = new android.os.Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        finish();
                    }
                }, 2000);
            }
        } // End of protected void onPostExecute(Bitmap bmp) {}
    } // End of private class DownloadFilesTask extends AsyncTask<String, Integer, Bitmap> {}

    // These are activity life cycle handling
    // onCreate
    @Override
    public void onCreate(Bundle savedInstanceState) {
        //setTheme(R.style.HubTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_viewer);
        progressbar_wrapper = (LinearLayout) findViewById(R.id.progressbar_wrapper);
        image_viewer = (ImageView) findViewById(R.id.image_viewer);
        progressbar = (ProgressBar) findViewById(R.id.progressbar);
        image_viewer.setOnTouchListener(new MyOnTouchListener());
        final String uriForImage = getIntent().getStringExtra("url");
        downloadFilesTask = new DownloadFilesTask();
        downloadFilesTask.execute(uriForImage);
    }

    // onStart
    @Override
    protected void onStart() {
        super.onStart();
    }

    // onResume
    @Override
    protected void onResume() {
        super.onResume();
    }

    // onPause
    @Override
    protected void onPause() {
        super.onPause();
    }

    // onStop
    @Override
    protected void onStop() {
        super.onStop();
    }

    // onRestart
    @Override
    protected void onRestart() {
        super.onRestart();
    }

    // onDestroy
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (imageFile != null) {
            try {
                Drawable drawable = image_viewer.getDrawable();
                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                Bitmap bitmap = bitmapDrawable.getBitmap();
                bitmap.recycle();

                drawable = null;
                bitmapDrawable = null;
                bitmap = null;

            } catch (NullPointerException e) {
            }
        }
    }

    // onKeyDown
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            this.onBackPressed();
        }
        return true;
    }

    // onBackPressed
    public void onBackPressed() {
        finish();
    }

    // onConfigurationChanged
    @Override
    public void onConfigurationChanged(Configuration newConfig) {

        super.onConfigurationChanged(newConfig);
        if (newConfig.equals(Configuration.ORIENTATION_LANDSCAPE)) {

        } else if (newConfig.equals(Configuration.ORIENTATION_PORTRAIT)) {

        }
    }

    // onLowMemory
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        finish();
    }

    // Get the Cartesian distance between the first two pointers
    private float spacing(MotionEvent event) {
        float x = 0;
        float y = 0;
        try {
            Method getX = MotionEvent.class.getMethod("getX", Integer.TYPE);
            Method getY = MotionEvent.class.getMethod("getX", Integer.TYPE);

            // x = event.getX(0) - event.getX(1);
            // y = event.getY(0) - event.getY(1);
            float x1 = (Float) getX.invoke(event, 0);
            float x2 = (Float) getX.invoke(event, 1);
            x = x1 - x2;
            float y1 = (Float) getY.invoke(event, 0);
            float y2 = (Float) getY.invoke(event, 1);
            y = y1 - y2;

        } catch (SecurityException e) {
        } catch (NoSuchMethodException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        }
        return FloatMath.sqrt(x * x + y * y);
    }

    // Some flags set manually for convenience
    private final int MotionEvent_ACTION_MASK         = 255; // that is 0xFF or 11111111
    private final int MotionEvent_ACTION_POINTER_DOWN = 5;   // that is 101
    private final int MotionEvent_ACTION_POINTER_UP   = 6;   // that is 110

    private class MyOnTouchListener implements OnTouchListener {

        // onTouch
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            ImageView view = (ImageView) v;
            Drawable drawable = view.getDrawable();
            if (drawable == null)
                return true;
            switch (event.getAction() & MotionEvent_ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                savedMatrix.set(matrix);
                start.set(event.getX(), event.getY());
                mode = PAN;
                break;
            case MotionEvent_ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > TOUCH_SENSITIVE) {
                    savedMatrix.set(matrix);
                    mode = PINCH_ZOOM;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent_ACTION_POINTER_UP:
                mode = NONE;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == PAN) {
                    // /////////////////////////////////////////
                    matrix.set(savedMatrix);
                    float[] matrixValues = new float[9];
                    Rect viewRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
                    matrix.getValues(matrixValues);
                    float currentY = matrixValues[Matrix.MTRANS_Y];
                    float currentX = matrixValues[Matrix.MTRANS_X];
                    float currentScale = matrixValues[Matrix.MSCALE_X];
                    float currentHeight = drawable.getIntrinsicHeight() * currentScale;
                    float currentWidth = drawable.getIntrinsicWidth() * currentScale;
                    float dx = event.getX() - start.x;
                    float dy = event.getY() - start.y;
                    float newX = currentX + dx;
                    float newY = currentY + dy;

                    RectF drawingRect = new RectF(newX, newY, newX + currentWidth, newY + currentHeight);
                    float diffUp = Math.min(viewRect.bottom - drawingRect.bottom, viewRect.top - drawingRect.top) - SPACING_TOP_AND_BOTTOM;
                    float diffDown = Math.max(viewRect.bottom - drawingRect.bottom, viewRect.top - drawingRect.top) + SPACING_TOP_AND_BOTTOM;
                    float diffLeft = Math.min(viewRect.left - drawingRect.left, viewRect.right - drawingRect.right) - SPACING_LEFT_AND_RIGHT;
                    float diffRight = Math.max(viewRect.left - drawingRect.left, viewRect.right - drawingRect.right) + SPACING_LEFT_AND_RIGHT;
                    if (diffUp > 0) {
                        dy += diffUp;
                    }
                    if (diffDown < 0) {
                        dy += diffDown;
                    }
                    if (diffLeft > 0) {
                        dx += diffLeft;
                    }
                    if (diffRight < 0) {
                        dx += diffRight;
                    }
                    matrix.postTranslate(dx, dy);
                } else if (mode == PINCH_ZOOM) {
                    float newDist = spacing(event);
                    if (newDist > TOUCH_SENSITIVE) {
                        matrix.set(savedMatrix);
                        float scale = newDist / oldDist;

                        // Get the center of the image. (Failed to get it when image has been moved)
                        Rect viewRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
                        centerOfImage.x = viewRect.centerX();
                        centerOfImage.y = viewRect.centerY();

                        float[] f = new float[9];
                        Matrix tmp = new Matrix(matrix);
                        tmp.postScale(scale, scale, centerOfImage.x, centerOfImage.y);
                        tmp.getValues(f);
                        float scaleX = f[Matrix.MSCALE_X];
                        if (scaleX < MIN_SCALE || scaleX > MAX_SCALE) {
                            matrix.set(savedMatrixZoom);
                        } else {
                            matrix.postScale(scale, scale, centerOfImage.x, centerOfImage.y);
                            savedMatrixZoom.set(matrix);
                        }


                    }
                }
                break;
            }
            view.setImageMatrix(matrix);
            return true;
        } // End of public boolean onTouch(View v, MotionEvent event) {}

    } // End of private class MyOnTouchListener implements OnTouchListener {}

} // End of public class ActivityImageViewer extends Activity {}

解决方案

You can use the Scale Gesture Detector for pinch to zoom. Instead of creating pinch to zoom from scratch you can do something like following,

public class MyCustomView extends View {

private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;

public MyCustomView(Context mContext){
    ...
    // View code goes here
    ...
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);
    return true;
}

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.save();
    canvas.scale(mScaleFactor, mScaleFactor);
    ...
    // onDraw() code goes here
    ...
    canvas.restore();
}

private class ScaleListener 
        extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();

        // Don't let the object get too small or too large.
        mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

        invalidate();
        return true;
    }
}
}

Note : Your translation will reside in onDraw method to scale an image.

这篇关于如何捏缩放工作,在Android中平移图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆