Fork us on GitHub

In A Pinch

Codename One has supported multi-touch and effectively pinch ...

In A Pinch

Picture
Codename One has supported multi-touch and effectively pinch to zoom events from the very first release. However, it wasn't intuitive to write code that would handle pinch to zoom. We just committed new pinch callback events to component which effectively allows you to zoom in/out with gestures.

Effectively if you are interested in handling pinch you would just override: protected boolean pinch(float scale) and return true after handling the pinch operation. We did this to support our new ImageViewer class (where you can see a working sample of pinch), the image viewer allows you to inspect, zoom and pan into an image. It also allows swiping between images if you have a set of images (using an image list model).

Now to simulate the pinching we needed a simpler solution than just building for the device, which is why we added right click dragging. Now when you drag using the right mouse button (or by pressing 2 fingers on a Mac laptop and dragging together) you will get a pinch effect. We do this by hardcoding the second finger at position 0,0. So effectively if you drag towards the top left corner you will be zooming out (fingers closer together) and by dragging away you will be zooming in.

Here is a simple example of using the ImageViewer:

Notice that we use a list to allow swiping between images (unnecessary if you have only one image), we also create a placeholder image to show while the image is still loading. Notice that encoded images aren't always fully loaded and so when you swipe if the images are really large you might see delays!

This leads me to one of the more important aspects here: image locking.

Image Locking
Once of the big performance improvements we got in swiping was through image locking, unfortunately this is so unclear in our current docs that when Nokia forked LWUIT they actually removed the usage of EncodedImage instead of fixing a minor locking bug.
To understand locking we first need to understand EncodedImage. EncodedImage stores the data of the image in RAM (png or JPEG data) which is normally pretty small, unlike the full decoded image which can take up to width X height X 4. When a user tries to draw an encoded image we check a WeakReference cache and if the image is cached then we show it otherwise w e load the image, cache it then draw.

Naturally loading the image is more expensive so we want the images that are showing to stay in cache (otherwise GC will thrash a lot). That's where lock() kicks in, we automatically invoke image loading when necessary but when lock() is active we keep a hard reference to the actual native image so it won't get GC'd. This REALLY improves performance!
Internally we invoke this automatically for bg images, icons etc. which results in a huge performance boost. However, if you use a complex renderer or custom drawing UI you should lock() your images where possible!

Generics Update
You might have noticed from the code above that the list model is now generified, the same is also true now for the list renderer and list. We are working on modernizing as much of our code as we can while maintaining backwards compatibility.

Notice: This post was automatically converted using a script from an older blogging system. Some elements might not have come out as intended.... If that is the case please let us know via the comments section below.

Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.