49

My layout contains buttons, textviews, etc. Is it possible to implement pinch zoom in my layout?

Swati Garg
  • 995
  • 1
  • 10
  • 21
Bytecode
  • 6,551
  • 16
  • 54
  • 101

7 Answers7

43

Updated Answer

Code can be found here : official-doc

Answer Outdated

Check out the following links which may help you

Best examples are provided in the below links, which you can refactor to meet your requirements.

  1. Implementing the pinch zoom gesture

  2. Android-pinch

  3. GestureDetector.SimpleOnGestureListener

Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
Vinayak Bevinakatti
  • 40,205
  • 25
  • 108
  • 139
  • 23
    This answer will be worthless, once the links go down. At least quote the relevant parts. – Lukas Knuth Dec 10 '15 at 08:29
  • 4
    FYI, this answer is out-of-date. [ScaleGestureDetector](https://developer.android.com/reference/android/view/ScaleGestureDetector.html) is Android's answer for pinch-zoom, since API 8. See [Emanuel's answer](http://stackoverflow.com/a/11722858/199364). – ToolmakerSteve Oct 20 '16 at 17:08
38

For android 2.2+ (api level8), you can use ScaleGestureDetector.

you need a member:

private ScaleGestureDetector mScaleDetector;

in your constructor (or onCreate()) you add:

mScaleDetector = new ScaleGestureDetector(context, new OnScaleGestureListener() {
    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
    }
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        Log.d(LOG_KEY, "zoom ongoing, scale: " + detector.getScaleFactor());
        return false;
    }
});

You override onTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleDetector.onTouchEvent(event);
    return true;
}

If you draw your View by hand, in the onScale() you probably do store the scale factor in a member, then call invalidate() and use the scale factor when drawing in your onDraw(). Otherwise you can directly modify font sizes or things like that in the onScale().

Emmanuel Touzery
  • 9,008
  • 3
  • 65
  • 81
  • 1
    Additional information in [Android docs - Dragging and Scaling](https://developer.android.com/training/gestures/scale.html) Especially note example code showing how to combine panning (scrolling) with scaling (pinch zoom). – ToolmakerSteve Oct 20 '16 at 17:12
16

I implemented a pinch zoom for my TextView, using this tutorial. The resulting code is this:

private GestureDetector gestureDetector;
private View.OnTouchListener gestureListener;

and in onCreate():

    // Zoom handlers
    gestureDetector = new GestureDetector(new MyGestureDetector());
    gestureListener = new View.OnTouchListener() {

        // We can be in one of these 2 states
        static final int NONE = 0;
        static final int ZOOM = 1;
        int mode = NONE;

        static final int MIN_FONT_SIZE = 10;
        static final int MAX_FONT_SIZE = 50;

        float oldDist = 1f;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            TextView textView = (TextView) findViewById(R.id.text);

            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    Log.d(TAG, "oldDist=" + oldDist);
                    if (oldDist > 10f) {
                       mode = ZOOM;
                       Log.d(TAG, "mode=ZOOM" );
                    }
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == ZOOM) {
                        float newDist = spacing(event);
                        // If you want to tweak font scaling, this is the place to go.
                        if (newDist > 10f) {
                            float scale = newDist / oldDist;

                            if (scale > 1) {
                                scale = 1.1f;
                            } else if (scale < 1) {
                                scale = 0.95f;
                            }

                            float currentSize = textView.getTextSize() * scale;
                            if ((currentSize < MAX_FONT_SIZE && currentSize > MIN_FONT_SIZE)
                                    ||(currentSize >= MAX_FONT_SIZE && scale < 1)
                                    || (currentSize <= MIN_FONT_SIZE && scale > 1)) {
                                textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, currentSize);
                            }
                        }
                    }
                    break;
                }
            return false;
        }

Magic constants 1.1 and 0.95 were chosen empirically (using scale variable for this purpose made my TextView behave kind of weird).

Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
George
  • 8,368
  • 12
  • 65
  • 106
  • 5
    Can i know your `MyGestureDetector()` class – Praveenkumar Jan 28 '12 at 11:12
  • 1
    @Renanlf That was more than a year ago. Sorry, I don't even code for android anymore. Nor do I have those sources anywhere. – George Aug 28 '12 at 14:09
  • 2
    `MyGestureDetector()` is not relevant here; because of the declaration `GestureDetector(GestureDetector.OnGestureListener listener)` we conclude that it's a misnomer child of `GestureDetector.OnGestureListener`. And the events detected by that class are irrelevant for pinch zooming. – 18446744073709551615 Dec 12 '12 at 13:25
  • switch (event.getAction() & MotionEvent.ACTION_MASK), in this line of the code: ACTION_MASK turns 255 (ff) so what is the point of adding Motion.ACTION_MASK? Will switch (event.getAction()) be enough, if not why? Could you please explain it. – answer88 Mar 24 '14 at 06:34
  • @folone Could you help me in [this](http://stackoverflow.com/questions/23187772/how-to-pass-pinch-zoom-event-from-a-viewgroup-to-multiple-child-views) question. This question is similar to what I am facing – user3265443 Apr 20 '14 at 21:40
  • The code does not seeem to work. `MyGestureDetector` is not defined, and so are other things in the code, like `spacing`, `TAG`, ...) – Alex Dec 16 '16 at 10:33
5

There is also this project that does the job and worked perfectly for me: https://github.com/chrisbanes/PhotoView

BoD
  • 10,838
  • 6
  • 63
  • 59
4

In android Honeycomb(API Level 11), it is possible, We can use setScaleX and setScaleY with pivot point
I have explained it here

  1. Zooming a view completely
  2. Pinch Zoom to view completely
Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
Labeeb Panampullan
  • 34,521
  • 28
  • 94
  • 112
1

I have created a project for basic pinch-zoom that supports Android 2.1+

Available here

Jason Polites
  • 5,571
  • 3
  • 25
  • 24
0

I have an open source library that does this very well. It's a four gesture library that comes with an out-of-the-box pan zoom setting. You can find it here: https://bitbucket.org/warwick/hacergestov3 Or you can download the demo app here: https://play.google.com/store/apps/details?id=com.WarwickWestonWright.HacerGestoV3Demo This is a pure canvas library so it can be used in pretty any scenario. Hope this helps.

user2288580
  • 2,210
  • 23
  • 16