Handle custom Gesture

Description

The following code shows how to Handle custom Gesture.

Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5

Example


package com.java2s.myapplication3.app;
/*from w  ww. j a  va 2 s  . c  om*/
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.Scroller;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        PanGestureScrollView scrollView = new PanGestureScrollView(this);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        for(int i=0; i < 5; i++) {
            ImageView iv = new ImageButton(this);
            iv.setImageResource(R.drawable.ic_launcher);
            layout.addView(iv, new LinearLayout.LayoutParams(1000, 500));
        }

        scrollView.addView(layout);
        setContentView(scrollView);
    }
}


class PanGestureScrollView extends FrameLayout {

    private GestureDetector mDetector;
    private Scroller mScroller;

    /* Positions of the last motion event */
    private float mInitialX, mInitialY;
    /* Drag threshold */
    private int mTouchSlop;

    public PanGestureScrollView(Context context) {
        super(context);
        init(context);
    }

    public PanGestureScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PanGestureScrollView(Context context, AttributeSet attrs,
                                int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        mDetector = new GestureDetector(context, mListener);
        mScroller = new Scroller(context);
        // Get system constants for touch thresholds
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    /*
     * Override the measureChild... implementations to guarantee that the child
     * view gets measured to be as large as it wants to be. The default
     * implementation will force some children to be only as large as this view.
     */
    @Override
    protected void measureChild(View child, int parentWidthMeasureSpec,
                                int parentHeightMeasureSpec) {
        int childWidthMeasureSpec;
        int childHeightMeasureSpec;

        childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0,
                MeasureSpec.UNSPECIFIED);
        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0,
                MeasureSpec.UNSPECIFIED);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

    @Override
    protected void measureChildWithMargins(View child,
                                           int parentWidthMeasureSpec, int widthUsed,
                                           int parentHeightMeasureSpec, int heightUsed) {
        final MarginLayoutParams lp = (MarginLayoutParams) child
                .getLayoutParams();

        final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
                lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);
        final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
                lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

    // Listener to handle all the touch events
    private SimpleOnGestureListener mListener = new SimpleOnGestureListener() {
        public boolean onDown(MotionEvent e) {
            // Cancel any current fling
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }
            return true;
        }

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            // Call a helper method to start the scroller animation
            fling((int) -velocityX / 3, (int) -velocityY / 3);
            return true;
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            // Any view can be scrolled by simply calling its scrollBy() method
            scrollBy((int) distanceX, (int) distanceY);
            return true;
        }
    };

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            // This is called at drawing time by ViewGroup. We use
            // this method to keep the fling animation going through
            // to completion.
            int oldX = getScrollX();
            int oldY = getScrollY();
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();

            if (getChildCount() > 0) {
                View child = getChildAt(0);
                x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(),
                        child.getWidth());
                y = clamp(y,
                        getHeight() - getPaddingBottom() - getPaddingTop(),
                        child.getHeight());
                if (x != oldX || y != oldY) {
                    scrollTo(x, y);
                }
            }

            // Keep on drawing until the animation has finished.
            postInvalidate();
        }
    }

    // Override scrollTo to do bounds checks on any scrolling request
    @Override
    public void scrollTo(int x, int y) {
        // we rely on the fact the View.scrollBy calls scrollTo.
        if (getChildCount() > 0) {
            View child = getChildAt(0);
            x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(),
                    child.getWidth());
            y = clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(),
                    child.getHeight());
            if (x != getScrollX() || y != getScrollY()) {
                super.scrollTo(x, y);
            }
        }
    }

    /*
     * Monitor touch events passed down to the children and intercept as soon as
     * it is determined we are dragging
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mInitialX = event.getX();
                mInitialY = event.getY();
                // Feed the down event to the detector so it has
                // context when/if dragging begins
                mDetector.onTouchEvent(event);
                break;
            case MotionEvent.ACTION_MOVE:
                final float x = event.getX();
                final float y = event.getY();
                final int yDiff = (int) Math.abs(y - mInitialY);
                final int xDiff = (int) Math.abs(x - mInitialX);
                // Verify that either difference is enough to be a drag
                if (yDiff > mTouchSlop || xDiff > mTouchSlop) {
                    // Start capturing events
                    return true;
                }
                break;
        }

        return super.onInterceptTouchEvent(event);
    }

    /*
     * Feed all touch events we receive to the detector for processing.
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDetector.onTouchEvent(event);
    }

    /*
     * Utility method to initialize the Scroller and start redrawing
     */
    public void fling(int velocityX, int velocityY) {
        if (getChildCount() > 0) {
            int height = getHeight() - getPaddingBottom() - getPaddingTop();
            int width = getWidth() - getPaddingLeft() - getPaddingRight();
            int bottom = getChildAt(0).getHeight();
            int right = getChildAt(0).getWidth();

            mScroller.fling(getScrollX(), getScrollY(), velocityX, velocityY,
                    0, Math.max(0, right - width), 0,
                    Math.max(0, bottom - height));

            invalidate();
        }
    }

    /*
     * Utility method to assist in doing bounds checking
     */
    private int clamp(int n, int my, int child) {
        if (my >= child || n < 0) {
            /*
             * my >= child is this case: |--------------- me ---------------|
             * |------ child ------| or |--------------- me ---------------|
             * |------ child ------| or |--------------- me ---------------|
             * |------ child ------|
             *
             * n < 0 is this case: |------ me ------| |-------- child --------|
             * |-- mScrollX --|
             */
            return 0;
        }
        if ((my + n) > child) {
            /*
             * this case: |------ me ------| |------ child ------| |-- mScrollX
             * --|
             */
            return child - my;
        }
        return n;
    }
}
Handle custom Gesture




















Home »
  Android »
    Android UI »




UI Basics
Action Bar
Animation
Button
Canvas
CheckBox
Clock Date Picker
Dialog
EditText
Event
Fragment
Gesture
GridView
ImageView
Layout
ListView
Map
Menu
Model
OpenGL
ProgressBar
RadioButton
Spinner
Tab
TextView
Thread
Toast
Video
View
WebView