I have done some work to help me understand multitouch features in Android. I built a simple demo with examples of pinch zooming and panning. Most of the examples involve using drawing operations on the canvas of a view.
About two years ago, I started some work on moving images in Android. I started with the “Making Sense of Multitouch” blog article and ended up doing some simple things with moving images and then drag-drop based on the Android Launcher (see references for links). It’s interesting to me that I have gone back to that same article for a different purpose. I am working on apps where the basic zoom and pan operations are needed.
Overview of the Examples
1 Basic Multitouch
The first example does the basics of multitouch as explained in the Multitouch article. An image displays on the screen. You can touch the image and move it around. You can also use two fingers to do pinch-zoom and zoom out.
I did this as the first step because I wanted to be sure that I understood the Multitouch article and had a working example.
To understand how this example works, go through the Mulitouch article and then get the source code for my examples (see below). My adaptation of the Multitouch article is in class PanZoomView.
/** * This view supports both zooming and panning. * What gets shown in the view depends on the onDraw method provided by subclasses. * The default onDraw method defined displays R.drawable.zoom_view_sample. */ public class PanZoomView extends View
The key things to understand in the article and the code are these:
- How the canvas moves around. See the call to “canvas.translate(x, y)” in method onDraw.
- How the canvas is scaled during a pinch-zoom gesture. See the call to :canvas.scale(mScaleFactor, mScaleFactor)” in method onDraw.
- How onTouchEvent handles touch and multitouch events. It sets variables so the calls to translate and scale work.
In the second section, there are two examples that do essentially the same thing for handling panning and zooming as the first one. The difference is that instead of an image being moved around and zoomed, it is a circle and a rectangle. Those are drawn on the canvas in the onDraw method of the view.
I did these as the next step in understanding how to build my views for my own app. Zooming an image was step one. Zooming a custom canvas was step 2. To help me understand pinch zoom and the point around which zooming occurs, I display a small circle at the point of focus for the scaling of the view. Place two fingers on the screen and look for that dot, halfway between your two fingers.
The Circles example supports both panning and zooming. The Rectangles example supports only zooming. I found myself getting a bit confused while trying to understand for translation on the canvas and scaling so both examples were useful to me.
3. Pan Zoom Listener
PanZoomListener is an interesting example. It comes from Java Pan / Zoom listener for Android (reference 2 below). Rather than doing a custom view every time you want to have panning and zooming, which is what all the other examples do, you simply set up a listener on a view you already have working.
FrameLayout f = new FrameLayout(context); FrameLayout.LayoutParams fp = new FrameLayout.LayoutParams (...); imageView imageView = new ImageView (this); view.addView (imageView, fp); view.setOnTouchListener(new PanAndZoomListener(view, imageView, Anchor.TOPLEFT));
That may look like a lot to do, but it’s not nearly as complicated as what you do when you build a view of your own with custom handling of panning and zooming.
It works pretty well, but there are a few things that you’d need to adjust because not all of the operations are completely smooth. I definitely like the idea. I adapted the code and built my own example.
What you see in the example I did is an image. As soon as you touch it, it resizes and centers itself. After that, you can use pinch zoom on it. The focus of the zoom is the point between your two fingers.
4. Image Squares
This example was another step toward getting the right panning and zooming effects in the app that I am working on. In the app, I want to be able to draw a grid of squares on a canvas. In the example, I don’t draw the entire grid but simply some squares along a diagonal from top to bottom. This example supports zooming but not moving the canvas around as you touch the screen with one finger. The focus point of the zoom is shown with a small circle again.
You cannot move the canvas around with a simple touch. However, if you start a pinch-zoom gesture and then move both fingers around the image does shift. I never figured out exactly what was causing that. So watch out for that if build on this example.
5. Fixed Point Zoom
Since I was having a few problems with the canvas jumping around a bit, I decided to try using a fixed point for zooming. The last example zooms in and out around the center dot shown on the screen.
The code structure of this example is a bit different than the earlier ones. All of the views in these examples are subclasses of a PanZoomView class. The view used in this example is LargeGridView. It defines its own drawOnCanvas method like all the rest do, but it also defines its own onDraw method. By the time I got here, I found that the flexible framework I built in PanZoomView to explore the different aspects of panning and zooming wasn’t quite right for fixed point zooming.
Fixed point zoom is what I have ended up using in a couple of apps.
(UPDATE – Feb 16, 2016. I have done even more with fixed point zooming. The latest article on this topic is for a zoomable game board. See Android Example of a Zoomable Game Board.)
I have done this article a bit differently than some of my earlier blog tutorials. I have not included as much code and explanations. I assume that most readers will dig into the code as they need to. Download the source code using the links in the next section.
What I wanted to do here is show the progression of my thinking and understanding as I worked on an interesting problem. If you are new to Android, I suggest following a similar progression. Start simple and add more complex features as your understanding increases.
You can download the source code for this demo from the wglxy.com website. Click here: download zip file from wglxy.com. The zip is attached at the bottom of that page. After you import the project into Eclipse, it’s a good idea to use the Project – Clean menu item to rebuild the project.
This demo app was compiled with Android 4.2 (API 17). It works in all API levels from API 10 on up.
Making Sense of Multitouch – I recommend this to anyone looking for a good starting point for touch handling in Android.
Java / Pan Zoom Listener for Android – Article that describes the PanZoomListener. Definitely, take a look at this one.
Moving Views in Android – Part 1 – a simple example that moves an image when you click a button
Moving Views in Android – Part 2, Drag and Drop – an example based on the Launcher code of Android 2.2.
Android Example of a Zoomable Game Board – my latest article on the topic of panning and zooming.