Recipe Using Multitouch

A multitouch event is when more than one pointer (such as a finger) touches the screen at the same time. This is identified by using a touch listener OnTouchListener, which receives multiple types of motion events:

■ action_down—A press gesture has started with a primary pointer (finger).

■ action_pointer_down—A secondary pointer (finger) has gone down.

■ action_move—A change in press location has changed during a press gesture.

■ action_pointer_up—A secondary pointer was released.

■ action_up—A primary pointer was released, and the press gesture has completed.

This recipe displays an image to the screen and allows the multitouch events to zoom the image in or out. It also checks for single pointer events to drag the picture around the screen.This is shown in the activity in Listing 5.13. First, the activity implements the OnTouchListener that is set in the onCreate() method.When a touch event occurs, the onTouch() method checks the motion event and acts as follows:

■ If a first pointer touches the screen, the touch state is declared to be a drag motion, and the touch-down position and Matrix are saved.

■ If a second pointer touches the screen when the first pointer is still down, the distance between the two touch-down positions is calculated. As long as it is larger than some threshold (50 pixels here), the touch state is declared to be a zoom motion, and the distance and mid-point of the two events, as well as the Matrix, are saved.

■ If a move occurs, the figure is translated for a single touch-down event and scaled for a multitouch event.

■ If a pointer goes up, the touch state is declared to be no motion.

Listing 5.13 src/com/cookbook/multitouch/MultiTouch.java package com.cookbook.multitouch;

import android.app.Activity; import android.graphics.Matrix; import android.os.Bundle; import android.util.FloatMath;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnTouchListener;

import android.widget.ImageView;

public class MultiTouch extends Activity implements OnTouchListener { // Matrix instances to move and zoom image Matrix matrix = new Matrix(); Matrix eventMatrix = new Matrix();

// possible touch states final static int NONE = 0; final static int DRAG = 1; final static int ZOOM = 2; int touchState = NONE;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

ImageView view = (ImageView) findViewById(R.id.imageView); view.setOnTouchListener(this);

final static float MIN_DIST = 50; static float eventDistance = 0; static float centerX =0, centerY = 0; @Override public boolean onTouch(View v, MotionEvent event) { ImageView view = (ImageView) v;

switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN:

//primary touch event starts: remember touch down location touchState = DRAG;

centerX = event.getX(0);

centerY = event.getY(0);

eventMatrix.set(matrix);

break;

case MotionEvent.ACTION_POINTER_DOWN:

//secondary touch event starts: remember distance and center eventDistance = calcDistance(event); calcMidpoint(centerX, centerY, event); if (eventDistance > MIN_DIST) { eventMatrix.set(matrix);

touchState = ZOOM;

break;

case MotionEvent.ACTION_MOVE: if (touchState == DRAG) {

//single finger drag, translate accordingly matrix.set(eventMatrix);

matrix.setTranslate(event.getX(0) - centerX, event.getY(O) - centerY);

//multi-finger zoom, scale accordingly around center float dist = calcDistance(event);

matrix.set(eventMatrix);

float scale = dist / eventDistance;

matrix.postScale(scale, scale, centerX, centerY);

// Perform the transformation view.setlmageMatrix(matrix);

break;

case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: touchState = NONE; break;

return true;

private float calcDistance(MotionEvent event) { float x = event.getX(O) - event.getX(l); float y = event.getY(O) - event.getY(l); return FloatMath.sqrt(x * x + y * y);

private void calcMidpoint(float centerX, float centerY,

MotionEvent event) { centerX = (event.getX(O) + event.getX(1))/2; centerY = (event.getY(O) + event.getY(1))/2;

The layout that specifies a picture to zoom is shown in Listing 5.14. For this recipe, it is taken as the icon.png, which is automatically created in Eclipse; however, it can be replaced by any picture.

Listing 5.14 res/layout/main.xml

<?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/icon" android:scaleType="matrix" > </ImageView>

</FrameLayout>

Character Building Thought Power

Character Building Thought Power

Character-Building Thought Power by Ralph Waldo Trine. Ralph draws a distinct line between bad and good habits. In this book, every effort is made by the writer to explain what comprises good habits and why every one needs it early in life. It draws the conclusion that habits nurtured in early life concretize into impulses in future for the good or bad of the subject.

Get My Free Ebook


Post a comment