Enabling zoom on scroll view

2019-03-29 11:28发布

问题:

I have certain data in placed in my ScrollView. I want to enable it to zoom in/ zoom out. It contains simple ImageView and TextView.

Any suggestions will be helpful. Thank you.

Here is my code:

<ScrollView
    android:id="@+id/viewSoupMenu"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
     android:background="@drawable/soupback" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

<LinearLayout
          android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
          android:layout_marginTop="50dp">

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         android:layout_marginLeft="35dp"
         android:layout_marginTop="30dp"
        android:background="@android:color/transparent"
        android:src="@drawable/flowericon" />

    <ImageButton
        android:id="@+id/btnVegClearSoup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         android:layout_marginLeft="5dp"
         android:layout_marginTop="20dp"
        android:background="@android:color/transparent"
        android:src="@drawable/btnvegsoupclearclickedxml" />

     </LinearLayout>
</ScrollView>

回答1:

You can use the class mentioned below for enabling Pinch Zoom in your ImageView and you can create a duplicate class of this class which extends TextView instead of ImageView for enabling zooming in it.

public class PinchZoomImageView extends ImageView implements OnTouchListener{

    public PinchZoomImageView(Context context) {
        super(context);
        _init();
    }

    public PinchZoomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        _init();
    }

    public PinchZoomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        _init();
    }

    private void _init(){
        //setOnTouchListener(this);

        view = (ImageView) this;
        view.setOnTouchListener(this);

        metric = new DisplayMetrics();
        // Work around a Cupcake bug

        d_dpi=((0.52f/(metric.densityDpi))*240.0f)-0.52f;
        Log.d("ash","dpi= "+d_dpi);
        if(metric.densityDpi==160)
        d_dpi=0.34f;
        matrix.setTranslate(1f, 1f);
        matrix.setScale((0.52f/800.0f)*metric.widthPixels+d_dpi, (0.52f/480.0f)*metric.heightPixels+d_dpi);
        view.setImageMatrix(matrix);
        bMap =  BitmapFactory.decodeResource(getResources(), R.drawable.mfigure);
        btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(hasFocus){
            init();
        }
    }

    private void init() {
        maxZoom = (3.0f/480.0f)*metric.heightPixels+d_dpi;
        minZoom = (0.52f/800.0f)*metric.widthPixels+d_dpi;
        height = view.getDrawable().getIntrinsicHeight();
        width = view.getDrawable().getIntrinsicWidth();
        viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        ImageView view = (ImageView) v;

        // Handle touch events here...
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                savedMatrix.set(matrix);
                start.set(event.getX()/metric.widthPixels * 800, event.getY()/metric.heightPixels * 480);
                Log.d(TAG, "mode=DRAG");
                mode = DRAG;
                click = true;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                Log.d(TAG, "oldDist=" + oldDist);
                if (oldDist > 10f) {
                    savedMatrix.set(matrix);
                    midPoint(mid, event);
                    mode = ZOOM;
                    Log.d(TAG, "mode=ZOOM");
                }
                click = false;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                Log.d(TAG, "mode=NONE");
                if(click)
                    onClick(event.getX(), event.getY(),true);
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {

                    temp_x = ((start.x) - ((event.getX()/metric.widthPixels)*800));
                    temp_y = ((start.y) - ((event.getY()/metric.heightPixels) * 480));               
                    if(FloatMath.sqrt(temp_x * temp_x + temp_y * temp_y)< 10)
                      break;

                    matrix.set(savedMatrix);

                    // limit pan
                    matrix.getValues(matrixValues);
                    float currentY = matrixValues[Matrix.MTRANS_Y];
                    float currentX = matrixValues[Matrix.MTRANS_X];
                    float currentScale = matrixValues[Matrix.MSCALE_X];
                    float currentHeight = height * currentScale;
                    float currentWidth = width * currentScale;
                    float dx = (event.getX()/metric.widthPixels * 800) - start.x;
                    float dy = (event.getY()/metric.heightPixels * 480) - 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);
                    float diffDown = Math.max(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
                    float diffLeft = Math.min(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
                    float diffRight = Math.max(viewRect.left-drawingRect.left, viewRect.right-drawingRect.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);
                    //selection.set(selection.x + dx, selection.y + dy);
                    click = false;
                }
                else if (mode == ZOOM) {
                    float newDist = spacing(event);
                    Log.d(TAG, "newDist=" + newDist);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        float scale = newDist / oldDist;

                        matrix.getValues(matrixValues);
                        float currentScale = matrixValues[Matrix.MSCALE_X];

                        // limit zoom
                        if (scale * currentScale > maxZoom) {
                            scale = maxZoom / currentScale;
                        } else if (scale * currentScale < minZoom) {
                            scale = minZoom / currentScale;
                        }
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                }
                break;
        }
        float mv[] = new float[9];
        matrix.getValues(mv);

        Log.d("PV", "Click x " + mv[Matrix.MTRANS_X] + " y " + mv[Matrix.MTRANS_Y] + " cx " + event.getX() + " cy " + event.getY());

        view.setImageMatrix(matrix);
        view.invalidate();
        return true; // indicate event was handled
    }

     public void onClick(float x, float y,boolean state){
        Log.d("TAG","x="+x+" y "+y);
        float mv[] = new float[9];
        matrix.getValues(mv);

        if(btsize != null)
            btsize.recycle();

        btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map);

        if(btSel != null)
            btSel.recycle();

        btSel = BitmapFactory.decodeResource(getResources(), R.drawable.mfigure);

        Canvas canvas;
        try{
            canvas = new Canvas(btsize);
        }
        catch(Exception e){
            btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map).copy(Config.ARGB_8888,true);
            canvas = new Canvas(btsize);
        }

        x -= mv[Matrix.MTRANS_X];
        y -= mv[Matrix.MTRANS_Y];

        float wdt = btsize.getWidth() * mv[Matrix.MSCALE_X];
        float ht = btsize.getHeight() * mv[Matrix.MSCALE_Y];

        float tw = x/wdt;
        float th = y/ht;

        selPoint.set(tw, th);
        if(state)
             canvas.drawBitmap(btSel, (tw * btsize.getWidth()) - (btSel.getWidth()/2), (th * btsize.getHeight()) - (btSel.getHeight()/2), null);
        else
            canvas.drawBitmap(btSel, (x * btsize.getWidth()) - (btSel.getWidth()/2), (y * btsize.getHeight()) - (btSel.getHeight()/2), null);

        setImageBitmap(btsize);

    }

    /** Determine the space between the first two fingers */
    private float spacing(MotionEvent event) {
         float x = ((event.getX(0)/metric.widthPixels)*800) - ((event.getX(1)/metric.widthPixels)*800);
           float y = ((event.getY(0)/metric.heightPixels) * 480) - ((event.getY(1)/metric.heightPixels) * 480);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, MotionEvent event) {
         float x = ((event.getX(0)/metric.widthPixels) * 800) + ((event.getX(1)/metric.widthPixels)*800);
           float y = ((event.getY(0)/metric.heightPixels) * 480) + ((event.getY(1)/metric.heightPixels) * 480);
        point.set(x / 2, y / 2);
    }

    private static final String TAG = "Touch";
    // These matrices will be used to move and zoom image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = 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;
    int mode = NONE;

    // Remember some things for zooming
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    // Limit zoomable/pannable image
    private ImageView view;
    private float[] matrixValues = new float[9];
    private float maxZoom;
    private float minZoom;
    private float height;
    private float width;
    private RectF viewRect;
    private float temp_x,temp_y;
    private boolean click = false;
    public PointF selPoint = new PointF();
    Bitmap bMap;
    private float d_dpi;
    Paint paint = new Paint();
    Canvas canvas = new Canvas();
    private DisplayMetrics metric; 
    Bitmap bt = null;
    Bitmap btsize = null;
    Bitmap btSel = null;

} 


回答2:

Try using FrameLayout and have a look at this official document: Zooming a View.