Android Open Source - custom-touch-examples Two Dimension Gesture Scroll View






From Project

Back to project page custom-touch-examples.

License

The source code is released under:

Copyright (c) 2012 Wireless Designs, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in ...

If you think the Android project custom-touch-examples 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

package com.examples.customtouch.widget;
// w w w . ja va2 s  . c  o  m
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.OverScroller;

public class TwoDimensionGestureScrollView extends FrameLayout {

  private GestureDetector mDetector;
  private OverScroller mScroller;
  
  /* Positions of the last motion event */
  private float mInitialX, mInitialY;
  /* Drag threshold */
  private int mTouchSlop;
  
  public TwoDimensionGestureScrollView(Context context) {
    super(context);
    init(context);
  }

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

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

  private void init(Context context) {
    mDetector = new GestureDetector(context, mListener);
    mScroller = new OverScroller(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);
    }
  
  @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 x = mScroller.getCurrX();
            int y = mScroller.getCurrY();

            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);
            }
        }
    }
  
  /*
   * 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;
    }

    //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/2, (int)-velocityY/2);
            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;
        }
    };

    /*
     * 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);
    }
}




Java Source Code List

com.examples.customtouch.MainActivity.java
com.examples.customtouch.MoveLoggerActivity.java
com.examples.customtouch.MultitouchActivity.java
com.examples.customtouch.TouchDelegateActivity.java
com.examples.customtouch.TouchForwardActivity.java
com.examples.customtouch.TouchInterceptActivity.java
com.examples.customtouch.TouchListenerActivity.java
com.examples.customtouch.TwoDimensionGestureScrollActivity.java
com.examples.customtouch.TwoDimensionScrollActivity.java
com.examples.customtouch.widget.RotateZoomImageView.java
com.examples.customtouch.widget.TouchDelegateLayout.java
com.examples.customtouch.widget.TouchForwardLayout.java
com.examples.customtouch.widget.TwoDimensionGestureScrollView.java
com.examples.customtouch.widget.TwoDimensionScrollView.java