Android Open Source - Android-GUI-Creator Composite Gesture Detector






From Project

Back to project page Android-GUI-Creator.

License

The source code is released under:

GNU General Public License

If you think the Android project Android-GUI-Creator listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (c) 2012./*from  w ww  .j  av  a 2 s .c  om*/
 * This file is part of Android Interface Toolkit application.
 *
 * Android Interface Toolkit is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Android Interface Toolkit is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with Android Interface Toolkit.  If not, see <http://www.gnu.org/licenses/>.
 */

package name.wildswift.android.guitool.gesture;

import android.content.Context;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import name.wildswift.android.guitool.gesture.helpers.DetectorsElement;
import name.wildswift.android.guitool.gesture.helpers.FingerState;
import name.wildswift.android.guitool.gesture.recognizers.DoubleTapRecognizer;
import name.wildswift.android.guitool.gesture.recognizers.GestureRecognizer;
import name.wildswift.android.guitool.gesture.recognizers.LongPressRecognizer;
import name.wildswift.android.guitool.gesture.recognizers.SingleTapRecognizer;
import name.wildswift.android.guitool.gesture.recognizers.simple.SimpleGesture;
import name.wildswift.android.guitool.gesture.recognizers.simple.*;

import java.util.Arrays;
import java.util.LinkedList;


/**
 * 11.02.12
 *
 * @author Swift
 */
public class CompositeGestureDetector {

    private OnGestureListener listener;

    private DetectorsElement[] detectors;
    private FingerState[] states;
    private SimpleGesture[] gestures;
    private boolean gesturesCleared = true;

    private GestureRecognizer[] recognizers;

    private LinkedList<GestureRecognizer> activeRecognizers;

    private byte maxFingers;

    public CompositeGestureDetector(Context context, byte maxFingers, OnGestureListener listener) {
        if (maxFingers <= 0) throw new IllegalArgumentException("maxFingers must be more then 0");

        this.maxFingers = maxFingers;
        this.listener = listener;

        detectors = new DetectorsElement[maxFingers];
        for (byte i = 0; i < maxFingers; i++) {
            detectors[i] = new DetectorsElement(context, new InternalGestureDetectorListener(i));
        }

        states = new FingerState[maxFingers];
        for (byte i = 0; i < maxFingers; i++) {
            states[i] = new FingerState();
        }

        gestures = new SimpleGesture[maxFingers];
        for (byte i = 0; i < maxFingers; i++) {
            gestures[i] = null;
        }

        recognizers = new GestureRecognizer[]{
                new SingleTapRecognizer(listener),
                new LongPressRecognizer(listener),
                new DoubleTapRecognizer(listener)
        };
    }

    public boolean onMotionEvent(MotionEvent event) {
        int actionIndexExternal;
        int actionIndex;
        switch (event.getActionMasked()){
            case MotionEvent.ACTION_DOWN:
                // if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
                listener.onGestureStart(event);
                activeRecognizers = new LinkedList<GestureRecognizer>(Arrays.asList(recognizers));
            case MotionEvent.ACTION_POINTER_DOWN:
                // find empty slot for new finger, mark it as busy
                // and increment indexes of all fingers that more or equals than new 
                actionIndexExternal = event.getActionIndex();
                boolean foundEmptySlot = false;
                actionIndex = -1;
                for (int i = 0; i < maxFingers; i++){
                    if (states[i].isDown() && states[i].getFingerNum() >= actionIndexExternal) {
                        states[i].setFingerNum(states[i].getFingerNum() + 1);
                    }
                    if (!states[i].isDown() && !foundEmptySlot) {
                        foundEmptySlot = true;
                        states[i].setDown(true);
                        states[i].setDownTime(event.getEventTime());
                        states[i].setFingerNum(actionIndexExternal);
                        actionIndex = i;
                    }
                }
                if (actionIndex == -1) return false;

                // send event to associated GestureDetector group
                detectors[actionIndex].onTouchEvent(MotionEvent.obtain(event.getEventTime(), event.getEventTime(), MotionEvent.ACTION_DOWN,
                        event.getX(states[actionIndex].getFingerNum()), event.getY(states[actionIndex].getFingerNum()), event.getMetaState()));

                // notify listener about new finger in gesture
                listener.onFingerStart(actionIndex, event);
                break;


            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                // check index of finger
                actionIndexExternal = event.getActionIndex();
                // up event generated in 0 - event.getPointerCount() interval
                // you may receive all up events with 0 actionIndex
                actionIndex = -1;
                for (int i = 0; i < maxFingers; i++) {
                    if (states[i].isDown() && states[i].getFingerNum() == actionIndexExternal) {
                        actionIndex = i;
                        states[i].setDown(false);
                    }
                    if (states[i].isDown() && states[i].getFingerNum() >= actionIndexExternal) {
                        states[i].setFingerNum(states[i].getFingerNum() - 1);
                    }
                }
                // if action index not changed action not for our detector
                if (actionIndex == -1) return false;


                // send event to associated GestureDetector group
                detectors[actionIndex].onTouchEvent(MotionEvent.obtain(states[actionIndex].getDownTime(), event.getEventTime(), MotionEvent.ACTION_UP,
                        event.getX(states[actionIndex].getFingerNum()), event.getY(states[actionIndex].getFingerNum()), event.getMetaState()));

                // notify listener about finger is up
                listener.onFingerEnd(actionIndex, event);
                // if we receive action UP that means that all
                if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                    listener.onGestureEnd(event);
                }
                break;

            case MotionEvent.ACTION_MOVE:
                for(int i = 0; i < maxFingers; i++) {
                    FingerState state = states[i];
                    if (!state.isDown()) continue;
                    detectors[i].onTouchEvent(MotionEvent.obtain(states[i].getDownTime(), event.getEventTime(), MotionEvent.ACTION_MOVE,
                            event.getX(states[i].getFingerNum()), event.getY(states[i].getFingerNum()), event.getMetaState()));
                }
                break;
        }

        notifyRecognizers();

        return true;
    }


    private void notifyRecognizers() {
        if (gesturesCleared) return;
        LinkedList<GestureRecognizer> recognizersForDelete = new LinkedList<GestureRecognizer>();
        for (GestureRecognizer recognizer : activeRecognizers) {
            if (!recognizer.onNewEvent(gestures)) {
                recognizersForDelete.add(recognizer);
            }
        }
        activeRecognizers.removeAll(recognizersForDelete);
        for (int i = 0; i < gestures.length; i++) {
            gestures[i] = null;
        }
        gesturesCleared = true;
    }


    private class InternalGestureDetectorListener implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener  {
        private int index;

        private InternalGestureDetectorListener(int index) {
            this.index = index;
        }

        public boolean onDown(MotionEvent motionEvent) {
            gestures[index] = new DownSimpleGesture(motionEvent);
            gesturesCleared = false;
            Log.d(getClass().getSimpleName(), "onDown " + index);
            return true;
        }

        public void onShowPress(MotionEvent motionEvent) {
            // Pass not need
        }

        public boolean onSingleTapUp(MotionEvent motionEvent) {
            gestures[index] = new SingleTapSimpleGesture(motionEvent);
            gesturesCleared = false;
            Log.d(getClass().getSimpleName(), "onSingleTapUp " + index);
            return true;
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2, float v, float v1) {
            gestures[index] = new ScrollSimpleGesture(e1, e2, v, v1);
            gesturesCleared = false;
            Log.d(getClass().getSimpleName(), "onScroll " + index);
            return true;
        }

        public void onLongPress(MotionEvent motionEvent) {
            // because this event generates from handler after some time, it have special handling
            gestures[index] = new LongPressSimpleGesture(motionEvent);
            gesturesCleared = false;
            Log.d(getClass().getSimpleName(), "onLongPress " + index);
            notifyRecognizers();
        }

        public boolean onFling(MotionEvent e1, MotionEvent e2, float v, float v1) {
            gestures[index] = new FlingSimpleGesture(e1, e2, v, v1);
            gesturesCleared = false;
            Log.d(getClass().getSimpleName(), "onFling " + index);
            return true;
        }

        public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
            // Pass not need
            return true;
        }

        public boolean onDoubleTap(MotionEvent motionEvent) {
            gestures[index] = new DoubleTapSimpleGesture(motionEvent);
            gesturesCleared = false;
            Log.d(getClass().getSimpleName(), "onDoubleTap " + index);
            return true;
        }

        public boolean onDoubleTapEvent(MotionEvent motionEvent) {
            // Pass not need
            return false;
        }
    }


}




Java Source Code List

name.wildswift.android.guitool.AndroidInterfaceTool.java
name.wildswift.android.guitool.MainBuilderScreen.java
name.wildswift.android.guitool.decorators.TestView.java
name.wildswift.android.guitool.decorators.ViewDecorator.java
name.wildswift.android.guitool.gesture.CompositeGestureDetector.java
name.wildswift.android.guitool.gesture.OnGestureListener.java
name.wildswift.android.guitool.gesture.gestures.DoubleTap.java
name.wildswift.android.guitool.gesture.gestures.GestureType.java
name.wildswift.android.guitool.gesture.gestures.Gesture.java
name.wildswift.android.guitool.gesture.gestures.LongPress.java
name.wildswift.android.guitool.gesture.gestures.MotionPoint.java
name.wildswift.android.guitool.gesture.gestures.SingleTap.java
name.wildswift.android.guitool.gesture.helpers.DetectorsElement.java
name.wildswift.android.guitool.gesture.helpers.FingerState.java
name.wildswift.android.guitool.gesture.helpers.LongPressWrapper.java
name.wildswift.android.guitool.gesture.helpers.OnGestureListenerWrapper.java
name.wildswift.android.guitool.gesture.recognizers.DoubleTapRecognizer.java
name.wildswift.android.guitool.gesture.recognizers.GestureRecognizer.java
name.wildswift.android.guitool.gesture.recognizers.LongPressRecognizer.java
name.wildswift.android.guitool.gesture.recognizers.SingleTapRecognizer.java
name.wildswift.android.guitool.gesture.recognizers.simple.DoubleTapSimpleGesture.java
name.wildswift.android.guitool.gesture.recognizers.simple.DownSimpleGesture.java
name.wildswift.android.guitool.gesture.recognizers.simple.FlingSimpleGesture.java
name.wildswift.android.guitool.gesture.recognizers.simple.LongPressSimpleGesture.java
name.wildswift.android.guitool.gesture.recognizers.simple.ScrollSimpleGesture.java
name.wildswift.android.guitool.gesture.recognizers.simple.SimpleGesture.java
name.wildswift.android.guitool.gesture.recognizers.simple.SingleTapSimpleGesture.java
name.wildswift.android.guitool.view.RotateDrawable.java
name.wildswift.android.guitool.view.SlidePanel.java