Activity with multitouch for Buttons

New Version avaiable here:

http://www.passsy.de/multitouch-for-all-views/

I wrote an Activity which enables multitouch support. There you can touch two Views on the Activity at once.

Only the MOVE event doesn’t work very well. UP and DOWN works perfect.
Download Zip: here

package de.passsy.test;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;

public class MultitouchtestActivity extends MultiTouchActivity {
    /** Called when the activity is first created. */

    private Button btn1;
    private Button btn2;
    private Button btn3;
    private Button btn4;

    @Override
    public void onCreate(Bundle savedInstanceState) {
	this.requestWindowFeature(Window.FEATURE_NO_TITLE);
	this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
	this.getWindow().clearFlags(
		WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
	btn1 = (Button) findViewById(R.id.button1);
	btn1.setOnTouchListener(this);
	btn2 = (Button) findViewById(R.id.button2);
	btn2.setOnTouchListener(this);
	btn3 = (Button) findViewById(R.id.button3);
	btn3.setOnTouchListener(this);
	btn4 = (Button) findViewById(R.id.button4);
	btn4.setOnTouchListener(this);
    }
}
package de.passsy.test;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;

public class MultiTouchActivity extends Activity implements OnTouchListener {

    private View parent;

    public void onCreate(Bundle instance) {
	super.onCreate(instance);
	parent = findViewById(android.R.id.content).getRootView();
	parent.setOnTouchListener(this);
    }

    public boolean onTouch(View v, MotionEvent event) {

	for (int ptrIndex = 0; ptrIndex < event.getPointerCount(); ptrIndex++) {

	    // index of the pointer which starts this Event
	    int actionPointerIndex = event.getActionIndex();

	    // resolve the action as a basic type (up, down or move)
	    int actionResolved = event.getAction() & MotionEvent.ACTION_MASK;
	    if (actionResolved < 7 && actionResolved > 4) {
		actionResolved = actionResolved - 5;
	    }

	    if (actionResolved == MotionEvent.ACTION_MOVE) {

		dealEvent(ptrIndex, event, v, actionResolved);
		Log.v("tag", "move" + ptrIndex);

	    } else {
		dealEvent(actionPointerIndex, event, v, actionResolved);
	    }
	}
	return false;
    }

    private void dealEvent(int actionPointerIndex, MotionEvent event,
	    View eventView, int actionresolved) {
	int rawX, rawY;
	int location[] = { 0, 0 };
	eventView.getLocationOnScreen(location);
	// Log.v("tag", location + "");
	rawX = (int) event.getX(actionPointerIndex) + location[0];
	rawY = (int) event.getY(actionPointerIndex) + location[1];

	ArrayList views = getTouchedViews(rawX, rawY, actionresolved);

	// dumpEvent(event);
	for (View view : views) {
	    int x, y;
	    view.getLocationOnScreen(location);
	    x = rawX - location[0];
	    y = rawY - location[1];
	    // Log.v("tag", "touched" + view.toString());
	    /*
	     * view.onTouchEvent(MotionEvent.obtain(event.getDownTime(),
	     * event.getEventTime(), event.getActionMasked(), x, y,
	     * event.getMetaState()));
	     */
	    // MotionEvent me = MotionEvent.obtain(event);
	    MotionEvent me = MotionEvent.obtain(event.getDownTime(),
		    event.getEventTime(), actionresolved, x, y,
		    event.getPressure(actionPointerIndex),
		    event.getPressure(actionPointerIndex),
		    event.getMetaState(), event.getXPrecision(),
		    event.getYPrecision(), event.getDeviceId(),
		    event.getEdgeFlags());
	    me.setLocation(x, y);

	    // Log.v("tag", "oldeventid: " + event.getAction() + " #" +
	    // actionPointerIndex+ " id" + ptrId+ " resolved "+ actionResolved);
	    // Log.v("tag", "neweventid: " + me.getAction() + " #" +
	    // actionPointerIndex+ " id" + ptrId+ " resolved "+ actionResolved);

	    if (!me.equals(event)) {
		/*
		 * Log.v("tag", "actionindex: " + actionPointerIndex +
		 * " resolved: " + actionPointerIndex + " to " + view.toString()
		 * + " y:" + view.getTop() + "-" + (view.getTop() +
		 * view.getHeight()));
		 */
		// me.setAction(actionresolved);
		view.onTouchEvent(me);
	    }

	    if (actionresolved == MotionEvent.ACTION_MOVE) {
		Log.v("tag",
			"#" + actionPointerIndex + "Rawx:" + rawX + " rawy:"
				+ rawY + "x:" + x + " y:" + y + " "
				+ view.toString());
	    }
	}

    }

    private ArrayList getTouchedViews(int x, int y, int action) {

	int moveGap = 0;

	if (action == MotionEvent.ACTION_MOVE) {
	    moveGap = 0;
	}

	ArrayList touchedViews = new ArrayList();
	ArrayList possibleViews = new ArrayList();

	if (parent instanceof ViewGroup) {
	    possibleViews.add(parent);
	    for (int i = 0; i < possibleViews.size(); i++) { 		View view = possibleViews.get(i); 		int location[] = { 0, 0 }; 		view.getLocationOnScreen(location); 		if (((view.getHeight() + location[1] + moveGap >= y)
			& (view.getWidth() + location[0] + moveGap >= x)
			& (view.getLeft() - moveGap  getChildViews(View view) {
	ArrayList views = new ArrayList();
	if (view instanceof ViewGroup) {
	    ViewGroup v = ((ViewGroup) view);
	    if (v.getChildCount() > 0) {
		for (int i = 0; i < v.getChildCount(); i++) {
		    views.add(v.getChildAt(i));
		}

	    }
	}
	return views;
    }
}

Download Zip: here

, , , , , , , , , , , , , , , , , , ,

6 Comments

  • Ryan sagt:

    Thank you so much, excellent example!

  • Vinay sagt:

    So I want to show a toast with a message when a set of 2 buttons are pressed….so say I want to show a toast with message “Hi” when button 1 and 3 are pressed.How will I do that?? please help me!! really need the help!!! still in school and have a project submission this weekend…please reply!!

  • Reiszecke sagt:

    Helped a lot, but Eclipse still sees a few errors in there:

    for (View view : views)
    ______________|^| : “Type mismatch: cannot convert from element type Object to View”

    View view = possibleViews.get(i);
    ______________|^| : “Type mismatch: cannot convert from Object to View”

    if (((view.getHeight() + location[1] + moveGap >= y)
    “The operator & is undefined for the argument type(s) boolean, int”

    & (view.getWidth() + location[0] + moveGap >= x)
    & (view.getLeft()
    “The operator & is undefined for the argument type(s) boolean, int”

    moveGap
    “MoveGap cannot be resolved to a type”

    Sorry if i annoy you with these problems but i’d be so happy if you could fix that for us :/

  • Pascal sagt:

    first go to the newer version linked above. then download the zip package and don’t copy the Text from the page.

  • alex sagt:

    Thanks, but if I don’t want to have 10 statements every second how do I make, that just UP and DOWN for every button is called once?

  • passsy sagt:

    do this:

    public boolean onTouchEvent( MotionEvent event ){

    if (event.getActionMasked()==MotionEvent.ACTION_UP
    ||event.getActionMasked()==MotionEvent.ACTION_DOWN){
    //TODO do something
    }
    //ignore the rest
    }

Hinterlasse eine Antwort

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>