3
votes

How would I implement two-finger zoom for Android in Titanium?

I did it for iPhone in Titanium, as there is a pinch event and zoomScal properties are available of scroolView in Titanium for iPhone :) but these are not available for Android. :(

This solution for the same problem for iPhone is available in the Appcelerator archives.

2
according to their docs, the pinch event is only available for iOS docs.appcelerator.com/titanium/latest/#!/api/… (Expand the pinch event arrow at the bottom of the page) - Ronnie

2 Answers

1
votes

It's an old post, but this module titanium-android-pinchview will maybe be useful to someone

0
votes

You have to wrap the touchstart, touchmove, and touchend events to emulate this behavior in Android. Also, since many Android devices don't support multi touch, you need to account for this.

First you have to setup your scrollView correctly, for example, since Android does not have a zoomScale property you need to emulate this with a matrix. Like this:

var scrollView = Ti.UI.createScrollView({... Init here...});
var contentOfScrollView = Ti.UI.createView({
    width : //..bigger than scrollview,
    height : //..bigger than scrollview,
    transform : Ti.UI.create2DMatrix()
});

For a start, I would try to keep track of all the active touch objects in a view. Then if you have two touches, get the distance between them and save this as the original zoom scale, from this you can compare new distances as the user moves. This approach will break down if there are more than two touches and is not very robust since it cant account for any edge cases but it will work sometimes :-)

The main problem is Titanium doesn't pass the ID of the touch, or allow you to get all the touches so it makes it very difficult to track which touch is which when your removing, or adding, touches.

Heres a simple code sample, it suffers from what I outlined above, ( I don't try to track which touch is which) and you will have to fiddle with it to make it more robust, but I'm sure you can take it from here:

var touches = [];
var zoomScale = 1.0;
var lastDistance = 0.0;
var wratio = contentOfScrollView.width / scrollView.width;
var hratio = contentOfScrollView.height / scrollView.height;

Now lets add our listeners.

// Listeners
scrollview.addEventListener('touchstart' , function(e) {
    touches.push({x : e.x, y : e.y});
});
scrollview.addEventListener('touchmove' , function(e) {
    if(touches.length == 2 && distance > 0) {
        // Calculate distance between touches
        var dx = touches[1].x - touches[0].x;
        var dy = touches[1].y - touches[0].y;
        var distance = Math.sqrt(dx*dx+dy*dy);

        // Heres where you would do your scaling based on whatever your
        // use case is.  You could try something like this, tune it yourself though 
        scrollView.zoomScale = lastDistance - distance;

        // Now set the matrix of the content!
        contentOfScrollView.transform.scale(zoomScale*wratio, zoomScale*hratio);
        // Save for later
        lastDistance = distance;
    } else {
        // Reset everything
        lastDistance = 0.0;
    }
});
scrollview.addEventListener('touchend' , function(e) {
    touches.pop();
});
scrollview.addEventListener('touchcancel' , function(e) {
    touches.pop();
});

This is NOT a complete, robust, or bug tested implementation, but I cant write all your code for you, experiment with this as a starting point. Good luck!