Advertisement
Guest User

DragableSpace

a guest
Jan 31st, 2011
1,765
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.57 KB | None | 0 0
  1. public class DragableSpace extends ViewGroup {
  2.     private Scroller mScroller;
  3.     private VelocityTracker mVelocityTracker;
  4.  
  5.     private int mScrollX = 0;
  6.     private int mCurrentScreen = 0;
  7.  
  8.     private float mLastMotionX;
  9.  
  10.     private static final String LOG_TAG = "DragableSpace";
  11.  
  12.     private static final int SNAP_VELOCITY = 1000;
  13.  
  14.     private final static int TOUCH_STATE_REST = 0;
  15.     private final static int TOUCH_STATE_SCROLLING = 1;
  16.  
  17.     private int mTouchState = TOUCH_STATE_REST;
  18.  
  19.     private int mTouchSlop = 0;
  20.  
  21.     public DragableSpace(Context context) {
  22.         super(context);
  23.         mScroller = new Scroller(context);
  24.  
  25.         mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
  26.  
  27.         this.setLayoutParams(new ViewGroup.LayoutParams(
  28.                     ViewGroup.LayoutParams.WRAP_CONTENT,
  29.                     ViewGroup.LayoutParams.FILL_PARENT));
  30.     }
  31.  
  32.     public DragableSpace(Context context, AttributeSet attrs) {
  33.         super(context, attrs);
  34.         TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DragableSpace);
  35.         mCurrentScreen = a.getInteger(R.styleable.DragableSpace_default_screen, 0);
  36.        
  37.         mScroller = new Scroller(context);
  38.  
  39.         mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
  40.  
  41.         this.setLayoutParams(new ViewGroup.LayoutParams(
  42.                     ViewGroup.LayoutParams.WRAP_CONTENT ,
  43.                     ViewGroup.LayoutParams.FILL_PARENT));
  44.  
  45.        
  46.     }
  47.  
  48.     @Override
  49.     public boolean onInterceptTouchEvent(MotionEvent ev) {
  50.         /*
  51.          * This method JUST determines whether we want to intercept the motion.
  52.          * If we return true, onTouchEvent will be called and we do the actual
  53.          * scrolling there.
  54.          */
  55.  
  56.         /*
  57.          * Shortcut the most recurring case: the user is in the dragging state
  58.          * and he is moving his finger. We want to intercept this motion.
  59.          */
  60.         final int action = ev.getAction();
  61.         if ((action == MotionEvent.ACTION_MOVE)
  62.                 && (mTouchState != TOUCH_STATE_REST)) {
  63.             return true;
  64.                 }
  65.  
  66.         final float x = ev.getX();
  67.  
  68.         switch (action) {
  69.             case MotionEvent.ACTION_MOVE:
  70.                 /*
  71.                  * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
  72.                  * whether the user has moved far enough from his original down touch.
  73.                  */
  74.  
  75.                 /*
  76.                  * Locally do absolute value. mLastMotionX is set to the y value
  77.                  * of the down event.
  78.                  */
  79.                 final int xDiff = (int) Math.abs(x - mLastMotionX);
  80.  
  81.                 boolean xMoved = xDiff > mTouchSlop;
  82.  
  83.                 if (xMoved) {
  84.                     // Scroll if the user moved far enough along the X axis
  85.                     mTouchState = TOUCH_STATE_SCROLLING;
  86.                 }
  87.                 break;
  88.  
  89.             case MotionEvent.ACTION_DOWN:
  90.                 // Remember location of down touch
  91.                 mLastMotionX = x;
  92.  
  93.                 /*
  94.                  * If being flinged and user touches the screen, initiate drag;
  95.                  * otherwise don't.  mScroller.isFinished should be false when
  96.                  * being flinged.
  97.                  */
  98.                 mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
  99.                 break;
  100.  
  101.             case MotionEvent.ACTION_CANCEL:
  102.             case MotionEvent.ACTION_UP:
  103.                 // Release the drag
  104.                 mTouchState = TOUCH_STATE_REST;
  105.                 break;
  106.         }
  107.  
  108.         /*
  109.          * The only time we want to intercept motion events is if we are in the
  110.          * drag mode.
  111.          */
  112.         return mTouchState != TOUCH_STATE_REST;
  113.     }
  114.  
  115.     @Override
  116.     public boolean onTouchEvent(MotionEvent event) {
  117.  
  118.         if (mVelocityTracker == null) {
  119.             mVelocityTracker = VelocityTracker.obtain();
  120.         }
  121.         mVelocityTracker.addMovement(event);
  122.  
  123.         final int action = event.getAction();
  124.         final float x = event.getX();
  125.  
  126.         switch (action) {
  127.             case MotionEvent.ACTION_DOWN:
  128.                 Log.i(LOG_TAG, "event : down");
  129.                 /*
  130.                  * If being flinged and user touches, stop the fling. isFinished
  131.                  * will be false if being flinged.
  132.                  */
  133.                 if (!mScroller.isFinished()) {
  134.                     mScroller.abortAnimation();
  135.                 }
  136.  
  137.                 // Remember where the motion event started
  138.                 mLastMotionX = x;
  139.                 break;
  140.             case MotionEvent.ACTION_MOVE:
  141.                 // Log.i(LOG_TAG,"event : move");
  142.                 // if (mTouchState == TOUCH_STATE_SCROLLING) {
  143.                 // Scroll to follow the motion event
  144.                 final int deltaX = (int) (mLastMotionX - x);
  145.                 mLastMotionX = x;
  146.  
  147.                 //Log.i(LOG_TAG, "event : move, deltaX " + deltaX + ", mScrollX " + mScrollX);
  148.  
  149.                 if (deltaX < 0) {
  150.                     if (mScrollX > 0) {
  151.                         scrollBy(Math.max(-mScrollX, deltaX), 0);
  152.                     }
  153.                 } else if (deltaX > 0) {
  154.                     final int availableToScroll = getChildAt(getChildCount() - 1)
  155.                         .getRight()
  156.                         - mScrollX - getWidth();
  157.                     if (availableToScroll > 0) {
  158.                         scrollBy(Math.min(availableToScroll, deltaX), 0);
  159.                     }
  160.                 }
  161.                 // }
  162.                 break;
  163.             case MotionEvent.ACTION_UP:
  164.                 Log.i(LOG_TAG, "event : up");
  165.                 // if (mTouchState == TOUCH_STATE_SCROLLING) {
  166.                 final VelocityTracker velocityTracker = mVelocityTracker;
  167.                 velocityTracker.computeCurrentVelocity(1000);
  168.                 int velocityX = (int) velocityTracker.getXVelocity();
  169.  
  170.                 if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
  171.                     // Fling hard enough to move left
  172.                     snapToScreen(mCurrentScreen - 1);
  173.                 } else if (velocityX < -SNAP_VELOCITY
  174.                         && mCurrentScreen < getChildCount() - 1) {
  175.                     // Fling hard enough to move right
  176.                     snapToScreen(mCurrentScreen + 1);
  177.                 } else {
  178.                     snapToDestination();
  179.                 }
  180.  
  181.                 if (mVelocityTracker != null) {
  182.                     mVelocityTracker.recycle();
  183.                     mVelocityTracker = null;
  184.                 }
  185.                 // }
  186.                 mTouchState = TOUCH_STATE_REST;
  187.                 break;
  188.             case MotionEvent.ACTION_CANCEL:
  189.                 Log.i(LOG_TAG, "event : cancel");
  190.                 mTouchState = TOUCH_STATE_REST;
  191.         }
  192.         mScrollX = this.getScrollX();
  193.  
  194.         return true;
  195.     }
  196.  
  197.     private void snapToDestination() {
  198.         final int screenWidth = getWidth();
  199.         final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
  200.         Log.i(LOG_TAG, "from des");
  201.         snapToScreen(whichScreen);
  202.     }
  203.  
  204.     public void snapToScreen(int whichScreen) {        
  205.         Log.i(LOG_TAG, "snap To Screen " + whichScreen);
  206.         mCurrentScreen = whichScreen;
  207.         final int newX = whichScreen * getWidth();
  208.         final int delta = newX - mScrollX;
  209.         mScroller.startScroll(mScrollX, 0, delta, 0, Math.abs(delta) * 2);            
  210.         invalidate();
  211.     }
  212.  
  213.     public void setToScreen(int whichScreen) {
  214.         Log.i(LOG_TAG, "set To Screen " + whichScreen);
  215.         mCurrentScreen = whichScreen;
  216.         final int newX = whichScreen * getWidth();
  217.         mScroller.startScroll(newX, 0, 0, 0, 10);            
  218.         invalidate();
  219.     }
  220.  
  221.     @Override
  222.     protected void onLayout(boolean changed, int l, int t, int r, int b) {
  223.         int childLeft = 0;
  224.  
  225.         final int count = getChildCount();
  226.         for (int i = 0; i < count; i++) {
  227.             final View child = getChildAt(i);
  228.             if (child.getVisibility() != View.GONE) {
  229.                 final int childWidth = child.getMeasuredWidth();
  230.                 child.layout(childLeft, 0, childLeft + childWidth, child
  231.                         .getMeasuredHeight());
  232.                 childLeft += childWidth;
  233.             }
  234.         }
  235.  
  236.     }
  237.  
  238.     @Override
  239.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  240.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  241.  
  242.         final int width = MeasureSpec.getSize(widthMeasureSpec);
  243.         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  244.         if (widthMode != MeasureSpec.EXACTLY) {
  245.             throw new IllegalStateException("error mode.");
  246.         }
  247.  
  248.         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  249.         if (heightMode != MeasureSpec.EXACTLY) {
  250.             throw new IllegalStateException("error mode.");
  251.         }
  252.  
  253.         // The children are given the same width and height as the workspace
  254.         final int count = getChildCount();
  255.         for (int i = 0; i < count; i++) {
  256.             getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
  257.         }
  258.         Log.i(LOG_TAG, "moving to screen "+mCurrentScreen);
  259.         scrollTo(mCurrentScreen * width, 0);      
  260.     }  
  261.  
  262.     @Override
  263.     public void computeScroll() {
  264.         if (mScroller.computeScrollOffset()) {
  265.             mScrollX = mScroller.getCurrX();
  266.             scrollTo(mScrollX, 0);
  267.             postInvalidate();
  268.         }
  269.     }
  270.    
  271.     /**
  272.      * Return the parceable instance to be saved
  273.      */
  274.     @Override
  275.     protected Parcelable onSaveInstanceState() {
  276.       final SavedState state = new SavedState(super.onSaveInstanceState());
  277.       state.currentScreen = mCurrentScreen;
  278.       return state;
  279.     }
  280.  
  281.  
  282.     /**
  283.      * Restore the previous saved current screen
  284.      */
  285.     @Override
  286.     protected void onRestoreInstanceState(Parcelable state) {
  287.       SavedState savedState = (SavedState) state;
  288.       super.onRestoreInstanceState(savedState.getSuperState());
  289.       if (savedState.currentScreen != -1) {
  290.         mCurrentScreen = savedState.currentScreen;
  291.       }
  292.     }
  293.  
  294.     // ========================= INNER CLASSES ==============================
  295.  
  296.     public interface onViewChangedEvent{      
  297.       void onViewChange (int currentViewIndex);
  298.     }
  299.  
  300.     /**
  301.      * A SavedState which save and load the current screen
  302.      */
  303.     public static class SavedState extends BaseSavedState {
  304.       int currentScreen = -1;
  305.  
  306.       /**
  307.        * Internal constructor
  308.        *
  309.        * @param superState
  310.        */
  311.       SavedState(Parcelable superState) {
  312.         super(superState);
  313.       }
  314.  
  315.       /**
  316.        * Private constructor
  317.        *
  318.        * @param in
  319.        */
  320.       private SavedState(Parcel in) {
  321.         super(in);
  322.         currentScreen = in.readInt();
  323.       }
  324.  
  325.       /**
  326.        * Save the current screen
  327.        */
  328.       @Override
  329.       public void writeToParcel(Parcel out, int flags) {
  330.         super.writeToParcel(out, flags);
  331.         out.writeInt(currentScreen);
  332.       }
  333.  
  334.       /**
  335.        * Return a Parcelable creator
  336.        */
  337.       public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
  338.         public SavedState createFromParcel(Parcel in) {
  339.           return new SavedState(in);
  340.         }
  341.  
  342.         public SavedState[] newArray(int size) {
  343.           return new SavedState[size];
  344.         }
  345.       };
  346.     }
  347.  
  348. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement