Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android imageView: setting drag and pinch zoom parameters

I am currently developing for Android (my first app) an application which lets users see the subway map and be able to pinch zoom and drag around.

I am currently modifying the code found in Hello Android, 3rd Edition and got the pinch zooming and dragging to work. I'm using Matrix as my layout scale.

However I now have 3 problems:

  1. I tried many things to limit the drag parameters but I can't seem to stop it being dragged off the parent view (and can actually disappear from view). I've tried setting layout parameters in the XML file and it just doesn't work.

  2. I can pinch zoom fine but I have trouble, again, limiting the amount of zoom. I'm trying to play around with setting a max_zoom and min_zoom to limit the scaling value (i will post my code after)

  3. I also have trouble trying to map a coordinate on my image so that people can click on certain parts (the whole point of this is to let users click a station on the map and view information about it)

I have a feeling i'm having trouble because I'm using the matrix scale.

Here is my current code:

Touch.java

package org.example.touch; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.PointF; import android.os.Bundle; import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.GridView; import android.widget.ImageView;  public class Touch extends Activity implements OnTouchListener { private static final String TAG = "Touch";  private static final float MIN_ZOOM = 1.0f; private static final float MAX_ZOOM = 5.0f;  // 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;  @Override public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);    ImageView view = (ImageView) findViewById(R.id.imageView);    //view.setLayoutParams(new GridView.LayoutParams(85, 85));    view.setScaleType(ImageView.ScaleType.FIT_CENTER);    view.setOnTouchListener(this);    }  public boolean onTouch(View v, MotionEvent event) {    ImageView view = (ImageView) v;    view.setScaleType(ImageView.ScaleType.MATRIX);    float scale;     // Dump touch event to log    dumpEvent(event);     // Handle touch events here...    switch (event.getAction() & MotionEvent.ACTION_MASK) {     case MotionEvent.ACTION_DOWN: //first finger down only       savedMatrix.set(matrix);       start.set(event.getX(), event.getY());       Log.d(TAG, "mode=DRAG" );       mode = DRAG;       break;    case MotionEvent.ACTION_UP: //first finger lifted    case MotionEvent.ACTION_POINTER_UP: //second finger lifted       mode = NONE;       Log.d(TAG, "mode=NONE" );       break;    case MotionEvent.ACTION_POINTER_DOWN: //second finger down       oldDist = spacing(event);       Log.d(TAG, "oldDist=" + oldDist);       if (oldDist > 5f) {          savedMatrix.set(matrix);          midPoint(mid, event);          mode = ZOOM;          Log.d(TAG, "mode=ZOOM" );       }       break;     case MotionEvent.ACTION_MOVE:        if (mode == DRAG) { //movement of first finger          matrix.set(savedMatrix);          if (view.getLeft() >= -392){             matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);          }       }       else if (mode == ZOOM) { //pinch zooming          float newDist = spacing(event);          Log.d(TAG, "newDist=" + newDist);          if (newDist > 5f) {             matrix.set(savedMatrix);             scale = newDist / oldDist; **//thinking i need to play around with this value to limit it**             matrix.postScale(scale, scale, mid.x, mid.y);          }       }       break;    }     // Perform the transformation    view.setImageMatrix(matrix);     return true; // indicate event was handled }  private float spacing(MotionEvent event) {    float x = event.getX(0) - event.getX(1);    float y = event.getY(0) - event.getY(1);    return FloatMath.sqrt(x * x + y * y); }  private void midPoint(PointF point, MotionEvent event) {    float x = event.getX(0) + event.getX(1);    float y = event.getY(0) + event.getY(1);    point.set(x / 2, y / 2); }  /** Show an event in the LogCat view, for debugging */ private void dumpEvent(MotionEvent event) {    String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,       "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };    StringBuilder sb = new StringBuilder();    int action = event.getAction();    int actionCode = action & MotionEvent.ACTION_MASK;    sb.append("event ACTION_" ).append(names[actionCode]);    if (actionCode == MotionEvent.ACTION_POINTER_DOWN          || actionCode == MotionEvent.ACTION_POINTER_UP) {       sb.append("(pid " ).append(       action >> MotionEvent.ACTION_POINTER_ID_SHIFT);       sb.append(")" );    }    sb.append("[" );    for (int i = 0; i < event.getPointerCount(); i++) {       sb.append("#" ).append(i);       sb.append("(pid " ).append(event.getPointerId(i));       sb.append(")=" ).append((int) event.getX(i));       sb.append("," ).append((int) event.getY(i));       if (i + 1 < event.getPointerCount())          sb.append(";" );    }    sb.append("]" );    Log.d(TAG, sb.toString()); } } 

main.xml (rather simple nothing really complicated):

<?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" > <ImageView android:id="@+id/imageView"      android:layout_width="fill_parent"      android:layout_height="fill_parent"      android:src="@drawable/map"      android:scaleType="matrix" > </ImageView> </FrameLayout> 

AndroidManifest.xml (only added the theme so there is no title bar and is full screen)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"   package="org.example.touch"   android:versionCode="7"   android:versionName="1.0" > <application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >   <activity android:name=".Touch"         android:label="@string/app_name" >      <intent-filter>         <action android:name="android.intent.action.MAIN" />         <category android:name="android.intent.category.LAUNCHER" />      </intent-filter>   </activity> </application> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="7" /> </manifest> 
like image 787
w1ck3d64 Avatar asked Nov 19 '10 17:11

w1ck3d64


People also ask

How do you pinch zoom on Android?

Tap anywhere on the screen, except the keyboard or navigation bar. Drag 2 fingers to move around the screen. Pinch with 2 fingers to adjust zoom. To stop magnification, use your magnification shortcut again.

How do I use TouchImageView?

TouchImageViews placed in a ViewPager like the Gallery app. Mirror two TouchImageViews using onTouchImageViewListener and setZoom() . Click on TouchImageView to cycle through images. Note that the zoom state is maintained though the images are switched.


1 Answers

I just created this:

https://github.com/jasonpolites/gesture-imageview

Might be useful for someone...

like image 175
Jason Polites Avatar answered Oct 11 '22 19:10

Jason Polites