Advertisement
Guest User

SemiOpening Sliding Drawer

a guest
Mar 16th, 2012
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 33.48 KB | None | 0 0
  1. /**
  2.  * SlidingDrawer hides content out of the screen and allows the user to drag a
  3.  * handle to bring the content on screen. SlidingDrawer can be used vertically
  4.  * or horizontally.
  5.  *
  6.  * A special widget composed of two children views: the handle, that the users
  7.  * drags, and the content, attached to the handle and dragged with it.
  8.  *
  9.  * SlidingDrawer should be used as an overlay inside layouts. This means
  10.  * SlidingDrawer should only be used inside of a FrameLayout or a RelativeLayout
  11.  * for instance. The size of the SlidingDrawer defines how much space the
  12.  * content will occupy once slid out so SlidingDrawer should usually use
  13.  * fill_parent for both its dimensions.
  14.  *
  15.  * Inside an XML layout, SlidingDrawer must define the id of the handle and of
  16.  * the content:
  17.  *
  18.  * <pre class="prettyprint">
  19.  * &lt;SlidingDrawer
  20.  *     android:id="@+id/drawer"
  21.  *     android:layout_width="fill_parent"
  22.  *     android:layout_height="fill_parent"
  23.  *
  24.  *     android:handle="@+id/handle"
  25.  *     android:content="@+id/content"&gt;
  26.  *
  27.  *     &lt;ImageView
  28.  *         android:id="@id/handle"
  29.  *         android:layout_width="88dip"
  30.  *         android:layout_height="44dip" /&gt;
  31.  *
  32.  *     &lt;GridView
  33.  *         android:id="@id/content"
  34.  *         android:layout_width="fill_parent"
  35.  *         android:layout_height="fill_parent" /&gt;
  36.  *
  37.  * &lt;/SlidingDrawer&gt;
  38.  * </pre>
  39.  *
  40.  * @attr ref android.R.styleable#SlidingDrawer_content
  41.  * @attr ref android.R.styleable#SlidingDrawer_handle
  42.  * @attr ref android.R.styleable#SlidingDrawer_topOffset
  43.  * @attr ref android.R.styleable#SlidingDrawer_bottomOffset
  44.  * @attr ref android.R.styleable#SlidingDrawer_orientation
  45.  * @attr ref android.R.styleable#SlidingDrawer_allowSingleTap
  46.  * @attr ref android.R.styleable#SlidingDrawer_animateOnClick
  47.  */
  48. public class SlidingDrawer extends ViewGroup {
  49.     public static final int ORIENTATION_HORIZONTAL = 0;
  50.     public static final int ORIENTATION_VERTICAL = 1;
  51.  
  52.     private static final int TAP_THRESHOLD = 6;
  53.     private static final float MAXIMUM_TAP_VELOCITY = 100.0f;
  54.     private static final float MAXIMUM_MINOR_VELOCITY = 150.0f;
  55.     private static final float MAXIMUM_MAJOR_VELOCITY = 200.0f;
  56.     private static final float MAXIMUM_ACCELERATION = 2000.0f;
  57.     private static final int VELOCITY_UNITS = 1000;
  58.     private static final int MSG_ANIMATE = 1000;
  59.     private static final int ANIMATION_FRAME_DURATION = 1000 / 60;
  60.  
  61.     private static final int EXPANDED_FULL_OPEN = -10001;
  62.     private static final int COLLAPSED_FULL_CLOSED = -10002;
  63.  
  64.     private final int mHandleId;
  65.     private final int mContentId;
  66.  
  67.     private View mHandle;
  68.     private View mContent;
  69.  
  70.     private final Rect mFrame = new Rect();
  71.     private final Rect mInvalidate = new Rect();
  72.     private boolean mTracking;
  73.     private boolean mLocked;
  74.  
  75.     private VelocityTracker mVelocityTracker;
  76.  
  77.     private boolean mVertical;
  78.     private boolean mExpanded;
  79.     private int mBottomOffset;
  80.     private int mTopOffset;
  81.     private int mHandleHeight;
  82.     private int mHandleWidth;
  83.     private ListView listView; // this is listview inside relativelayout which
  84.                                 // is content of sliding drawer
  85.  
  86.     private OnDrawerOpenListener mOnDrawerOpenListener;
  87.     private OnDrawerCloseListener mOnDrawerCloseListener;
  88.     private OnDrawerScrollListener mOnDrawerScrollListener;
  89.  
  90.     private final Handler mHandler = new SlidingHandler();
  91.     private float mAnimatedAcceleration;
  92.     private float mAnimatedVelocity;
  93.     private float mAnimationPosition;
  94.     private long mAnimationLastTime;
  95.     private long mCurrentAnimationTime;
  96.     private int mTouchDelta;
  97.     private boolean mAnimating;
  98.     private boolean mAllowSingleTap;
  99.     private boolean mAnimateOnClick;
  100.     private boolean inBetween;
  101.     private final int mTapThreshold;
  102.     private final int mMaximumTapVelocity;
  103.     private final int mMaximumMinorVelocity;
  104.     private final int mMaximumMajorVelocity;
  105.     private final int mMaximumAcceleration;
  106.     private final int mVelocityUnits;
  107.     /**
  108.      * this variable is set to true when we want drawer to be closed upto an
  109.      * certain extent not more than that. take care you have to set int variable
  110.      * closeUpto
  111.      */
  112.     private boolean lockedCanNotCloseMore = false;
  113.     /**
  114.      * this variable is set to true when we want drawer to be opened upto an
  115.      * certain extent not more than that. take care you have to set int variable
  116.      * openUpto
  117.      */
  118.     private boolean lockedCanNotOpenMore = false;
  119.  
  120.     private int closeUpto = 0;
  121.     private int openUpto = 0;
  122.  
  123.     private Context cntxt;
  124.  
  125.     /**
  126.      * Callback invoked when the drawer is opened.
  127.      */
  128.     public static interface OnDrawerOpenListener {
  129.         /**
  130.          * Invoked when the drawer becomes fully open.
  131.          */
  132.         public void onDrawerOpened();
  133.     }
  134.  
  135.     /**
  136.      * Callback invoked when the drawer is closed.
  137.      */
  138.     public static interface OnDrawerCloseListener {
  139.         /**
  140.          * Invoked when the drawer becomes fully closed.
  141.          */
  142.         public void onDrawerClosed();
  143.     }
  144.  
  145.     /**
  146.      * Callback invoked when the drawer is scrolled.
  147.      */
  148.     public static interface OnDrawerScrollListener {
  149.         /**
  150.          * Invoked when the user starts dragging/flinging the drawer's handle.
  151.          */
  152.         public void onScrollStarted();
  153.  
  154.         /**
  155.          * Invoked when the user stops dragging/flinging the drawer's handle.
  156.          */
  157.         public void onScrollEnded();
  158.  
  159.         /**
  160.          *
  161.          * Invoked while scrolling is going on. This callback has relative top
  162.          * position of handle with respect to parent if second argument is true
  163.          * then dont do height calculations in callback since we wont get proper
  164.          * height of sliding drawer and its contents.
  165.          */
  166.         public void onScrolling(int mHandleTop, boolean fromOnattWindw);
  167.     }
  168.  
  169.     /**
  170.      * Creates a new SlidingDrawer from a specified set of attributes defined in
  171.      * XML.
  172.      *
  173.      * @param context
  174.      *            The application's environment.
  175.      * @param attrs
  176.      *            The attributes defined in XML.
  177.      */
  178.     public SlidingDrawer(Context context, AttributeSet attrs) {
  179.         this(context, attrs, 0);
  180.     }
  181.  
  182.     /**
  183.      * Creates a new SlidingDrawer from a specified set of attributes defined in
  184.      * XML.
  185.      *
  186.      * @param context
  187.      *            The application's environment.
  188.      * @param attrs
  189.      *            The attributes defined in XML.
  190.      * @param defStyle
  191.      *            The style to apply to this widget.
  192.      */
  193.     public SlidingDrawer(Context context, AttributeSet attrs, int defStyle) {
  194.         super(context, attrs, defStyle);
  195.         cntxt = context;
  196.         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingDrawer, defStyle, 0);
  197.  
  198.         int orientation = a.getInt(R.styleable.SlidingDrawer_orientation, ORIENTATION_VERTICAL);
  199.         mVertical = orientation == ORIENTATION_VERTICAL;
  200.         mBottomOffset = (int) a.getDimension(R.styleable.SlidingDrawer_bottomOffset, 0.0f);
  201.         mTopOffset = (int) a.getDimension(R.styleable.SlidingDrawer_topOffset, 0.0f);
  202.         mAllowSingleTap = a.getBoolean(R.styleable.SlidingDrawer_allowSingleTap, true);
  203.         mAnimateOnClick = a.getBoolean(R.styleable.SlidingDrawer_animateOnClick, true);
  204.  
  205.         int handleId = a.getResourceId(R.styleable.SlidingDrawer_slide_handle, 0);
  206.         if (handleId == 0) {
  207.             throw new IllegalArgumentException("The handle attribute is required and must refer " + "to a valid child.");
  208.         }
  209.  
  210.         int contentId = a.getResourceId(R.styleable.SlidingDrawer_slide_content, 0);
  211.         if (contentId == 0) {
  212.             throw new IllegalArgumentException("The content attribute is required and must refer "
  213.                     + "to a valid child.");
  214.         }
  215.  
  216.         if (handleId == contentId) {
  217.             throw new IllegalArgumentException("The content and handle attributes must refer "
  218.                     + "to different children.");
  219.         }
  220.  
  221.         mHandleId = handleId;
  222.         mContentId = contentId;
  223.  
  224.         final float density = getResources().getDisplayMetrics().density;
  225.         mTapThreshold = (int) (TAP_THRESHOLD * density + 0.5f);
  226.         mMaximumTapVelocity = (int) (MAXIMUM_TAP_VELOCITY * density + 0.5f);
  227.         mMaximumMinorVelocity = (int) (MAXIMUM_MINOR_VELOCITY * density + 0.5f);
  228.         mMaximumMajorVelocity = (int) (MAXIMUM_MAJOR_VELOCITY * density + 0.5f);
  229.         mMaximumAcceleration = (int) (MAXIMUM_ACCELERATION * density + 0.5f);
  230.         mVelocityUnits = (int) (VELOCITY_UNITS * density + 0.5f);
  231.  
  232.         a.recycle();
  233.  
  234.         setAlwaysDrawnWithCacheEnabled(false);
  235.     }
  236.  
  237.     @Override
  238.     protected void onFinishInflate() {
  239.         mHandle = findViewById(mHandleId);
  240.         if (mHandle == null) {
  241.             throw new IllegalArgumentException("The handle attribute is must refer to an" + " existing child.");
  242.         }
  243.         mHandle.setOnClickListener(new DrawerToggler());
  244.  
  245.         mContent = findViewById(mContentId);
  246.         if (mContent == null) {
  247.             throw new IllegalArgumentException("The content attribute is must refer to an" + " existing child.");
  248.         }
  249.  
  250.         /*
  251.          * below code is written as support to open drawer to an extent so that
  252.          * one item in listview must be visible
  253.          */
  254.         int childCount = ((ViewGroup) mContent).getChildCount();
  255.         boolean gotlistview = false;
  256.         for (int i = 0; i < childCount; i++) {
  257.  
  258.             boolean b = (((ViewGroup) mContent).getChildAt(i) instanceof ListView);
  259.             if (((ViewGroup) mContent).getChildAt(i) instanceof ListView) {
  260.                 listView = (ListView) ((ViewGroup) mContent).getChildAt(i);
  261.                 gotlistview = true;
  262.             }
  263.         }
  264.         if (!gotlistview) {
  265.             throw new IllegalArgumentException("The content must be an ViewGroup and must contain ListView as a child");
  266.         }
  267.         mContent.setVisibility(View.GONE);
  268.     }
  269.  
  270.     @Override
  271.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  272.         int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
  273.         int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
  274.  
  275.         int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
  276.         int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
  277.  
  278.         if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
  279.             throw new RuntimeException("SlidingDrawer cannot have UNSPECIFIED dimensions");
  280.         }
  281.  
  282.         final View handle = mHandle;
  283.         measureChild(handle, widthMeasureSpec, heightMeasureSpec);
  284.  
  285.         if (mVertical) {
  286.             int height = heightSpecSize - handle.getMeasuredHeight() - mTopOffset;
  287.             mContent.measure(MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.EXACTLY),
  288.                     MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
  289.         }
  290.         else {
  291.             int width = widthSpecSize - handle.getMeasuredWidth() - mTopOffset;
  292.             mContent.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
  293.                     heightSpecSize, MeasureSpec.EXACTLY));
  294.         }
  295.  
  296.         setMeasuredDimension(widthSpecSize, heightSpecSize);
  297.     }
  298.  
  299.     @Override
  300.     protected void dispatchDraw(Canvas canvas) {
  301.         final long drawingTime = getDrawingTime();
  302.         final View handle = mHandle;
  303.         final boolean isVertical = mVertical;
  304.  
  305.         drawChild(canvas, handle, drawingTime);
  306.  
  307.         /*
  308.          * if (inBetween) { drawChild(canvas, mContent, drawingTime); //return;
  309.          * }
  310.          */
  311.  
  312.         if (mTracking || mAnimating) {
  313.             final Bitmap cache = mContent.getDrawingCache();
  314.             if (cache != null) {
  315.                 if (isVertical) {
  316.                     canvas.drawBitmap(cache, 0, handle.getBottom(), null);
  317.                 }
  318.                 else {
  319.                     canvas.drawBitmap(cache, handle.getRight(), 0, null);
  320.                 }
  321.             }
  322.             else {
  323.                 canvas.save();
  324.                 canvas.translate(isVertical ? 0 : handle.getLeft() - mTopOffset, isVertical ? handle.getTop()
  325.                         - mTopOffset : 0);
  326.                 drawChild(canvas, mContent, drawingTime);
  327.                 canvas.restore();
  328.             }
  329.         }
  330.         else if (mExpanded) {
  331.             drawChild(canvas, mContent, drawingTime);
  332.         }
  333.     }
  334.  
  335.     @Override
  336.     protected void onLayout(boolean changed, int l, int t, int r, int b) {
  337.         if (mTracking) {
  338.             return;
  339.         }
  340.  
  341.         final int width = r - l;
  342.         final int height = b - t;
  343.  
  344.         final View handle = mHandle;
  345.  
  346.         int childWidth = handle.getMeasuredWidth();
  347.         int childHeight = handle.getMeasuredHeight();
  348.  
  349.         int childLeft;
  350.         int childTop;
  351.  
  352.         final View content = mContent;
  353.  
  354.         if (mVertical) {
  355.             childLeft = (width - childWidth) / 2;
  356.             childTop = mExpanded ? mTopOffset : height - childHeight + mBottomOffset;
  357.  
  358.             content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(), mTopOffset + childHeight
  359.                     + content.getMeasuredHeight());
  360.         }
  361.         else {
  362.             childLeft = mExpanded ? mTopOffset : width - childWidth + mBottomOffset;
  363.             childTop = (height - childHeight) / 2;
  364.  
  365.             content.layout(mTopOffset + childWidth, 0, mTopOffset + childWidth + content.getMeasuredWidth(),
  366.                     content.getMeasuredHeight());
  367.         }
  368.  
  369.         handle.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
  370.         mHandleHeight = handle.getHeight();
  371.         mHandleWidth = handle.getWidth();
  372.     }
  373.  
  374.     @Override
  375.     public boolean onInterceptTouchEvent(MotionEvent event) {
  376.         if (mLocked) {
  377.             return false;
  378.         }
  379.  
  380.         final int action = event.getAction();
  381.  
  382.         float x = event.getX();
  383.         float y = event.getY();
  384.  
  385.         final Rect frame = mFrame;// Rect frame = new Rect();
  386.         final View handle = mHandle;
  387.         handle.getHitRect(frame);
  388.         if (!mTracking && !frame.contains((int) x, (int) y)) {
  389.             return false;
  390.         }
  391.  
  392.         /*
  393.          * if(listView!=null){ if(listView.getChildCount()>0){ View v =
  394.          * listView.getChildAt(0); int delta = getHeight() -
  395.          * (v.getHeight()+mHandle.getHeight()+10); if(mHandle.getTop()>delta ){
  396.          * return false; } }else{ // if listview doesn't contain any items } }
  397.          */
  398.         /*
  399.          * if(inBetween){ return false; }
  400.          */
  401.         if (action == MotionEvent.ACTION_DOWN) {
  402.             mTracking = true;
  403.             mTopOffset = 0;
  404.             handle.setPressed(true);
  405.             // Must be called before prepareTracking()
  406.             // if(handle.getTop()==getHeight()-handle.getHeight()){
  407.             prepareContent();
  408.             // }
  409.  
  410.             // Must be called after prepareContent()
  411.             if (mOnDrawerScrollListener != null) {
  412.                 mOnDrawerScrollListener.onScrollStarted();
  413.             }
  414.  
  415.             if (mVertical) {
  416.                 final int top = mHandle.getTop();
  417.                 mTouchDelta = (int) y - top;
  418.                 prepareTracking(top);
  419.             }
  420.             else {
  421.                 final int left = mHandle.getLeft();
  422.                 mTouchDelta = (int) x - left;
  423.                 prepareTracking(left);
  424.             }
  425.             mVelocityTracker.addMovement(event);
  426.         }
  427.  
  428.         return true;
  429.     }
  430.  
  431.     @Override
  432.     public boolean onTouchEvent(MotionEvent event) {
  433.         if (mLocked) {
  434.             return true;
  435.         }
  436.         if (mTracking) {
  437.             mVelocityTracker.addMovement(event);
  438.             final int action = event.getAction();
  439.             switch (action) {
  440.                 case MotionEvent.ACTION_MOVE:
  441.                     mAnimating = true;
  442.                     if(lockedCanNotCloseMore){
  443.                         if(event.getY()-mTouchDelta>closeUpto){
  444.                            
  445.                         }else{
  446.                             moveHandle((int) (mVertical ? event.getY() : event.getX()) - mTouchDelta);
  447.                         }
  448.                     }
  449.                     else{
  450.                         moveHandle((int) (mVertical ? event.getY() : event.getX()) - mTouchDelta);
  451.                     }
  452.                     break;
  453.                 case MotionEvent.ACTION_UP: {
  454.                     stopTracking();
  455.                     mAnimating = false;
  456.                     mTopOffset = mHandle.getTop();
  457.                     /*
  458.                      * if (mHandle.getTop() < (getHeight() -
  459.                      * mHandle.getHeight())) { //mExpanded = true; inBetween =
  460.                      * true; } else{ inBetween = false; }
  461.                      */
  462.                     openDrawer();
  463.                     requestLayout();
  464.                     // mContent.setVisibility(View.VISIBLE);
  465.                     // sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
  466.                     /*
  467.                      * final VelocityTracker velocityTracker = mVelocityTracker;
  468.                      * velocityTracker.computeCurrentVelocity(mVelocityUnits);
  469.                      *
  470.                      * float yVelocity = velocityTracker.getYVelocity(); float
  471.                      * xVelocity = velocityTracker.getXVelocity(); boolean
  472.                      * negative;
  473.                      *
  474.                      * final boolean vertical = mVertical; if (vertical) {
  475.                      * negative = yVelocity < 0; if (xVelocity < 0) { xVelocity
  476.                      * = -xVelocity; } if (xVelocity > mMaximumMinorVelocity) {
  477.                      * xVelocity = mMaximumMinorVelocity; } } else { negative =
  478.                      * xVelocity < 0; if (yVelocity < 0) { yVelocity =
  479.                      * -yVelocity; } if (yVelocity > mMaximumMinorVelocity) {
  480.                      * yVelocity = mMaximumMinorVelocity; } }
  481.                      *
  482.                      * float velocity = (float) Math.hypot(xVelocity,
  483.                      * yVelocity); if (negative) { velocity = -velocity; }
  484.                      *
  485.                      * final int top = mHandle.getTop(); final int left =
  486.                      * mHandle.getLeft();
  487.                      *
  488.                      * if (Math.abs(velocity) < mMaximumTapVelocity) { if
  489.                      * (vertical ? (mExpanded && top < mTapThreshold +
  490.                      * mTopOffset) || (!mExpanded && top > mBottomOffset +
  491.                      * getBottom() - getTop() - mHandleHeight - mTapThreshold) :
  492.                      * (mExpanded && left < mTapThreshold + mTopOffset) ||
  493.                      * (!mExpanded && left > mBottomOffset + getRight() -
  494.                      * getLeft() - mHandleWidth - mTapThreshold)) {
  495.                      *
  496.                      * if (mAllowSingleTap) {
  497.                      * playSoundEffect(SoundEffectConstants.CLICK);
  498.                      *
  499.                      * if (mExpanded) { animateClose(vertical ? top : left); }
  500.                      * else { animateOpen(vertical ? top : left); } } else {
  501.                      * performFling(vertical ? top : left, velocity, false); }
  502.                      *
  503.                      * } else { performFling(vertical ? top : left, velocity,
  504.                      * false); } } else { performFling(vertical ? top : left,
  505.                      * velocity, false); }
  506.                      */}
  507.                     break;
  508.             }
  509.         }
  510.  
  511.         return mTracking || mAnimating || super.onTouchEvent(event);
  512.     }
  513.  
  514.     private void animateClose(int position) {
  515.         prepareTracking(position);
  516.         performFling(position, mMaximumAcceleration, true);
  517.     }
  518.  
  519.     private void animateOpen(int position) {
  520.         prepareTracking(position);
  521.         performFling(position, -mMaximumAcceleration, true);
  522.     }
  523.  
  524.     private void performFling(int position, float velocity, boolean always) {
  525.         mAnimationPosition = position;
  526.         mAnimatedVelocity = velocity;
  527.  
  528.         if (mExpanded) {
  529.             if (always
  530.                     || (velocity > mMaximumMajorVelocity || (position > mTopOffset
  531.                             + (mVertical ? mHandleHeight : mHandleWidth) && velocity > -mMaximumMajorVelocity))) {
  532.                 // We are expanded, but they didn't move sufficiently to cause
  533.                 // us to retract. Animate back to the expanded position.
  534.                 mAnimatedAcceleration = mMaximumAcceleration;
  535.                 if (velocity < 0) {
  536.                     mAnimatedVelocity = 0;
  537.                 }
  538.             }
  539.             else {
  540.                 // We are expanded and are now going to animate away.
  541.                 mAnimatedAcceleration = -mMaximumAcceleration;
  542.                 if (velocity > 0) {
  543.                     mAnimatedVelocity = 0;
  544.                 }
  545.             }
  546.         }
  547.         else {
  548.             if (!always
  549.                     && (velocity > mMaximumMajorVelocity || (position > (mVertical ? getHeight() : getWidth()) / 2 && velocity > -mMaximumMajorVelocity))) {
  550.                 // We are collapsed, and they moved enough to allow us to
  551.                 // expand.
  552.                 mAnimatedAcceleration = mMaximumAcceleration;
  553.                 if (velocity < 0) {
  554.                     mAnimatedVelocity = 0;
  555.                 }
  556.             }
  557.             else {
  558.                 // We are collapsed, but they didn't move sufficiently to cause
  559.                 // us to retract. Animate back to the collapsed position.
  560.                 mAnimatedAcceleration = -mMaximumAcceleration;
  561.                 if (velocity > 0) {
  562.                     mAnimatedVelocity = 0;
  563.                 }
  564.             }
  565.         }
  566.  
  567.         long now = SystemClock.uptimeMillis();
  568.         mAnimationLastTime = now;
  569.         mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;
  570.         mAnimating = true;
  571.         mHandler.removeMessages(MSG_ANIMATE);
  572.         mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurrentAnimationTime);
  573.         stopTracking();
  574.     }
  575.  
  576.     private void prepareTracking(int position) {
  577.         mTracking = true;
  578.         mVelocityTracker = VelocityTracker.obtain();
  579.         moveHandle(position);
  580.         boolean opening = !mExpanded;
  581.         /*
  582.          * if (opening) { mAnimatedAcceleration = mMaximumAcceleration;
  583.          * mAnimatedVelocity = mMaximumMajorVelocity; mAnimationPosition =
  584.          * mBottomOffset + (mVertical ? getHeight() - mHandleHeight : getWidth()
  585.          * - mHandleWidth); moveHandle((int) mAnimationPosition); mAnimating =
  586.          * true; mHandler.removeMessages(MSG_ANIMATE); long now =
  587.          * SystemClock.uptimeMillis(); mAnimationLastTime = now;
  588.          * mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION; mAnimating =
  589.          * true; } else { if (mAnimating) { mAnimating = false;
  590.          * mHandler.removeMessages(MSG_ANIMATE); } moveHandle(position); }
  591.          */
  592.     }
  593.  
  594.     private void moveHandle(int position) {
  595.         final View handle = mHandle;
  596.         // mContent.setVisibility(View.VISIBLE);
  597.         if (mVertical) {
  598.             if (position == EXPANDED_FULL_OPEN) {
  599.                 handle.offsetTopAndBottom(mTopOffset - handle.getTop());
  600.                 invalidate();
  601.             }
  602.             else if (position == COLLAPSED_FULL_CLOSED) {
  603.                 handle.offsetTopAndBottom(mBottomOffset + getBottom() - getTop() - mHandleHeight - handle.getTop());
  604.                 invalidate();
  605.             }
  606.             else {
  607.                 final int top = handle.getTop();
  608.                 int deltaY = position - top;
  609.                 if (position < mTopOffset) {
  610.                     deltaY = mTopOffset - top;
  611.                 }
  612.                 else if (deltaY > mBottomOffset + getBottom() - getTop() - mHandleHeight - top) {
  613.                     deltaY = mBottomOffset + getBottom() - getTop() - mHandleHeight - top;
  614.                 }
  615.                 handle.offsetTopAndBottom(deltaY);
  616.  
  617.                 final Rect frame = mFrame;
  618.                 final Rect region = mInvalidate;
  619.  
  620.                 handle.getHitRect(frame);
  621.                 region.set(frame);
  622.  
  623.                 region.union(frame.left, frame.top - deltaY, frame.right, frame.bottom - deltaY);
  624.                 region.union(0, frame.bottom - deltaY, getWidth(), frame.bottom - deltaY + mContent.getHeight());
  625.                 // invalidate(region);
  626.                 invalidate();
  627.             }
  628.         }
  629.         else {
  630.             if (position == EXPANDED_FULL_OPEN) {
  631.                 handle.offsetLeftAndRight(mTopOffset - handle.getLeft());
  632.                 invalidate();
  633.             }
  634.             else if (position == COLLAPSED_FULL_CLOSED) {
  635.                 handle.offsetLeftAndRight(mBottomOffset + getRight() - getLeft() - mHandleWidth - handle.getLeft());
  636.                 invalidate();
  637.             }
  638.             else {
  639.                 final int left = handle.getLeft();
  640.                 int deltaX = position - left;
  641.                 if (position < mTopOffset) {
  642.                     deltaX = mTopOffset - left;
  643.                 }
  644.                 else if (deltaX > mBottomOffset + getRight() - getLeft() - mHandleWidth - left) {
  645.                     deltaX = mBottomOffset + getRight() - getLeft() - mHandleWidth - left;
  646.                 }
  647.                 handle.offsetLeftAndRight(deltaX);
  648.  
  649.                 final Rect frame = mFrame;
  650.                 final Rect region = mInvalidate;
  651.  
  652.                 handle.getHitRect(frame);
  653.                 region.set(frame);
  654.  
  655.                 region.union(frame.left - deltaX, frame.top, frame.right - deltaX, frame.bottom);
  656.                 region.union(frame.right - deltaX, 0, frame.right - deltaX + mContent.getWidth(), getHeight());
  657.  
  658.                 invalidate(region);
  659.             }
  660.         }
  661.         if (mOnDrawerScrollListener != null) {
  662.             mOnDrawerScrollListener.onScrolling(mHandle.getTop(), false);
  663.         }
  664.         requestLayout();
  665.         mContent.setVisibility(View.VISIBLE);
  666.     }
  667.  
  668.     private void prepareContent() {
  669.  
  670.         // if (inBetween) { return; }
  671.  
  672.         // Something changed in the content, we need to honor the layout request
  673.         // before creating the cached bitmap
  674.         final View content = mContent;
  675.         if (content.isLayoutRequested()) {
  676.             if (mVertical) {
  677.                 final int childHeight = mHandleHeight;
  678.                 int height = getBottom() - getTop() - childHeight - mTopOffset;
  679.                 content.measure(MeasureSpec.makeMeasureSpec(getRight() - getLeft(), MeasureSpec.EXACTLY),
  680.                         MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
  681.                 content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(), mTopOffset + childHeight
  682.                         + content.getMeasuredHeight());
  683.             }
  684.             else {
  685.                 final int childWidth = mHandle.getWidth();
  686.                 int width = getRight() - getLeft() - childWidth - mTopOffset;
  687.                 content.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
  688.                         getBottom() - getTop(), MeasureSpec.EXACTLY));
  689.                 content.layout(childWidth + mTopOffset, 0, mTopOffset + childWidth + content.getMeasuredWidth(),
  690.                         content.getMeasuredHeight());
  691.             }
  692.         }
  693.         // Try only once... we should really loop but it's not a big deal
  694.         // if the draw was cancelled, it will only be temporary anyway
  695.         content.getViewTreeObserver().dispatchOnPreDraw();
  696.         content.buildDrawingCache();
  697.         // if(mHandle.getTop() == (getHeight()-mHandle.getHeight()) ||
  698.         // mHandle.getTop() < (getHeight()-mHandle.getHeight())){
  699.  
  700.         // content.setVisibility(View.GONE);
  701.         content.setVisibility(View.VISIBLE);
  702.         // Animation animation = AnimationUtils.loadAnimation(cntxt,
  703.         // android.R.anim.fade_out);
  704.         // content.startAnimation(animation);
  705.  
  706.         // }else{
  707.         // Rect rect = new Rect(content.getLeft(), content.getTop(),
  708.         // content.getRight(), content.getBottom());
  709.         // invalidate(rect);
  710.         // }
  711.  
  712.     }
  713.  
  714.     private void stopTracking() {
  715.         mHandle.setPressed(false);
  716.         mTracking = false;
  717.  
  718.         if (mOnDrawerScrollListener != null) {
  719.             mOnDrawerScrollListener.onScrollEnded();
  720.         }
  721.  
  722.         if (mVelocityTracker != null) {
  723.             mVelocityTracker.recycle();
  724.             mVelocityTracker = null;
  725.         }
  726.     }
  727.  
  728.     private void doAnimation() {
  729.         if (mAnimating) {
  730.             incrementAnimation();
  731.             if (mAnimationPosition >= mBottomOffset + (mVertical ? getHeight() : getWidth()) - 1) {
  732.                 mAnimating = false;
  733.                 closeDrawer();
  734.             }
  735.             else if (mAnimationPosition < mTopOffset) {
  736.                 mAnimating = false;
  737.                 openDrawer();
  738.             }
  739.             else {
  740.  
  741.                 moveHandle((int) mAnimationPosition);
  742.                 mCurrentAnimationTime += ANIMATION_FRAME_DURATION;
  743.                 mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurrentAnimationTime);
  744.  
  745.             }
  746.         }
  747.     }
  748.  
  749.     private void incrementAnimation() {
  750.         long now = SystemClock.uptimeMillis();
  751.         float t = (now - mAnimationLastTime) / 1000.0f; // ms -> s
  752.         final float position = mAnimationPosition;
  753.         final float v = mAnimatedVelocity; // px/s
  754.         final float a = mAnimatedAcceleration; // px/s/s
  755.         mAnimationPosition = position + (v * t) + (0.5f * a * t * t); // px
  756.         mAnimatedVelocity = v + (a * t); // px/s
  757.         mAnimationLastTime = now; // ms
  758.     }
  759.  
  760.     /**
  761.      * Toggles the drawer open and close. Takes effect immediately.
  762.      *
  763.      * @see #open()
  764.      * @see #close()
  765.      * @see #animateClose()
  766.      * @see #animateOpen()
  767.      * @see #animateToggle()
  768.      */
  769.     public void toggle() {
  770.         if (!mExpanded) {
  771.             openDrawer();
  772.         }
  773.         else {
  774.             closeDrawer();
  775.         }
  776.         invalidate();
  777.         requestLayout();
  778.     }
  779.  
  780.     /**
  781.      * Toggles the drawer open and close with an animation.
  782.      *
  783.      * @see #open()
  784.      * @see #close()
  785.      * @see #animateClose()
  786.      * @see #animateOpen()
  787.      * @see #toggle()
  788.      */
  789.     public void animateToggle() {
  790.         if (!mExpanded) {
  791.             // animateOpen();
  792.         }
  793.         else {
  794.             // animateClose();
  795.         }
  796.     }
  797.  
  798.     /**
  799.      * Opens the drawer immediately.
  800.      *
  801.      * @see #toggle()
  802.      * @see #close()
  803.      * @see #animateOpen()
  804.      */
  805.     public void open() {
  806.         mTopOffset = 0;
  807.         openDrawer();
  808.         invalidate();
  809.         requestLayout();
  810.  
  811.         sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
  812.     }
  813.  
  814.     /**
  815.      * Closes the drawer immediately.
  816.      *
  817.      * @see #toggle()
  818.      * @see #open()
  819.      * @see #animateClose()
  820.      */
  821.     public void close() {
  822.         closeDrawer();
  823.         invalidate();
  824.         requestLayout();
  825.     }
  826.  
  827.     /**
  828.      * Closes the drawer with an animation.
  829.      *
  830.      * @see #close()
  831.      * @see #open()
  832.      * @see #animateOpen()
  833.      * @see #animateToggle()
  834.      * @see #toggle()
  835.      */
  836.     public void animateClose() {
  837.         prepareContent();
  838.         final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener;
  839.         if (scrollListener != null) {
  840.             scrollListener.onScrollStarted();
  841.         }
  842.         animateClose(mVertical ? mHandle.getTop() : mHandle.getLeft());
  843.  
  844.         if (scrollListener != null) {
  845.             scrollListener.onScrollEnded();
  846.         }
  847.     }
  848.  
  849.     /**
  850.      * Opens the drawer with an animation.
  851.      *
  852.      * @see #close()
  853.      * @see #open()
  854.      * @see #animateClose()
  855.      * @see #animateToggle()
  856.      * @see #toggle()
  857.      */
  858.     public void animateOpen() {
  859.         prepareContent();
  860.         final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener;
  861.         if (scrollListener != null) {
  862.             scrollListener.onScrollStarted();
  863.         }
  864.         animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft());
  865.  
  866.         sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
  867.  
  868.         if (scrollListener != null) {
  869.             scrollListener.onScrollEnded();
  870.         }
  871.     }
  872.  
  873.     private void closeDrawer() {
  874.         moveHandle(COLLAPSED_FULL_CLOSED);
  875.         mContent.setVisibility(View.GONE);
  876.         mContent.destroyDrawingCache();
  877.  
  878.         if (!mExpanded) {
  879.             return;
  880.         }
  881.  
  882.         mExpanded = false;
  883.         if (mOnDrawerCloseListener != null) {
  884.             mOnDrawerCloseListener.onDrawerClosed();
  885.         }
  886.     }
  887.  
  888.     private void openDrawer() {
  889.         // moveHandle(EXPANDED_FULL_OPEN);
  890.         // Animation animation = AnimationUtils.loadAnimation(cntxt,
  891.         // android.R.anim.fade_out);
  892.         // mContent.startAnimation(animation);
  893.         mContent.setVisibility(View.VISIBLE);
  894.  
  895.         if (mExpanded) {
  896.             return;
  897.         }
  898.  
  899.         mExpanded = true;
  900.  
  901.         if (mOnDrawerOpenListener != null) {
  902.             mOnDrawerOpenListener.onDrawerOpened();
  903.         }
  904.     }
  905.  
  906.     /**
  907.      * Sets the listener that receives a notification when the drawer becomes
  908.      * open.
  909.      *
  910.      * @param onDrawerOpenListener
  911.      *            The listener to be notified when the drawer is opened.
  912.      */
  913.     public void setOnDrawerOpenListener(OnDrawerOpenListener onDrawerOpenListener) {
  914.         mOnDrawerOpenListener = onDrawerOpenListener;
  915.     }
  916.  
  917.     /**
  918.      * Sets the listener that receives a notification when the drawer becomes
  919.      * close.
  920.      *
  921.      * @param onDrawerCloseListener
  922.      *            The listener to be notified when the drawer is closed.
  923.      */
  924.     public void setOnDrawerCloseListener(OnDrawerCloseListener onDrawerCloseListener) {
  925.         mOnDrawerCloseListener = onDrawerCloseListener;
  926.     }
  927.  
  928.     /**
  929.      * Sets the listener that receives a notification when the drawer starts or
  930.      * ends a scroll. A fling is considered as a scroll. A fling will also
  931.      * trigger a drawer opened or drawer closed event.
  932.      *
  933.      * @param onDrawerScrollListener
  934.      *            The listener to be notified when scrolling starts or stops.
  935.      */
  936.     public void setOnDrawerScrollListener(OnDrawerScrollListener onDrawerScrollListener) {
  937.         mOnDrawerScrollListener = onDrawerScrollListener;
  938.     }
  939.  
  940.     /**
  941.      * Returns the handle of the drawer.
  942.      *
  943.      * @return The View reprenseting the handle of the drawer, identified by the
  944.      *         "handle" id in XML.
  945.      */
  946.     public View getHandle() {
  947.         return mHandle;
  948.     }
  949.  
  950.     /**
  951.      * Returns the content of the drawer.
  952.      *
  953.      * @return The View reprenseting the content of the drawer, identified by
  954.      *         the "content" id in XML.
  955.      */
  956.     public View getContent() {
  957.         return mContent;
  958.     }
  959.  
  960.     /**
  961.      * Unlocks the SlidingDrawer so that touch events are processed.
  962.      *
  963.      * @see #lock()
  964.      */
  965.     public void unlock() {
  966.         mLocked = false;
  967.     }
  968.  
  969.     /**
  970.      * Locks the SlidingDrawer so that touch events are ignores.
  971.      *
  972.      * @see #unlock()
  973.      */
  974.     public void lock() {
  975.         mLocked = true;
  976.     }
  977.  
  978.     /**
  979.      * Indicates whether the drawer is currently fully opened.
  980.      *
  981.      * @return True if the drawer is opened, false otherwise.
  982.      */
  983.     public boolean isOpened() {
  984.         return mExpanded;
  985.     }
  986.  
  987.     /**
  988.      * Indicates whether the drawer is scrolling or flinging.
  989.      *
  990.      * @return True if the drawer is scroller or flinging, false otherwise.
  991.      */
  992.     public boolean isMoving() {
  993.         return mTracking || mAnimating;
  994.     }
  995.  
  996.     private class DrawerToggler implements OnClickListener {
  997.         public void onClick(View v) {
  998.             if (mLocked) {
  999.                 return;
  1000.             }
  1001.             // mAllowSingleTap isn't relevant here; you're *always*
  1002.             // allowed to open/close the drawer by clicking with the
  1003.             // trackball.
  1004.  
  1005.             if (mAnimateOnClick) {
  1006.                 animateToggle();
  1007.             }
  1008.             else {
  1009.                 toggle();
  1010.             }
  1011.         }
  1012.     }
  1013.  
  1014.     private class SlidingHandler extends Handler {
  1015.         public void handleMessage(Message m) {
  1016.             switch (m.what) {
  1017.                 case MSG_ANIMATE:
  1018.                     doAnimation();
  1019.                     break;
  1020.             }
  1021.         }
  1022.     }
  1023.  
  1024.     public int getmTopOffset() {
  1025.         return mTopOffset;
  1026.     }
  1027.  
  1028.     public void setmTopOffset(int mTopOffset) {
  1029.         this.mTopOffset = mTopOffset;
  1030.     }
  1031.  
  1032.     /**
  1033.      * opens drawer upto an extent such that only one item in listview will be
  1034.      * visible
  1035.      */
  1036.     public void openDefault() {
  1037.         if (listView != null) {
  1038.             if (listView.getChildCount() > 0) {
  1039.                 View v = listView.getChildAt(0);
  1040.                 System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^ open default sliding drawer height ^^^^^^^^^^^^^^^^^^^^^ "
  1041.                         + getHeight());
  1042.                 mTopOffset = getHeight() - (v.getHeight() + mHandle.getHeight() + 10);
  1043.                 openDrawer();
  1044.                 requestLayout();
  1045.             }
  1046.             else {
  1047.                 // if listview doesn't contain any items
  1048.             }
  1049.         }
  1050.     }
  1051.  
  1052.     /**
  1053.      * this will open the drawer upto the specified no of pixels this is
  1054.      * specially written for global talk
  1055.      */
  1056.     public void setMtopOffset(int topOffset) {
  1057.         mTopOffset = Math.abs(topOffset);
  1058.         // int offset = (int) topOffset;
  1059.         // mTopOffset = getHeight()- offset;
  1060.         // System.out.println("%%%%%%%%%%%%%%%%%% height of sliding drawer %%%%%%%%%%%%%%%%% "+getHeight());
  1061.         // openDrawer();
  1062.         // requestLayout();
  1063.     }
  1064.  
  1065.     /**
  1066.      * fully opens the drawer with specified mTopoffset
  1067.      *
  1068.      * @arg mTopOffset of Handle
  1069.      * @arg fromOnattWindw true if called from on attached to window callback of
  1070.      *      activity otherwis false
  1071.      *
  1072.      *      if topOffset is 0 then drawer is fully opened and as we increase
  1073.      *      topOffset then drawer starts closing. if fromOnattWindw is true then
  1074.      *      Avoid doing calculations in onscrolling callback since we dont get
  1075.      *      the proper height and width of sliding drawer and its contents.
  1076.      */
  1077.     public void openUpto(int topOffset, boolean fromOnattWindw) {
  1078.         mTopOffset = topOffset;
  1079.         openDrawer();
  1080.         requestLayout();
  1081.         if (mOnDrawerScrollListener != null) {
  1082.             // mOnDrawerScrollListener.onScrollStarted();
  1083.             mOnDrawerScrollListener.onScrolling(mTopOffset, fromOnattWindw);
  1084.             // mOnDrawerScrollListener.onScrollEnded();
  1085.         }
  1086.         // invalidate();
  1087.  
  1088.     }
  1089.  
  1090.     public ListView getListView() {
  1091.         return listView;
  1092.     }
  1093.  
  1094.     public void setListView(ListView listView) {
  1095.         this.listView = listView;
  1096.     }
  1097.  
  1098.     public boolean isLockedCanNotCloseMore() {
  1099.         return lockedCanNotCloseMore;
  1100.     }
  1101.  
  1102.     public boolean isLockedCanNotOpenMore() {
  1103.         return lockedCanNotOpenMore;
  1104.     }
  1105.  
  1106.     public int getCloseUpto() {
  1107.         return closeUpto;
  1108.     }
  1109.  
  1110.     public int getOpenUpto() {
  1111.         return openUpto;
  1112.     }
  1113.  
  1114.     public void setLockedCanNotCloseMore(boolean lockedCanNotCloseMore) {
  1115.         this.lockedCanNotCloseMore = lockedCanNotCloseMore;
  1116.     }
  1117.  
  1118.     public void setLockedCanNotOpenMore(boolean lockedCanNotOpenMore) {
  1119.         this.lockedCanNotOpenMore = lockedCanNotOpenMore;
  1120.     }
  1121.  
  1122.     public void setCloseUpto(int closeUpto) {
  1123.         this.closeUpto = closeUpto;
  1124.     }
  1125.  
  1126.     public void setOpenUpto(int openUpto) {
  1127.         this.openUpto = openUpto;
  1128.     }
  1129.  
  1130. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement