diff options
| author | Alex Cruz <mazda@UnicornBox.(none)> | 2014-03-01 07:49:32 -0600 |
|---|---|---|
| committer | LorDClockaN <davor@losinj.com> | 2014-03-16 15:50:49 +0100 |
| commit | b5787669c7905e9d2c04f0ec89b72ae8a0e017c5 (patch) | |
| tree | f1455592eb5d9302f1eb4078dcac6c453f57ac47 | |
| parent | d8ffc2e5f82cc63ed09a346a7c4b7597c06add4e (diff) | |
Add necessary libs
Change-Id: Ic48a2fdfbcc9d8234fbda6b9af59a1db737bf65b
16 files changed, 3509 insertions, 6 deletions
@@ -1,14 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="src" path="gen"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> - <classpathentry exported="true" kind="lib" path="/Users/francesco/sdk/extras/android/support/v4/android-support-v4.jar"/> + <classpathentry exported="true" kind="lib" path="libs/android-support-v4.jar"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> - <classpathentry exported="true" kind="lib" path="/Users/francesco/sdk/build-tools/android-4.4/renderscript/lib/renderscript-v8.jar"/> - <classpathentry exported="true" kind="lib" path="/Users/francesco/Documents/lib/GoogleAnalyticsServicesAndroid_3.01/libGoogleAnalyticsServices.jar"/> - <classpathentry exported="true" kind="lib" path="/Users/francesco/Documents/lib/RootTools-3.3.jar"/> + <classpathentry exported="true" kind="lib" path="libs/renderscript-v8.jar"/> + <classpathentry exported="true" kind="lib" path="libs/RootTools-3.3.jar"/> + <classpathentry exported="true" kind="lib" path="libs/libGoogleAnalyticsServices.jar"/> <classpathentry exported="true" kind="lib" path="libs/nineoldandroids-2.4.0.jar"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/libs/RootTools-3.3.jar b/libs/RootTools-3.3.jar Binary files differnew file mode 100644 index 0000000..fc9419c --- /dev/null +++ b/libs/RootTools-3.3.jar diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar Binary files differnew file mode 100644 index 0000000..96644ed --- /dev/null +++ b/libs/android-support-v4.jar diff --git a/libs/libGoogleAnalyticsServices.jar b/libs/libGoogleAnalyticsServices.jar Binary files differnew file mode 100644 index 0000000..b7aac9f --- /dev/null +++ b/libs/libGoogleAnalyticsServices.jar diff --git a/libs/renderscript-v8.jar b/libs/renderscript-v8.jar Binary files differnew file mode 100644 index 0000000..8b07b19 --- /dev/null +++ b/libs/renderscript-v8.jar diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/CanvasTransformerBuilder.java b/src/com/jeremyfeinstein/slidingmenu/lib/CanvasTransformerBuilder.java new file mode 100644 index 0000000..e17ca04 --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/CanvasTransformerBuilder.java @@ -0,0 +1,95 @@ +package com.jeremyfeinstein.slidingmenu.lib; + +import android.graphics.Canvas; +import android.view.animation.Interpolator; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer; + +public class CanvasTransformerBuilder { + + private CanvasTransformer mTrans; + + private static Interpolator lin = new Interpolator() { + public float getInterpolation(float t) { + return t; + } + }; + + private void initTransformer() { + if (mTrans == null) + mTrans = new CanvasTransformer() { + public void transformCanvas(Canvas canvas, float percentOpen) { } + }; + } + + public CanvasTransformer zoom(final int openedX, final int closedX, + final int openedY, final int closedY, + final int px, final int py) { + return zoom(openedX, closedX, openedY, closedY, px, py, lin); + } + + public CanvasTransformer zoom(final int openedX, final int closedX, + final int openedY, final int closedY, + final int px, final int py, final Interpolator interp) { + initTransformer(); + mTrans = new CanvasTransformer() { + public void transformCanvas(Canvas canvas, float percentOpen) { + mTrans.transformCanvas(canvas, percentOpen); + float f = interp.getInterpolation(percentOpen); + canvas.scale((openedX - closedX) * f + closedX, + (openedY - closedY) * f + closedY, px, py); + } + }; + return mTrans; + } + + public CanvasTransformer rotate(final int openedDeg, final int closedDeg, + final int px, final int py) { + return rotate(openedDeg, closedDeg, px, py, lin); + } + + public CanvasTransformer rotate(final int openedDeg, final int closedDeg, + final int px, final int py, final Interpolator interp) { + initTransformer(); + mTrans = new CanvasTransformer() { + public void transformCanvas(Canvas canvas, float percentOpen) { + mTrans.transformCanvas(canvas, percentOpen); + float f = interp.getInterpolation(percentOpen); + canvas.rotate((openedDeg - closedDeg) * f + closedDeg, + px, py); + } + }; + return mTrans; + } + + public CanvasTransformer translate(final int openedX, final int closedX, + final int openedY, final int closedY) { + return translate(openedX, closedX, openedY, closedY, lin); + } + + public CanvasTransformer translate(final int openedX, final int closedX, + final int openedY, final int closedY, final Interpolator interp) { + initTransformer(); + mTrans = new CanvasTransformer() { + public void transformCanvas(Canvas canvas, float percentOpen) { + mTrans.transformCanvas(canvas, percentOpen); + float f = interp.getInterpolation(percentOpen); + canvas.translate((openedX - closedX) * f + closedX, + (openedY - closedY) * f + closedY); + } + }; + return mTrans; + } + + public CanvasTransformer concatTransformer(final CanvasTransformer t) { + initTransformer(); + mTrans = new CanvasTransformer() { + public void transformCanvas(Canvas canvas, float percentOpen) { + mTrans.transformCanvas(canvas, percentOpen); + t.transformCanvas(canvas, percentOpen); + } + }; + return mTrans; + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/CustomViewAbove.java b/src/com/jeremyfeinstein/slidingmenu/lib/CustomViewAbove.java new file mode 100644 index 0000000..fa73ef0 --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/CustomViewAbove.java @@ -0,0 +1,1007 @@ +package com.jeremyfeinstein.slidingmenu.lib; + +import java.util.ArrayList; +import java.util.List; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.os.Build; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.util.AttributeSet; +import android.util.FloatMath; +import android.util.Log; +import android.view.FocusFinder; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnClosedListener; +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnOpenedListener; +//import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnCloseListener; +//import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnOpenListener; + +public class CustomViewAbove extends ViewGroup { + + private static final String TAG = "CustomViewAbove"; + private static final boolean DEBUG = false; + + private static final boolean USE_CACHE = false; + + private static final int MAX_SETTLE_DURATION = 600; // ms + private static final int MIN_DISTANCE_FOR_FLING = 25; // dips + + private static final Interpolator sInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + private View mContent; + + private int mCurItem; + private Scroller mScroller; + + private boolean mScrollingCacheEnabled; + + private boolean mScrolling; + + private boolean mIsBeingDragged; + private boolean mIsUnableToDrag; + private int mTouchSlop; + private float mInitialMotionX; + /** + * Position of the last motion event. + */ + private float mLastMotionX; + private float mLastMotionY; + /** + * ID of the active pointer. This is used to retain consistency during + * drags/flings if multiple pointers are used. + */ + protected int mActivePointerId = INVALID_POINTER; + /** + * Sentinel value for no current active pointer. + * Used by {@link #mActivePointerId}. + */ + private static final int INVALID_POINTER = -1; + + /** + * Determines speed during touch scrolling + */ + protected VelocityTracker mVelocityTracker; + private int mMinimumVelocity; + protected int mMaximumVelocity; + private int mFlingDistance; + + private CustomViewBehind mViewBehind; + // private int mMode; + private boolean mEnabled = true; + + private OnPageChangeListener mOnPageChangeListener; + private OnPageChangeListener mInternalPageChangeListener; + + // private OnCloseListener mCloseListener; + // private OnOpenListener mOpenListener; + private OnClosedListener mClosedListener; + private OnOpenedListener mOpenedListener; + + private List<View> mIgnoredViews = new ArrayList<View>(); + + // private int mScrollState = SCROLL_STATE_IDLE; + + /** + * Callback interface for responding to changing state of the selected page. + */ + public interface OnPageChangeListener { + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param positionOffset Value from [0, 1) indicating the offset from the page at position. + * @param positionOffsetPixels Value in pixels indicating the offset from position. + */ + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + /** + * This method will be invoked when a new page becomes selected. Animation is not + * necessarily complete. + * + * @param position Position index of the new selected page. + */ + public void onPageSelected(int position); + + } + + /** + * Simple implementation of the {@link OnPageChangeListener} interface with stub + * implementations of each method. Extend this if you do not intend to override + * every method of {@link OnPageChangeListener}. + */ + public static class SimpleOnPageChangeListener implements OnPageChangeListener { + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // This space for rent + } + + public void onPageSelected(int position) { + // This space for rent + } + + public void onPageScrollStateChanged(int state) { + // This space for rent + } + + } + + public CustomViewAbove(Context context) { + this(context, null); + } + + public CustomViewAbove(Context context, AttributeSet attrs) { + super(context, attrs); + initCustomViewAbove(); + } + + void initCustomViewAbove() { + setWillNotDraw(false); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + setFocusable(true); + final Context context = getContext(); + mScroller = new Scroller(context, sInterpolator); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + setInternalPageChangeListener(new SimpleOnPageChangeListener() { + public void onPageSelected(int position) { + if (mViewBehind != null) { + switch (position) { + case 0: + case 2: + mViewBehind.setChildrenEnabled(true); + break; + case 1: + mViewBehind.setChildrenEnabled(false); + break; + } + } + } + }); + + final float density = context.getResources().getDisplayMetrics().density; + mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); + } + + /** + * Set the currently selected page. If the CustomViewPager has already been through its first + * layout there will be a smooth animated transition between the current item and the + * specified item. + * + * @param item Item index to select + */ + public void setCurrentItem(int item) { + setCurrentItemInternal(item, true, false); + } + + /** + * Set the currently selected page. + * + * @param item Item index to select + * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately + */ + public void setCurrentItem(int item, boolean smoothScroll) { + setCurrentItemInternal(item, smoothScroll, false); + } + + public int getCurrentItem() { + return mCurItem; + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { + setCurrentItemInternal(item, smoothScroll, always, 0); + } + + void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { + if (!always && mCurItem == item) { + setScrollingCacheEnabled(false); + return; + } + + item = mViewBehind.getMenuPage(item); + + final boolean dispatchSelected = mCurItem != item; + mCurItem = item; + final int destX = getDestScrollX(mCurItem); + if (dispatchSelected && mOnPageChangeListener != null) { + mOnPageChangeListener.onPageSelected(item); + } + if (dispatchSelected && mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageSelected(item); + } + if (smoothScroll) { + smoothScrollTo(destX, 0, velocity); + } else { + completeScroll(); + scrollTo(destX, 0); + } + } + + /** + * Set a listener that will be invoked whenever the page changes or is incrementally + * scrolled. See {@link OnPageChangeListener}. + * + * @param listener Listener to set + */ + public void setOnPageChangeListener(OnPageChangeListener listener) { + mOnPageChangeListener = listener; + } + /* + public void setOnOpenListener(OnOpenListener l) { + mOpenListener = l; + } + + public void setOnCloseListener(OnCloseListener l) { + mCloseListener = l; + } + */ + public void setOnOpenedListener(OnOpenedListener l) { + mOpenedListener = l; + } + + public void setOnClosedListener(OnClosedListener l) { + mClosedListener = l; + } + + /** + * Set a separate OnPageChangeListener for internal use by the support library. + * + * @param listener Listener to set + * @return The old listener that was set, if any. + */ + OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { + OnPageChangeListener oldListener = mInternalPageChangeListener; + mInternalPageChangeListener = listener; + return oldListener; + } + + public void addIgnoredView(View v) { + if (!mIgnoredViews.contains(v)) { + mIgnoredViews.add(v); + } + } + + public void removeIgnoredView(View v) { + mIgnoredViews.remove(v); + } + + public void clearIgnoredViews() { + mIgnoredViews.clear(); + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) FloatMath.sin(f); + } + + public int getDestScrollX(int page) { + switch (page) { + case 0: + case 2: + return mViewBehind.getMenuLeft(mContent, page); + case 1: + return mContent.getLeft(); + } + return 0; + } + + private int getLeftBound() { + return mViewBehind.getAbsLeftBound(mContent); + } + + private int getRightBound() { + return mViewBehind.getAbsRightBound(mContent); + } + + public int getContentLeft() { + return mContent.getLeft() + mContent.getPaddingLeft(); + } + + public boolean isMenuOpen() { + return mCurItem == 0 || mCurItem == 2; + } + + private boolean isInIgnoredView(MotionEvent ev) { + Rect rect = new Rect(); + for (View v : mIgnoredViews) { + v.getHitRect(rect); + if (rect.contains((int)ev.getX(), (int)ev.getY())) return true; + } + return false; + } + + public int getBehindWidth() { + if (mViewBehind == null) { + return 0; + } else { + return mViewBehind.getBehindWidth(); + } + } + + public int getChildWidth(int i) { + switch (i) { + case 0: + return getBehindWidth(); + case 1: + return mContent.getWidth(); + default: + return 0; + } + } + + public boolean isSlidingEnabled() { + return mEnabled; + } + + public void setSlidingEnabled(boolean b) { + mEnabled = b; + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + */ + void smoothScrollTo(int x, int y) { + smoothScrollTo(x, y, 0); + } + + /** + * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. + * + * @param x the number of pixels to scroll by on the X axis + * @param y the number of pixels to scroll by on the Y axis + * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) + */ + void smoothScrollTo(int x, int y, int velocity) { + if (getChildCount() == 0) { + // Nothing to do. + setScrollingCacheEnabled(false); + return; + } + int sx = getScrollX(); + int sy = getScrollY(); + int dx = x - sx; + int dy = y - sy; + if (dx == 0 && dy == 0) { + completeScroll(); + if (isMenuOpen()) { + if (mOpenedListener != null) + mOpenedListener.onOpened(); + } else { + if (mClosedListener != null) + mClosedListener.onClosed(); + } + return; + } + + setScrollingCacheEnabled(true); + mScrolling = true; + + final int width = getBehindWidth(); + final int halfWidth = width / 2; + final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); + final float distance = halfWidth + halfWidth * + distanceInfluenceForSnapDuration(distanceRatio); + + int duration = 0; + velocity = Math.abs(velocity); + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); + } else { + final float pageDelta = (float) Math.abs(dx) / width; + duration = (int) ((pageDelta + 1) * 100); + duration = MAX_SETTLE_DURATION; + } + duration = Math.min(duration, MAX_SETTLE_DURATION); + + mScroller.startScroll(sx, sy, dx, dy, duration); + invalidate(); + } + + public void setContent(View v) { + if (mContent != null) + this.removeView(mContent); + mContent = v; + addView(mContent); + } + + public View getContent() { + return mContent; + } + + public void setCustomViewBehind(CustomViewBehind cvb) { + mViewBehind = cvb; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + + final int contentWidth = getChildMeasureSpec(widthMeasureSpec, 0, width); + final int contentHeight = getChildMeasureSpec(heightMeasureSpec, 0, height); + mContent.measure(contentWidth, contentHeight); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + // Make sure scroll position is set correctly. + if (w != oldw) { + // [ChrisJ] - This fixes the onConfiguration change for orientation issue.. + // maybe worth having a look why the recomputeScroll pos is screwing + // up? + completeScroll(); + scrollTo(getDestScrollX(mCurItem), getScrollY()); + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int width = r - l; + final int height = b - t; + mContent.layout(0, 0, width, height); + } + + public void setAboveOffset(int i) { + // RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mContent.getLayoutParams()); + // params.setMargins(i, params.topMargin, params.rightMargin, params.bottomMargin); + mContent.setPadding(i, mContent.getPaddingTop(), + mContent.getPaddingRight(), mContent.getPaddingBottom()); + } + + + @Override + public void computeScroll() { + if (!mScroller.isFinished()) { + if (mScroller.computeScrollOffset()) { + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + + if (oldX != x || oldY != y) { + scrollTo(x, y); + pageScrolled(x); + } + + // Keep on drawing until the animation has finished. + invalidate(); + return; + } + } + + // Done with scroll, clean up state. + completeScroll(); + } + + private void pageScrolled(int xpos) { + final int widthWithMargin = getWidth(); + final int position = xpos / widthWithMargin; + final int offsetPixels = xpos % widthWithMargin; + final float offset = (float) offsetPixels / widthWithMargin; + + onPageScrolled(position, offset, offsetPixels); + } + + /** + * This method will be invoked when the current page is scrolled, either as part + * of a programmatically initiated smooth scroll or a user initiated touch scroll. + * If you override this method you must call through to the superclass implementation + * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled + * returns. + * + * @param position Position index of the first page currently being displayed. + * Page position+1 will be visible if positionOffset is nonzero. + * @param offset Value from [0, 1) indicating the offset from the page at position. + * @param offsetPixels Value in pixels indicating the offset from position. + */ + protected void onPageScrolled(int position, float offset, int offsetPixels) { + if (mOnPageChangeListener != null) { + mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + if (mInternalPageChangeListener != null) { + mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); + } + } + + private void completeScroll() { + boolean needPopulate = mScrolling; + if (needPopulate) { + // Done with scroll, no longer want to cache view drawing. + setScrollingCacheEnabled(false); + mScroller.abortAnimation(); + int oldX = getScrollX(); + int oldY = getScrollY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); + if (oldX != x || oldY != y) { + scrollTo(x, y); + } + if (isMenuOpen()) { + if (mOpenedListener != null) + mOpenedListener.onOpened(); + } else { + if (mClosedListener != null) + mClosedListener.onClosed(); + } + } + mScrolling = false; + } + + protected int mTouchMode = SlidingMenu.TOUCHMODE_MARGIN; + + public void setTouchMode(int i) { + mTouchMode = i; + } + + public int getTouchMode() { + return mTouchMode; + } + + private boolean thisTouchAllowed(MotionEvent ev) { + int x = (int) (ev.getX() + mScrollX); + if (isMenuOpen()) { + return mViewBehind.menuOpenTouchAllowed(mContent, mCurItem, x); + } else { + switch (mTouchMode) { + case SlidingMenu.TOUCHMODE_FULLSCREEN: + return !isInIgnoredView(ev); + case SlidingMenu.TOUCHMODE_NONE: + return false; + case SlidingMenu.TOUCHMODE_MARGIN: + return mViewBehind.marginTouchAllowed(mContent, x); + } + } + return false; + } + + private boolean thisSlideAllowed(float dx) { + boolean allowed = false; + if (isMenuOpen()) { + allowed = mViewBehind.menuOpenSlideAllowed(dx); + } else { + allowed = mViewBehind.menuClosedSlideAllowed(dx); + } + if (DEBUG) + Log.v(TAG, "this slide allowed " + allowed + " dx: " + dx); + return allowed; + } + + private int getPointerIndex(MotionEvent ev, int id) { + int activePointerIndex = MotionEventCompat.findPointerIndex(ev, id); + if (activePointerIndex == -1) + mActivePointerId = INVALID_POINTER; + return activePointerIndex; + } + + private boolean mQuickReturn = false; + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + + if (!mEnabled) + return false; + + final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; + + if (DEBUG) + if (action == MotionEvent.ACTION_DOWN) + Log.v(TAG, "Received ACTION_DOWN"); + + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP + || (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) { + endDrag(); + return false; + } + + switch (action) { + case MotionEvent.ACTION_MOVE: + determineDrag(ev); + break; + case MotionEvent.ACTION_DOWN: + int index = MotionEventCompat.getActionIndex(ev); + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + if (mActivePointerId == INVALID_POINTER) + break; + mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, index); + mLastMotionY = MotionEventCompat.getY(ev, index); + if (thisTouchAllowed(ev)) { + mIsBeingDragged = false; + mIsUnableToDrag = false; + if (isMenuOpen() && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) { + mQuickReturn = true; + } + } else { + mIsUnableToDrag = true; + } + break; + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + break; + } + + if (!mIsBeingDragged) { + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + } + return mIsBeingDragged || mQuickReturn; + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) { + + if (!mEnabled) + return false; + + if (!mIsBeingDragged && !thisTouchAllowed(ev)) + return false; + + // if (!mIsBeingDragged && !mQuickReturn) + // return false; + + final int action = ev.getAction(); + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + completeScroll(); + + // Remember where the motion event started + int index = MotionEventCompat.getActionIndex(ev); + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + mLastMotionX = mInitialMotionX = ev.getX(); + break; + case MotionEvent.ACTION_MOVE: + if (!mIsBeingDragged) { + determineDrag(ev); + if (mIsUnableToDrag) + return false; + } + if (mIsBeingDragged) { + // Scroll to follow the motion event + final int activePointerIndex = getPointerIndex(ev, mActivePointerId); + if (mActivePointerId == INVALID_POINTER) + break; + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = mLastMotionX - x; + mLastMotionX = x; + float oldScrollX = getScrollX(); + float scrollX = oldScrollX + deltaX; + final float leftBound = getLeftBound(); + final float rightBound = getRightBound(); + if (scrollX < leftBound) { + scrollX = leftBound; + } else if (scrollX > rightBound) { + scrollX = rightBound; + } + // Don't lose the rounded component + mLastMotionX += scrollX - (int) scrollX; + scrollTo((int) scrollX, getScrollY()); + pageScrolled((int) scrollX); + } + break; + case MotionEvent.ACTION_UP: + if (mIsBeingDragged) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( + velocityTracker, mActivePointerId); + final int scrollX = getScrollX(); + final float pageOffset = (float) (scrollX - getDestScrollX(mCurItem)) / getBehindWidth(); + final int activePointerIndex = getPointerIndex(ev, mActivePointerId); + if (mActivePointerId != INVALID_POINTER) { + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final int totalDelta = (int) (x - mInitialMotionX); + int nextPage = determineTargetPage(pageOffset, initialVelocity, totalDelta); + setCurrentItemInternal(nextPage, true, true, initialVelocity); + } else { + setCurrentItemInternal(mCurItem, true, true, initialVelocity); + } + mActivePointerId = INVALID_POINTER; + endDrag(); + } else if (mQuickReturn && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) { + // close the menu + setCurrentItem(1); + endDrag(); + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsBeingDragged) { + setCurrentItemInternal(mCurItem, true, true); + mActivePointerId = INVALID_POINTER; + endDrag(); + } + break; + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int indexx = MotionEventCompat.getActionIndex(ev); + mLastMotionX = MotionEventCompat.getX(ev, indexx); + mActivePointerId = MotionEventCompat.getPointerId(ev, indexx); + break; + } + case MotionEventCompat.ACTION_POINTER_UP: + onSecondaryPointerUp(ev); + int pointerIndex = getPointerIndex(ev, mActivePointerId); + if (mActivePointerId == INVALID_POINTER) + break; + mLastMotionX = MotionEventCompat.getX(ev, pointerIndex); + break; + } + return true; + } + + private void determineDrag(MotionEvent ev) { + final int activePointerId = mActivePointerId; + final int pointerIndex = getPointerIndex(ev, activePointerId); + if (activePointerId == INVALID_POINTER || pointerIndex == INVALID_POINTER) + return; + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float dx = x - mLastMotionX; + final float xDiff = Math.abs(dx); + final float y = MotionEventCompat.getY(ev, pointerIndex); + final float dy = y - mLastMotionY; + final float yDiff = Math.abs(dy); + if (xDiff > (isMenuOpen()?mTouchSlop/2:mTouchSlop) && xDiff > yDiff && thisSlideAllowed(dx)) { + startDrag(); + mLastMotionX = x; + mLastMotionY = y; + setScrollingCacheEnabled(true); + // TODO add back in touch slop check + } else if (xDiff > mTouchSlop) { + mIsUnableToDrag = true; + } + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + mScrollX = x; + mViewBehind.scrollBehindTo(mContent, x, y); + ((SlidingMenu)getParent()).manageLayers(getPercentOpen()); + } + + private int determineTargetPage(float pageOffset, int velocity, int deltaX) { + int targetPage = mCurItem; + if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + if (velocity > 0 && deltaX > 0) { + targetPage -= 1; + } else if (velocity < 0 && deltaX < 0){ + targetPage += 1; + } + } else { + targetPage = (int) Math.round(mCurItem + pageOffset); + } + return targetPage; + } + + protected float getPercentOpen() { + return Math.abs(mScrollX-mContent.getLeft()) / getBehindWidth(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + // Draw the margin drawable if needed. + mViewBehind.drawShadow(mContent, canvas); + mViewBehind.drawFade(mContent, canvas, getPercentOpen()); + mViewBehind.drawSelector(mContent, canvas, getPercentOpen()); + } + + // variables for drawing + private float mScrollX = 0.0f; + + private void onSecondaryPointerUp(MotionEvent ev) { + if (DEBUG) Log.v(TAG, "onSecondaryPointerUp called"); + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + } + } + } + + private void startDrag() { + mIsBeingDragged = true; + mQuickReturn = false; + } + + private void endDrag() { + mQuickReturn = false; + mIsBeingDragged = false; + mIsUnableToDrag = false; + mActivePointerId = INVALID_POINTER; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void setScrollingCacheEnabled(boolean enabled) { + if (mScrollingCacheEnabled != enabled) { + mScrollingCacheEnabled = enabled; + if (USE_CACHE) { + final int size = getChildCount(); + for (int i = 0; i < size; ++i) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + child.setDrawingCacheEnabled(enabled); + } + } + } + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + return true; + } + } + } + + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + // Let the focused view and/or our descendants get the key first + return super.dispatchKeyEvent(event) || executeKeyEvent(event); + } + + /** + * You can call this function yourself to have the scroll view perform + * scrolling from a key event, just as if the event had been dispatched to + * it by the view hierarchy. + * + * @param event The key event to execute. + * @return Return true if the event was handled, else false. + */ + public boolean executeKeyEvent(KeyEvent event) { + boolean handled = false; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = arrowScroll(FOCUS_LEFT); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = arrowScroll(FOCUS_RIGHT); + break; + case KeyEvent.KEYCODE_TAB: + if (Build.VERSION.SDK_INT >= 11) { + // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD + // before Android 3.0. Ignore the tab key on those devices. + if (KeyEventCompat.hasNoModifiers(event)) { + handled = arrowScroll(FOCUS_FORWARD); + } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { + handled = arrowScroll(FOCUS_BACKWARD); + } + } + break; + } + } + return handled; + } + + public boolean arrowScroll(int direction) { + View currentFocused = findFocus(); + if (currentFocused == this) currentFocused = null; + + boolean handled = false; + + View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, + direction); + if (nextFocused != null && nextFocused != currentFocused) { + if (direction == View.FOCUS_LEFT) { + handled = nextFocused.requestFocus(); + } else if (direction == View.FOCUS_RIGHT) { + // If there is nothing to the right, or this is causing us to + // jump to the left, then what we really want to do is page right. + if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) { + handled = pageRight(); + } else { + handled = nextFocused.requestFocus(); + } + } + } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { + // Trying to move left and nothing there; try to page. + handled = pageLeft(); + } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { + // Trying to move right and nothing there; try to page. + handled = pageRight(); + } + if (handled) { + playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); + } + return handled; + } + + boolean pageLeft() { + if (mCurItem > 0) { + setCurrentItem(mCurItem-1, true); + return true; + } + return false; + } + + boolean pageRight() { + if (mCurItem < 1) { + setCurrentItem(mCurItem+1, true); + return true; + } + return false; + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/CustomViewBehind.java b/src/com/jeremyfeinstein/slidingmenu/lib/CustomViewBehind.java new file mode 100644 index 0000000..fa0544d --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/CustomViewBehind.java @@ -0,0 +1,439 @@ +package com.jeremyfeinstein.slidingmenu.lib; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer; + +public class CustomViewBehind extends ViewGroup { + + private static final String TAG = "CustomViewBehind"; + + private static final int MARGIN_THRESHOLD = 48; // dips + private int mTouchMode = SlidingMenu.TOUCHMODE_MARGIN; + + private CustomViewAbove mViewAbove; + + private View mContent; + private View mSecondaryContent; + private int mMarginThreshold; + private int mWidthOffset; + private CanvasTransformer mTransformer; + private boolean mChildrenEnabled; + + public CustomViewBehind(Context context) { + this(context, null); + } + + public CustomViewBehind(Context context, AttributeSet attrs) { + super(context, attrs); + mMarginThreshold = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + MARGIN_THRESHOLD, getResources().getDisplayMetrics()); + } + + public void setCustomViewAbove(CustomViewAbove customViewAbove) { + mViewAbove = customViewAbove; + } + + public void setCanvasTransformer(CanvasTransformer t) { + mTransformer = t; + } + + public void setWidthOffset(int i) { + mWidthOffset = i; + requestLayout(); + } + + public void setMarginThreshold(int marginThreshold) { + mMarginThreshold = marginThreshold; + } + + public int getMarginThreshold() { + return mMarginThreshold; + } + + public int getBehindWidth() { + return mContent.getWidth(); + } + + public void setContent(View v) { + if (mContent != null) + removeView(mContent); + mContent = v; + addView(mContent); + } + + public View getContent() { + return mContent; + } + + /** + * Sets the secondary (right) menu for use when setMode is called with SlidingMenu.LEFT_RIGHT. + * @param v the right menu + */ + public void setSecondaryContent(View v) { + if (mSecondaryContent != null) + removeView(mSecondaryContent); + mSecondaryContent = v; + addView(mSecondaryContent); + } + + public View getSecondaryContent() { + return mSecondaryContent; + } + + public void setChildrenEnabled(boolean enabled) { + mChildrenEnabled = enabled; + } + + @Override + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + if (mTransformer != null) + invalidate(); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + return !mChildrenEnabled; + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + return !mChildrenEnabled; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (mTransformer != null) { + canvas.save(); + mTransformer.transformCanvas(canvas, mViewAbove.getPercentOpen()); + super.dispatchDraw(canvas); + canvas.restore(); + } else + super.dispatchDraw(canvas); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int width = r - l; + final int height = b - t; + mContent.layout(0, 0, width-mWidthOffset, height); + if (mSecondaryContent != null) + mSecondaryContent.layout(0, 0, width-mWidthOffset, height); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + final int contentWidth = getChildMeasureSpec(widthMeasureSpec, 0, width-mWidthOffset); + final int contentHeight = getChildMeasureSpec(heightMeasureSpec, 0, height); + mContent.measure(contentWidth, contentHeight); + if (mSecondaryContent != null) + mSecondaryContent.measure(contentWidth, contentHeight); + } + + private int mMode; + private boolean mFadeEnabled; + private final Paint mFadePaint = new Paint(); + private float mScrollScale; + private Drawable mShadowDrawable; + private Drawable mSecondaryShadowDrawable; + private int mShadowWidth; + private float mFadeDegree; + + public void setMode(int mode) { + if (mode == SlidingMenu.LEFT || mode == SlidingMenu.RIGHT) { + if (mContent != null) + mContent.setVisibility(View.VISIBLE); + if (mSecondaryContent != null) + mSecondaryContent.setVisibility(View.INVISIBLE); + } + mMode = mode; + } + + public int getMode() { + return mMode; + } + + public void setScrollScale(float scrollScale) { + mScrollScale = scrollScale; + } + + public float getScrollScale() { + return mScrollScale; + } + + public void setShadowDrawable(Drawable shadow) { + mShadowDrawable = shadow; + invalidate(); + } + + public void setSecondaryShadowDrawable(Drawable shadow) { + mSecondaryShadowDrawable = shadow; + invalidate(); + } + + public void setShadowWidth(int width) { + mShadowWidth = width; + invalidate(); + } + + public void setFadeEnabled(boolean b) { + mFadeEnabled = b; + } + + public void setFadeDegree(float degree) { + if (degree > 1.0f || degree < 0.0f) + throw new IllegalStateException("The BehindFadeDegree must be between 0.0f and 1.0f"); + mFadeDegree = degree; + } + + public int getMenuPage(int page) { + page = (page > 1) ? 2 : ((page < 1) ? 0 : page); + if (mMode == SlidingMenu.LEFT && page > 1) { + return 0; + } else if (mMode == SlidingMenu.RIGHT && page < 1) { + return 2; + } else { + return page; + } + } + + public void scrollBehindTo(View content, int x, int y) { + int vis = View.VISIBLE; + if (mMode == SlidingMenu.LEFT) { + if (x >= content.getLeft()) vis = View.INVISIBLE; + scrollTo((int)((x + getBehindWidth())*mScrollScale), y); + } else if (mMode == SlidingMenu.RIGHT) { + if (x <= content.getLeft()) vis = View.INVISIBLE; + scrollTo((int)(getBehindWidth() - getWidth() + + (x-getBehindWidth())*mScrollScale), y); + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + mContent.setVisibility(x >= content.getLeft() ? View.INVISIBLE : View.VISIBLE); + mSecondaryContent.setVisibility(x <= content.getLeft() ? View.INVISIBLE : View.VISIBLE); + vis = x == 0 ? View.INVISIBLE : View.VISIBLE; + if (x <= content.getLeft()) { + scrollTo((int)((x + getBehindWidth())*mScrollScale), y); + } else { + scrollTo((int)(getBehindWidth() - getWidth() + + (x-getBehindWidth())*mScrollScale), y); + } + } + if (vis == View.INVISIBLE) + Log.v(TAG, "behind INVISIBLE"); + setVisibility(vis); + } + + public int getMenuLeft(View content, int page) { + if (mMode == SlidingMenu.LEFT) { + switch (page) { + case 0: + return content.getLeft() - getBehindWidth(); + case 2: + return content.getLeft(); + } + } else if (mMode == SlidingMenu.RIGHT) { + switch (page) { + case 0: + return content.getLeft(); + case 2: + return content.getLeft() + getBehindWidth(); + } + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + switch (page) { + case 0: + return content.getLeft() - getBehindWidth(); + case 2: + return content.getLeft() + getBehindWidth(); + } + } + return content.getLeft(); + } + + public int getAbsLeftBound(View content) { + if (mMode == SlidingMenu.LEFT || mMode == SlidingMenu.LEFT_RIGHT) { + return content.getLeft() - getBehindWidth(); + } else if (mMode == SlidingMenu.RIGHT) { + return content.getLeft(); + } + return 0; + } + + public int getAbsRightBound(View content) { + if (mMode == SlidingMenu.LEFT) { + return content.getLeft(); + } else if (mMode == SlidingMenu.RIGHT || mMode == SlidingMenu.LEFT_RIGHT) { + return content.getLeft() + getBehindWidth(); + } + return 0; + } + + public boolean marginTouchAllowed(View content, int x) { + int left = content.getLeft(); + int right = content.getRight(); + if (mMode == SlidingMenu.LEFT) { + return (x >= left && x <= mMarginThreshold + left); + } else if (mMode == SlidingMenu.RIGHT) { + return (x <= right && x >= right - mMarginThreshold); + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + return (x >= left && x <= mMarginThreshold + left) || + (x <= right && x >= right - mMarginThreshold); + } + return false; + } + + public void setTouchMode(int i) { + mTouchMode = i; + } + + public boolean menuOpenTouchAllowed(View content, int currPage, float x) { + switch (mTouchMode) { + case SlidingMenu.TOUCHMODE_FULLSCREEN: + return true; + case SlidingMenu.TOUCHMODE_MARGIN: + return menuTouchInQuickReturn(content, currPage, x); + } + return false; + } + + public boolean menuTouchInQuickReturn(View content, int currPage, float x) { + if (mMode == SlidingMenu.LEFT || (mMode == SlidingMenu.LEFT_RIGHT && currPage == 0)) { + return x >= content.getLeft(); + } else if (mMode == SlidingMenu.RIGHT || (mMode == SlidingMenu.LEFT_RIGHT && currPage == 2)) { + return x <= content.getRight(); + } + return false; + } + + public boolean menuClosedSlideAllowed(float dx) { + if (mMode == SlidingMenu.LEFT) { + return dx > 0; + } else if (mMode == SlidingMenu.RIGHT) { + return dx < 0; + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + return true; + } + return false; + } + + public boolean menuOpenSlideAllowed(float dx) { + if (mMode == SlidingMenu.LEFT) { + return dx < 0; + } else if (mMode == SlidingMenu.RIGHT) { + return dx > 0; + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + return true; + } + return false; + } + + public void drawShadow(View content, Canvas canvas) { + if (mShadowDrawable == null || mShadowWidth <= 0) return; + int left = 0; + if (mMode == SlidingMenu.LEFT) { + left = content.getLeft() - mShadowWidth; + } else if (mMode == SlidingMenu.RIGHT) { + left = content.getRight(); + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + if (mSecondaryShadowDrawable != null) { + left = content.getRight(); + mSecondaryShadowDrawable.setBounds(left, 0, left + mShadowWidth, getHeight()); + mSecondaryShadowDrawable.draw(canvas); + } + left = content.getLeft() - mShadowWidth; + } + mShadowDrawable.setBounds(left, 0, left + mShadowWidth, getHeight()); + mShadowDrawable.draw(canvas); + } + + public void drawFade(View content, Canvas canvas, float openPercent) { + if (!mFadeEnabled) return; + final int alpha = (int) (mFadeDegree * 255 * Math.abs(1-openPercent)); + mFadePaint.setColor(Color.argb(alpha, 0, 0, 0)); + int left = 0; + int right = 0; + if (mMode == SlidingMenu.LEFT) { + left = content.getLeft() - getBehindWidth(); + right = content.getLeft(); + } else if (mMode == SlidingMenu.RIGHT) { + left = content.getRight(); + right = content.getRight() + getBehindWidth(); + } else if (mMode == SlidingMenu.LEFT_RIGHT) { + left = content.getLeft() - getBehindWidth(); + right = content.getLeft(); + canvas.drawRect(left, 0, right, getHeight(), mFadePaint); + left = content.getRight(); + right = content.getRight() + getBehindWidth(); + } + canvas.drawRect(left, 0, right, getHeight(), mFadePaint); + } + + private boolean mSelectorEnabled = true; + private Bitmap mSelectorDrawable; + private View mSelectedView; + + public void drawSelector(View content, Canvas canvas, float openPercent) { + if (!mSelectorEnabled) return; + if (mSelectorDrawable != null && mSelectedView != null) { + String tag = (String) mSelectedView.getTag(R.id.selected_view); + if (tag.equals(TAG+"SelectedView")) { + canvas.save(); + int left, right, offset; + offset = (int) (mSelectorDrawable.getWidth() * openPercent); + if (mMode == SlidingMenu.LEFT) { + right = content.getLeft(); + left = right - offset; + canvas.clipRect(left, 0, right, getHeight()); + canvas.drawBitmap(mSelectorDrawable, left, getSelectorTop(), null); + } else if (mMode == SlidingMenu.RIGHT) { + left = content.getRight(); + right = left + offset; + canvas.clipRect(left, 0, right, getHeight()); + canvas.drawBitmap(mSelectorDrawable, right - mSelectorDrawable.getWidth(), getSelectorTop(), null); + } + canvas.restore(); + } + } + } + + public void setSelectorEnabled(boolean b) { + mSelectorEnabled = b; + } + + public void setSelectedView(View v) { + if (mSelectedView != null) { + mSelectedView.setTag(R.id.selected_view, null); + mSelectedView = null; + } + if (v != null && v.getParent() != null) { + mSelectedView = v; + mSelectedView.setTag(R.id.selected_view, TAG+"SelectedView"); + invalidate(); + } + } + + private int getSelectorTop() { + int y = mSelectedView.getTop(); + y += (mSelectedView.getHeight() - mSelectorDrawable.getHeight()) / 2; + return y; + } + + public void setSelectorBitmap(Bitmap b) { + mSelectorDrawable = b; + refreshDrawableState(); + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/MenuInterface.java b/src/com/jeremyfeinstein/slidingmenu/lib/MenuInterface.java new file mode 100644 index 0000000..73e64bd --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/MenuInterface.java @@ -0,0 +1,35 @@ +package com.jeremyfeinstein.slidingmenu.lib; + +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.view.View; + +public interface MenuInterface { + + public abstract void scrollBehindTo(int x, int y, + CustomViewBehind cvb, float scrollScale); + + public abstract int getMenuLeft(CustomViewBehind cvb, View content); + + public abstract int getAbsLeftBound(CustomViewBehind cvb, View content); + + public abstract int getAbsRightBound(CustomViewBehind cvb, View content); + + public abstract boolean marginTouchAllowed(View content, int x, int threshold); + + public abstract boolean menuOpenTouchAllowed(View content, int currPage, int x); + + public abstract boolean menuTouchInQuickReturn(View content, int currPage, int x); + + public abstract boolean menuClosedSlideAllowed(int x); + + public abstract boolean menuOpenSlideAllowed(int x); + + public abstract void drawShadow(Canvas canvas, Drawable shadow, int width); + + public abstract void drawFade(Canvas canvas, int alpha, + CustomViewBehind cvb, View content); + + public abstract void drawSelector(View content, Canvas canvas, float percentOpen); + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/SlidingMenu.java b/src/com/jeremyfeinstein/slidingmenu/lib/SlidingMenu.java new file mode 100644 index 0000000..8b88708 --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/SlidingMenu.java @@ -0,0 +1,1022 @@ +package com.jeremyfeinstein.slidingmenu.lib; + +import java.lang.reflect.Method; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Display; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; + +import com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove.OnPageChangeListener; + +public class SlidingMenu extends RelativeLayout { + + private static final String TAG = SlidingMenu.class.getSimpleName(); + + public static final int SLIDING_WINDOW = 0; + public static final int SLIDING_CONTENT = 1; + private boolean mActionbarOverlay = false; + + /** Constant value for use with setTouchModeAbove(). Allows the SlidingMenu to be opened with a swipe + * gesture on the screen's margin + */ + public static final int TOUCHMODE_MARGIN = 0; + + /** Constant value for use with setTouchModeAbove(). Allows the SlidingMenu to be opened with a swipe + * gesture anywhere on the screen + */ + public static final int TOUCHMODE_FULLSCREEN = 1; + + /** Constant value for use with setTouchModeAbove(). Denies the SlidingMenu to be opened with a swipe + * gesture + */ + public static final int TOUCHMODE_NONE = 2; + + /** Constant value for use with setMode(). Puts the menu to the left of the content. + */ + public static final int LEFT = 0; + + /** Constant value for use with setMode(). Puts the menu to the right of the content. + */ + public static final int RIGHT = 1; + + /** Constant value for use with setMode(). Puts menus to the left and right of the content. + */ + public static final int LEFT_RIGHT = 2; + + private CustomViewAbove mViewAbove; + + private CustomViewBehind mViewBehind; + + private OnOpenListener mOpenListener; + + private OnOpenListener mSecondaryOpenListner; + + private OnCloseListener mCloseListener; + + /** + * The listener interface for receiving onOpen events. + * The class that is interested in processing a onOpen + * event implements this interface, and the object created + * with that class is registered with a component using the + * component's <code>addOnOpenListener<code> method. When + * the onOpen event occurs, that object's appropriate + * method is invoked + */ + public interface OnOpenListener { + + /** + * On open. + */ + public void onOpen(); + } + + /** + * The listener interface for receiving onOpened events. + * The class that is interested in processing a onOpened + * event implements this interface, and the object created + * with that class is registered with a component using the + * component's <code>addOnOpenedListener<code> method. When + * the onOpened event occurs, that object's appropriate + * method is invoked. + * + * @see OnOpenedEvent + */ + public interface OnOpenedListener { + + /** + * On opened. + */ + public void onOpened(); + } + + /** + * The listener interface for receiving onClose events. + * The class that is interested in processing a onClose + * event implements this interface, and the object created + * with that class is registered with a component using the + * component's <code>addOnCloseListener<code> method. When + * the onClose event occurs, that object's appropriate + * method is invoked. + * + * @see OnCloseEvent + */ + public interface OnCloseListener { + + /** + * On close. + */ + public void onClose(); + } + + /** + * The listener interface for receiving onClosed events. + * The class that is interested in processing a onClosed + * event implements this interface, and the object created + * with that class is registered with a component using the + * component's <code>addOnClosedListener<code> method. When + * the onClosed event occurs, that object's appropriate + * method is invoked. + * + * @see OnClosedEvent + */ + public interface OnClosedListener { + + /** + * On closed. + */ + public void onClosed(); + } + + /** + * The Interface CanvasTransformer. + */ + public interface CanvasTransformer { + + /** + * Transform canvas. + * + * @param canvas the canvas + * @param percentOpen the percent open + */ + public void transformCanvas(Canvas canvas, float percentOpen); + } + + /** + * Instantiates a new SlidingMenu. + * + * @param context the associated Context + */ + public SlidingMenu(Context context) { + this(context, null); + } + + /** + * Instantiates a new SlidingMenu and attach to Activity. + * + * @param activity the activity to attach slidingmenu + * @param slideStyle the slidingmenu style + */ + public SlidingMenu(Activity activity, int slideStyle) { + this(activity, null); + this.attachToActivity(activity, slideStyle); + } + + /** + * Instantiates a new SlidingMenu. + * + * @param context the associated Context + * @param attrs the attrs + */ + public SlidingMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /** + * Instantiates a new SlidingMenu. + * + * @param context the associated Context + * @param attrs the attrs + * @param defStyle the def style + */ + public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mViewBehind = new CustomViewBehind(context); + addView(mViewBehind, behindParams); + LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mViewAbove = new CustomViewAbove(context); + addView(mViewAbove, aboveParams); + // register the CustomViewBehind with the CustomViewAbove + mViewAbove.setCustomViewBehind(mViewBehind); + mViewBehind.setCustomViewAbove(mViewAbove); + mViewAbove.setOnPageChangeListener(new OnPageChangeListener() { + public static final int POSITION_OPEN = 0; + public static final int POSITION_CLOSE = 1; + public static final int POSITION_SECONDARY_OPEN = 2; + + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { } + + public void onPageSelected(int position) { + if (position == POSITION_OPEN && mOpenListener != null) { + mOpenListener.onOpen(); + } else if (position == POSITION_CLOSE && mCloseListener != null) { + mCloseListener.onClose(); + } else if (position == POSITION_SECONDARY_OPEN && mSecondaryOpenListner != null ) { + mSecondaryOpenListner.onOpen(); + } + } + }); + + // now style everything! + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); + // set the above and behind views if defined in xml + int mode = ta.getInt(R.styleable.SlidingMenu_mode, LEFT); + setMode(mode); + int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); + if (viewAbove != -1) { + setContent(viewAbove); + } else { + setContent(new FrameLayout(context)); + } + int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); + if (viewBehind != -1) { + setMenu(viewBehind); + } else { + setMenu(new FrameLayout(context)); + } + int touchModeAbove = ta.getInt(R.styleable.SlidingMenu_touchModeAbove, TOUCHMODE_MARGIN); + setTouchModeAbove(touchModeAbove); + int touchModeBehind = ta.getInt(R.styleable.SlidingMenu_touchModeBehind, TOUCHMODE_MARGIN); + setTouchModeBehind(touchModeBehind); + + int offsetBehind = (int) ta.getDimension(R.styleable.SlidingMenu_behindOffset, -1); + int widthBehind = (int) ta.getDimension(R.styleable.SlidingMenu_behindWidth, -1); + if (offsetBehind != -1 && widthBehind != -1) + throw new IllegalStateException("Cannot set both behindOffset and behindWidth for a SlidingMenu"); + else if (offsetBehind != -1) + setBehindOffset(offsetBehind); + else if (widthBehind != -1) + setBehindWidth(widthBehind); + else + setBehindOffset(0); + float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.33f); + setBehindScrollScale(scrollOffsetBehind); + int shadowRes = ta.getResourceId(R.styleable.SlidingMenu_shadowDrawable, -1); + if (shadowRes != -1) { + setShadowDrawable(shadowRes); + } + int shadowWidth = (int) ta.getDimension(R.styleable.SlidingMenu_shadowWidth, 0); + setShadowWidth(shadowWidth); + boolean fadeEnabled = ta.getBoolean(R.styleable.SlidingMenu_fadeEnabled, true); + setFadeEnabled(fadeEnabled); + float fadeDeg = ta.getFloat(R.styleable.SlidingMenu_fadeDegree, 0.33f); + setFadeDegree(fadeDeg); + boolean selectorEnabled = ta.getBoolean(R.styleable.SlidingMenu_selectorEnabled, false); + setSelectorEnabled(selectorEnabled); + int selectorRes = ta.getResourceId(R.styleable.SlidingMenu_selectorDrawable, -1); + if (selectorRes != -1) + setSelectorDrawable(selectorRes); + ta.recycle(); + } + + /** + * Attaches the SlidingMenu to an entire Activity + * + * @param activity the Activity + * @param slideStyle either SLIDING_CONTENT or SLIDING_WINDOW + */ + public void attachToActivity(Activity activity, int slideStyle) { + attachToActivity(activity, slideStyle, false); + } + + /** + * Attaches the SlidingMenu to an entire Activity + * + * @param activity the Activity + * @param slideStyle either SLIDING_CONTENT or SLIDING_WINDOW + * @param actionbarOverlay whether or not the ActionBar is overlaid + */ + public void attachToActivity(Activity activity, int slideStyle, boolean actionbarOverlay) { + if (slideStyle != SLIDING_WINDOW && slideStyle != SLIDING_CONTENT) + throw new IllegalArgumentException("slideStyle must be either SLIDING_WINDOW or SLIDING_CONTENT"); + + if (getParent() != null) + throw new IllegalStateException("This SlidingMenu appears to already be attached"); + + // get the window background + TypedArray a = activity.getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowBackground}); + int background = a.getResourceId(0, 0); + a.recycle(); + + switch (slideStyle) { + case SLIDING_WINDOW: + mActionbarOverlay = false; + ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); + ViewGroup decorChild = (ViewGroup) decor.getChildAt(0); + // save ActionBar themes that have transparent assets + decorChild.setBackgroundResource(background); + decor.removeView(decorChild); + decor.addView(this); + setContent(decorChild); + break; + case SLIDING_CONTENT: + mActionbarOverlay = actionbarOverlay; + // take the above view out of + ViewGroup contentParent = (ViewGroup)activity.findViewById(android.R.id.content); + View content = contentParent.getChildAt(0); + contentParent.removeView(content); + contentParent.addView(this); + setContent(content); + // save people from having transparent backgrounds + if (content.getBackground() == null) + content.setBackgroundResource(background); + break; + } + } + + /** + * Set the above view content from a layout resource. The resource will be inflated, adding all top-level views + * to the above view. + * + * @param res the new content + */ + public void setContent(int res) { + setContent(LayoutInflater.from(getContext()).inflate(res, null)); + } + + /** + * Set the above view content to the given View. + * + * @param view The desired content to display. + */ + public void setContent(View view) { + mViewAbove.setContent(view); + showContent(); + } + + /** + * Retrieves the current content. + * @return the current content + */ + public View getContent() { + return mViewAbove.getContent(); + } + + /** + * Set the behind view (menu) content from a layout resource. The resource will be inflated, adding all top-level views + * to the behind view. + * + * @param res the new content + */ + public void setMenu(int res) { + setMenu(LayoutInflater.from(getContext()).inflate(res, null)); + } + + /** + * Set the behind view (menu) content to the given View. + * + * @param view The desired content to display. + */ + public void setMenu(View v) { + mViewBehind.setContent(v); + } + + /** + * Retrieves the main menu. + * @return the main menu + */ + public View getMenu() { + return mViewBehind.getContent(); + } + + /** + * Set the secondary behind view (right menu) content from a layout resource. The resource will be inflated, adding all top-level views + * to the behind view. + * + * @param res the new content + */ + public void setSecondaryMenu(int res) { + setSecondaryMenu(LayoutInflater.from(getContext()).inflate(res, null)); + } + + /** + * Set the secondary behind view (right menu) content to the given View. + * + * @param view The desired content to display. + */ + public void setSecondaryMenu(View v) { + mViewBehind.setSecondaryContent(v); + // mViewBehind.invalidate(); + } + + /** + * Retrieves the current secondary menu (right). + * @return the current menu + */ + public View getSecondaryMenu() { + return mViewBehind.getSecondaryContent(); + } + + + /** + * Sets the sliding enabled. + * + * @param b true to enable sliding, false to disable it. + */ + public void setSlidingEnabled(boolean b) { + mViewAbove.setSlidingEnabled(b); + } + + /** + * Checks if is sliding enabled. + * + * @return true, if is sliding enabled + */ + public boolean isSlidingEnabled() { + return mViewAbove.isSlidingEnabled(); + } + + /** + * Sets which side the SlidingMenu should appear on. + * @param mode must be either SlidingMenu.LEFT or SlidingMenu.RIGHT + */ + public void setMode(int mode) { + if (mode != LEFT && mode != RIGHT && mode != LEFT_RIGHT) { + throw new IllegalStateException("SlidingMenu mode must be LEFT, RIGHT, or LEFT_RIGHT"); + } + mViewBehind.setMode(mode); + } + + /** + * Returns the current side that the SlidingMenu is on. + * @return the current mode, either SlidingMenu.LEFT or SlidingMenu.RIGHT + */ + public int getMode() { + return mViewBehind.getMode(); + } + + /** + * Sets whether or not the SlidingMenu is in static mode (i.e. nothing is moving and everything is showing) + * + * @param b true to set static mode, false to disable static mode. + */ + public void setStatic(boolean b) { + if (b) { + setSlidingEnabled(false); + mViewAbove.setCustomViewBehind(null); + mViewAbove.setCurrentItem(1); + // mViewBehind.setCurrentItem(0); + } else { + mViewAbove.setCurrentItem(1); + // mViewBehind.setCurrentItem(1); + mViewAbove.setCustomViewBehind(mViewBehind); + setSlidingEnabled(true); + } + } + + /** + * Opens the menu and shows the menu view. + */ + public void showMenu() { + showMenu(true); + } + + /** + * Opens the menu and shows the menu view. + * + * @param animate true to animate the transition, false to ignore animation + */ + public void showMenu(boolean animate) { + mViewAbove.setCurrentItem(0, animate); + } + + /** + * Opens the menu and shows the secondary menu view. Will default to the regular menu + * if there is only one. + */ + public void showSecondaryMenu() { + showSecondaryMenu(true); + } + + /** + * Opens the menu and shows the secondary (right) menu view. Will default to the regular menu + * if there is only one. + * + * @param animate true to animate the transition, false to ignore animation + */ + public void showSecondaryMenu(boolean animate) { + mViewAbove.setCurrentItem(2, animate); + } + + /** + * Closes the menu and shows the above view. + */ + public void showContent() { + showContent(true); + } + + /** + * Closes the menu and shows the above view. + * + * @param animate true to animate the transition, false to ignore animation + */ + public void showContent(boolean animate) { + mViewAbove.setCurrentItem(1, animate); + } + + /** + * Toggle the SlidingMenu. If it is open, it will be closed, and vice versa. + */ + public void toggle() { + toggle(true); + } + + /** + * Toggle the SlidingMenu. If it is open, it will be closed, and vice versa. + * + * @param animate true to animate the transition, false to ignore animation + */ + public void toggle(boolean animate) { + if (isMenuShowing()) { + showContent(animate); + } else { + showMenu(animate); + } + } + + /** + * Checks if is the behind view showing. + * + * @return Whether or not the behind view is showing + */ + public boolean isMenuShowing() { + return mViewAbove.getCurrentItem() == 0 || mViewAbove.getCurrentItem() == 2; + } + + /** + * Checks if is the behind view showing. + * + * @return Whether or not the behind view is showing + */ + public boolean isSecondaryMenuShowing() { + return mViewAbove.getCurrentItem() == 2; + } + + /** + * Gets the behind offset. + * + * @return The margin on the right of the screen that the behind view scrolls to + */ + public int getBehindOffset() { + return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + } + + /** + * Sets the behind offset. + * + * @param i The margin, in pixels, on the right of the screen that the behind view scrolls to. + */ + public void setBehindOffset(int i) { + // RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()); + // int bottom = params.bottomMargin; + // int top = params.topMargin; + // int left = params.leftMargin; + // params.setMargins(left, top, i, bottom); + mViewBehind.setWidthOffset(i); + } + + /** + * Sets the behind offset. + * + * @param resID The dimension resource id to be set as the behind offset. + * The menu, when open, will leave this width margin on the right of the screen. + */ + public void setBehindOffsetRes(int resID) { + int i = (int) getContext().getResources().getDimension(resID); + setBehindOffset(i); + } + + /** + * Sets the above offset. + * + * @param i the new above offset, in pixels + */ + public void setAboveOffset(int i) { + mViewAbove.setAboveOffset(i); + } + + /** + * Sets the above offset. + * + * @param resID The dimension resource id to be set as the above offset. + */ + public void setAboveOffsetRes(int resID) { + int i = (int) getContext().getResources().getDimension(resID); + setAboveOffset(i); + } + + /** + * Sets the behind width. + * + * @param i The width the Sliding Menu will open to, in pixels + */ + @SuppressWarnings("deprecation") + public void setBehindWidth(int i) { + int width; + Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay(); + try { + Class<?> cls = Display.class; + Class<?>[] parameterTypes = {Point.class}; + Point parameter = new Point(); + Method method = cls.getMethod("getSize", parameterTypes); + method.invoke(display, parameter); + width = parameter.x; + } catch (Exception e) { + width = display.getWidth(); + } + setBehindOffset(width-i); + } + + /** + * Sets the behind width. + * + * @param res The dimension resource id to be set as the behind width offset. + * The menu, when open, will open this wide. + */ + public void setBehindWidthRes(int res) { + int i = (int) getContext().getResources().getDimension(res); + setBehindWidth(i); + } + + /** + * Gets the behind scroll scale. + * + * @return The scale of the parallax scroll + */ + public float getBehindScrollScale() { + return mViewBehind.getScrollScale(); + } + + /** + * Gets the touch mode margin threshold + * @return the touch mode margin threshold + */ + public int getTouchmodeMarginThreshold() { + return mViewBehind.getMarginThreshold(); + } + + /** + * Set the touch mode margin threshold + * @param touchmodeMarginThreshold + */ + public void setTouchmodeMarginThreshold(int touchmodeMarginThreshold) { + mViewBehind.setMarginThreshold(touchmodeMarginThreshold); + } + + /** + * Sets the behind scroll scale. + * + * @param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every + * 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels) + */ + public void setBehindScrollScale(float f) { + if (f < 0 && f > 1) + throw new IllegalStateException("ScrollScale must be between 0 and 1"); + mViewBehind.setScrollScale(f); + } + + /** + * Sets the behind canvas transformer. + * + * @param t the new behind canvas transformer + */ + public void setBehindCanvasTransformer(CanvasTransformer t) { + mViewBehind.setCanvasTransformer(t); + } + + /** + * Gets the touch mode above. + * + * @return the touch mode above + */ + public int getTouchModeAbove() { + return mViewAbove.getTouchMode(); + } + + /** + * Controls whether the SlidingMenu can be opened with a swipe gesture. + * Options are {@link #TOUCHMODE_MARGIN TOUCHMODE_MARGIN}, {@link #TOUCHMODE_FULLSCREEN TOUCHMODE_FULLSCREEN}, + * or {@link #TOUCHMODE_NONE TOUCHMODE_NONE} + * + * @param i the new touch mode + */ + public void setTouchModeAbove(int i) { + if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN + && i != TOUCHMODE_NONE) { + throw new IllegalStateException("TouchMode must be set to either" + + "TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN or TOUCHMODE_NONE."); + } + mViewAbove.setTouchMode(i); + } + + /** + * Controls whether the SlidingMenu can be opened with a swipe gesture. + * Options are {@link #TOUCHMODE_MARGIN TOUCHMODE_MARGIN}, {@link #TOUCHMODE_FULLSCREEN TOUCHMODE_FULLSCREEN}, + * or {@link #TOUCHMODE_NONE TOUCHMODE_NONE} + * + * @param i the new touch mode + */ + public void setTouchModeBehind(int i) { + if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN + && i != TOUCHMODE_NONE) { + throw new IllegalStateException("TouchMode must be set to either" + + "TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN or TOUCHMODE_NONE."); + } + mViewBehind.setTouchMode(i); + } + + /** + * Sets the shadow drawable. + * + * @param resId the resource ID of the new shadow drawable + */ + public void setShadowDrawable(int resId) { + setShadowDrawable(getContext().getResources().getDrawable(resId)); + } + + /** + * Sets the shadow drawable. + * + * @param d the new shadow drawable + */ + public void setShadowDrawable(Drawable d) { + mViewBehind.setShadowDrawable(d); + } + + /** + * Sets the secondary (right) shadow drawable. + * + * @param resId the resource ID of the new shadow drawable + */ + public void setSecondaryShadowDrawable(int resId) { + setSecondaryShadowDrawable(getContext().getResources().getDrawable(resId)); + } + + /** + * Sets the secondary (right) shadow drawable. + * + * @param d the new shadow drawable + */ + public void setSecondaryShadowDrawable(Drawable d) { + mViewBehind.setSecondaryShadowDrawable(d); + } + + /** + * Sets the shadow width. + * + * @param resId The dimension resource id to be set as the shadow width. + */ + public void setShadowWidthRes(int resId) { + setShadowWidth((int)getResources().getDimension(resId)); + } + + /** + * Sets the shadow width. + * + * @param pixels the new shadow width, in pixels + */ + public void setShadowWidth(int pixels) { + mViewBehind.setShadowWidth(pixels); + } + + /** + * Enables or disables the SlidingMenu's fade in and out + * + * @param b true to enable fade, false to disable it + */ + public void setFadeEnabled(boolean b) { + mViewBehind.setFadeEnabled(b); + } + + /** + * Sets how much the SlidingMenu fades in and out. Fade must be enabled, see + * {@link #setFadeEnabled(boolean) setFadeEnabled(boolean)} + * + * @param f the new fade degree, between 0.0f and 1.0f + */ + public void setFadeDegree(float f) { + mViewBehind.setFadeDegree(f); + } + + /** + * Enables or disables whether the selector is drawn + * + * @param b true to draw the selector, false to not draw the selector + */ + public void setSelectorEnabled(boolean b) { + mViewBehind.setSelectorEnabled(true); + } + + /** + * Sets the selected view. The selector will be drawn here + * + * @param v the new selected view + */ + public void setSelectedView(View v) { + mViewBehind.setSelectedView(v); + } + + /** + * Sets the selector drawable. + * + * @param res a resource ID for the selector drawable + */ + public void setSelectorDrawable(int res) { + mViewBehind.setSelectorBitmap(BitmapFactory.decodeResource(getResources(), res)); + } + + /** + * Sets the selector drawable. + * + * @param b the new selector bitmap + */ + public void setSelectorBitmap(Bitmap b) { + mViewBehind.setSelectorBitmap(b); + } + + /** + * Add a View ignored by the Touch Down event when mode is Fullscreen + * + * @param v a view to be ignored + */ + public void addIgnoredView(View v) { + mViewAbove.addIgnoredView(v); + } + + /** + * Remove a View ignored by the Touch Down event when mode is Fullscreen + * + * @param v a view not wanted to be ignored anymore + */ + public void removeIgnoredView(View v) { + mViewAbove.removeIgnoredView(v); + } + + /** + * Clear the list of Views ignored by the Touch Down event when mode is Fullscreen + */ + public void clearIgnoredViews() { + mViewAbove.clearIgnoredViews(); + } + + /** + * Sets the OnOpenListener. {@link OnOpenListener#onOpen() OnOpenListener.onOpen()} will be called when the SlidingMenu is opened + * + * @param listener the new OnOpenListener + */ + public void setOnOpenListener(OnOpenListener listener) { + //mViewAbove.setOnOpenListener(listener); + mOpenListener = listener; + } + + + /** + * Sets the OnOpenListner for secondary menu {@link OnOpenListener#onOpen() OnOpenListener.onOpen()} will be called when the secondary SlidingMenu is opened + * + * @param listener the new OnOpenListener + */ + + public void setSecondaryOnOpenListner(OnOpenListener listener) { + mSecondaryOpenListner = listener; + } + + /** + * Sets the OnCloseListener. {@link OnCloseListener#onClose() OnCloseListener.onClose()} will be called when any one of the SlidingMenu is closed + * + * @param listener the new setOnCloseListener + */ + public void setOnCloseListener(OnCloseListener listener) { + //mViewAbove.setOnCloseListener(listener); + mCloseListener = listener; + } + + /** + * Sets the OnOpenedListener. {@link OnOpenedListener#onOpened() OnOpenedListener.onOpened()} will be called after the SlidingMenu is opened + * + * @param listener the new OnOpenedListener + */ + public void setOnOpenedListener(OnOpenedListener listener) { + mViewAbove.setOnOpenedListener(listener); + } + + /** + * Sets the OnClosedListener. {@link OnClosedListener#onClosed() OnClosedListener.onClosed()} will be called after the SlidingMenu is closed + * + * @param listener the new OnClosedListener + */ + public void setOnClosedListener(OnClosedListener listener) { + mViewAbove.setOnClosedListener(listener); + } + + public static class SavedState extends BaseSavedState { + + private final int mItem; + + public SavedState(Parcelable superState, int item) { + super(superState); + mItem = item; + } + + private SavedState(Parcel in) { + super(in); + mItem = in.readInt(); + } + + public int getItem() { + return mItem; + } + + /* (non-Javadoc) + * @see android.view.AbsSavedState#writeToParcel(android.os.Parcel, int) + */ + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(mItem); + } + + public static final Parcelable.Creator<SavedState> CREATOR = + new Parcelable.Creator<SavedState>() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + + } + + /* (non-Javadoc) + * @see android.view.View#onSaveInstanceState() + */ + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState, mViewAbove.getCurrentItem()); + return ss; + } + + /* (non-Javadoc) + * @see android.view.View#onRestoreInstanceState(android.os.Parcelable) + */ + @Override + protected void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + mViewAbove.setCurrentItem(ss.getItem()); + } + + /* (non-Javadoc) + * @see android.view.ViewGroup#fitSystemWindows(android.graphics.Rect) + */ + @SuppressLint("NewApi") + @Override + protected boolean fitSystemWindows(Rect insets) { + int leftPadding = insets.left; + int rightPadding = insets.right; + int topPadding = insets.top; + int bottomPadding = insets.bottom; + if (!mActionbarOverlay) { + Log.v(TAG, "setting padding!"); + setPadding(leftPadding, topPadding, rightPadding, bottomPadding); + } + return true; + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void manageLayers(float percentOpen) { + if (Build.VERSION.SDK_INT < 11) return; + + boolean layer = percentOpen > 0.0f && percentOpen < 1.0f; + final int layerType = layer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE; + + if (layerType != getContent().getLayerType()) { + getHandler().post(new Runnable() { + public void run() { + Log.v(TAG, "changing layerType. hardware? " + (layerType == View.LAYER_TYPE_HARDWARE)); + getContent().setLayerType(layerType, null); + getMenu().setLayerType(layerType, null); + if (getSecondaryMenu() != null) { + getSecondaryMenu().setLayerType(layerType, null); + } + } + }); + } + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivity.java b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivity.java new file mode 100644 index 0000000..a47114d --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivity.java @@ -0,0 +1,152 @@ +package com.jeremyfeinstein.slidingmenu.lib.app; + +import android.app.Activity; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; + +public class SlidingActivity extends Activity implements SlidingActivityBase { + + private SlidingActivityHelper mHelper; + + /* (non-Javadoc) + * @see android.app.Activity#onCreate(android.os.Bundle) + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mHelper = new SlidingActivityHelper(this); + mHelper.onCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#onPostCreate(android.os.Bundle) + */ + @Override + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mHelper.onPostCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#findViewById(int) + */ + @Override + public View findViewById(int id) { + View v = super.findViewById(id); + if (v != null) + return v; + return mHelper.findViewById(id); + } + + /* (non-Javadoc) + * @see android.app.Activity#onSaveInstanceState(android.os.Bundle) + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mHelper.onSaveInstanceState(outState); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(int) + */ + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View) + */ + @Override + public void setContentView(View v) { + setContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + @Override + public void setContentView(View v, LayoutParams params) { + super.setContentView(v, params); + mHelper.registerAboveContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(int) + */ + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View) + */ + public void setBehindContentView(View v) { + setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + public void setBehindContentView(View v, LayoutParams params) { + mHelper.setBehindContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#getSlidingMenu() + */ + public SlidingMenu getSlidingMenu() { + return mHelper.getSlidingMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#toggle() + */ + public void toggle() { + mHelper.toggle(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showAbove() + */ + public void showContent() { + mHelper.showContent(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showBehind() + */ + public void showMenu() { + mHelper.showMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showSecondaryMenu() + */ + public void showSecondaryMenu() { + mHelper.showSecondaryMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setSlidingActionBarEnabled(boolean) + */ + public void setSlidingActionBarEnabled(boolean b) { + mHelper.setSlidingActionBarEnabled(b); + } + + /* (non-Javadoc) + * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent) + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + boolean b = mHelper.onKeyUp(keyCode, event); + if (b) return b; + return super.onKeyUp(keyCode, event); + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivityBase.java b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivityBase.java new file mode 100644 index 0000000..7bff1f2 --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivityBase.java @@ -0,0 +1,74 @@ +package com.jeremyfeinstein.slidingmenu.lib.app; + +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; + +public interface SlidingActivityBase { + + /** + * Set the behind view content to an explicit view. This view is placed directly into the behind view 's view hierarchy. + * It can itself be a complex view hierarchy. + * + * @param view The desired content to display. + * @param layoutParams Layout parameters for the view. + */ + public void setBehindContentView(View view, LayoutParams layoutParams); + + /** + * Set the behind view content to an explicit view. This view is placed directly into the behind view 's view hierarchy. + * It can itself be a complex view hierarchy. When calling this method, the layout parameters of the specified + * view are ignored. Both the width and the height of the view are set by default to MATCH_PARENT. To use your + * own layout parameters, invoke setContentView(android.view.View, android.view.ViewGroup.LayoutParams) instead. + * + * @param view The desired content to display. + */ + public void setBehindContentView(View view); + + /** + * Set the behind view content from a layout resource. The resource will be inflated, adding all top-level views + * to the behind view. + * + * @param layoutResID Resource ID to be inflated. + */ + public void setBehindContentView(int layoutResID); + + /** + * Gets the SlidingMenu associated with this activity. + * + * @return the SlidingMenu associated with this activity. + */ + public SlidingMenu getSlidingMenu(); + + /** + * Toggle the SlidingMenu. If it is open, it will be closed, and vice versa. + */ + public void toggle(); + + /** + * Close the SlidingMenu and show the content view. + */ + public void showContent(); + + /** + * Open the SlidingMenu and show the menu view. + */ + public void showMenu(); + + /** + * Open the SlidingMenu and show the secondary (right) menu view. Will default to the regular menu + * if there is only one. + */ + public void showSecondaryMenu(); + + /** + * Controls whether the ActionBar slides along with the above view when the menu is opened, + * or if it stays in place. + * + * @param slidingActionBarEnabled True if you want the ActionBar to slide along with the SlidingMenu, + * false if you want the ActionBar to stay in place + */ + public void setSlidingActionBarEnabled(boolean slidingActionBarEnabled); + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivityHelper.java b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivityHelper.java new file mode 100644 index 0000000..0cf954b --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingActivityHelper.java @@ -0,0 +1,219 @@ +package com.jeremyfeinstein.slidingmenu.lib.app; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Handler; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +import com.jeremyfeinstein.slidingmenu.lib.R; +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; + +public class SlidingActivityHelper { + + private Activity mActivity; + + private SlidingMenu mSlidingMenu; + + private View mViewAbove; + + private View mViewBehind; + + private boolean mBroadcasting = false; + + private boolean mOnPostCreateCalled = false; + + private boolean mEnableSlide = true; + + /** + * Instantiates a new SlidingActivityHelper. + * + * @param activity the associated activity + */ + public SlidingActivityHelper(Activity activity) { + mActivity = activity; + } + + /** + * Sets mSlidingMenu as a newly inflated SlidingMenu. Should be called within the activitiy's onCreate() + * + * @param savedInstanceState the saved instance state (unused) + */ + public void onCreate(Bundle savedInstanceState) { + mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null); + } + + /** + * Further SlidingMenu initialization. Should be called within the activitiy's onPostCreate() + * + * @param savedInstanceState the saved instance state (unused) + */ + public void onPostCreate(Bundle savedInstanceState) { + if (mViewBehind == null || mViewAbove == null) { + throw new IllegalStateException("Both setBehindContentView must be called " + + "in onCreate in addition to setContentView."); + } + + mOnPostCreateCalled = true; + + mSlidingMenu.attachToActivity(mActivity, + mEnableSlide ? SlidingMenu.SLIDING_WINDOW : SlidingMenu.SLIDING_CONTENT); + + final boolean open; + final boolean secondary; + if (savedInstanceState != null) { + open = savedInstanceState.getBoolean("SlidingActivityHelper.open"); + secondary = savedInstanceState.getBoolean("SlidingActivityHelper.secondary"); + } else { + open = false; + secondary = false; + } + new Handler().post(new Runnable() { + public void run() { + if (open) { + if (secondary) { + mSlidingMenu.showSecondaryMenu(false); + } else { + mSlidingMenu.showMenu(false); + } + } else { + mSlidingMenu.showContent(false); + } + } + }); + } + + /** + * Controls whether the ActionBar slides along with the above view when the menu is opened, + * or if it stays in place. + * + * @param slidingActionBarEnabled True if you want the ActionBar to slide along with the SlidingMenu, + * false if you want the ActionBar to stay in place + */ + public void setSlidingActionBarEnabled(boolean slidingActionBarEnabled) { + if (mOnPostCreateCalled) + throw new IllegalStateException("enableSlidingActionBar must be called in onCreate."); + mEnableSlide = slidingActionBarEnabled; + } + + /** + * Finds a view that was identified by the id attribute from the XML that was processed in onCreate(Bundle). + * + * @param id the resource id of the desired view + * @return The view if found or null otherwise. + */ + public View findViewById(int id) { + View v; + if (mSlidingMenu != null) { + v = mSlidingMenu.findViewById(id); + if (v != null) + return v; + } + return null; + } + + /** + * Called to retrieve per-instance state from an activity before being killed so that the state can be + * restored in onCreate(Bundle) or onRestoreInstanceState(Bundle) (the Bundle populated by this method + * will be passed to both). + * + * @param outState Bundle in which to place your saved state. + */ + public void onSaveInstanceState(Bundle outState) { + outState.putBoolean("SlidingActivityHelper.open", mSlidingMenu.isMenuShowing()); + outState.putBoolean("SlidingActivityHelper.secondary", mSlidingMenu.isSecondaryMenuShowing()); + } + + /** + * Register the above content view. + * + * @param v the above content view to register + * @param params LayoutParams for that view (unused) + */ + public void registerAboveContentView(View v, LayoutParams params) { + if (!mBroadcasting) + mViewAbove = v; + } + + /** + * Set the activity content to an explicit view. This view is placed directly into the activity's view + * hierarchy. It can itself be a complex view hierarchy. When calling this method, the layout parameters + * of the specified view are ignored. Both the width and the height of the view are set by default to + * MATCH_PARENT. To use your own layout parameters, invoke setContentView(android.view.View, + * android.view.ViewGroup.LayoutParams) instead. + * + * @param v The desired content to display. + */ + public void setContentView(View v) { + mBroadcasting = true; + mActivity.setContentView(v); + } + + /** + * Set the behind view content to an explicit view. This view is placed directly into the behind view 's view hierarchy. + * It can itself be a complex view hierarchy. + * + * @param view The desired content to display. + * @param layoutParams Layout parameters for the view. (unused) + */ + public void setBehindContentView(View view, LayoutParams layoutParams) { + mViewBehind = view; + mSlidingMenu.setMenu(mViewBehind); + } + + /** + * Gets the SlidingMenu associated with this activity. + * + * @return the SlidingMenu associated with this activity. + */ + public SlidingMenu getSlidingMenu() { + return mSlidingMenu; + } + + /** + * Toggle the SlidingMenu. If it is open, it will be closed, and vice versa. + */ + public void toggle() { + mSlidingMenu.toggle(); + } + + /** + * Close the SlidingMenu and show the content view. + */ + public void showContent() { + mSlidingMenu.showContent(); + } + + /** + * Open the SlidingMenu and show the menu view. + */ + public void showMenu() { + mSlidingMenu.showMenu(); + } + + /** + * Open the SlidingMenu and show the secondary menu view. Will default to the regular menu + * if there is only one. + */ + public void showSecondaryMenu() { + mSlidingMenu.showSecondaryMenu(); + } + + /** + * On key up. + * + * @param keyCode the key code + * @param event the event + * @return true, if successful + */ + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && mSlidingMenu.isMenuShowing()) { + showContent(); + return true; + } + return false; + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingFragmentActivity.java b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingFragmentActivity.java new file mode 100644 index 0000000..65b5300 --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingFragmentActivity.java @@ -0,0 +1,152 @@ +package com.jeremyfeinstein.slidingmenu.lib.app; + +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; + +public class SlidingFragmentActivity extends FragmentActivity implements SlidingActivityBase { + + private SlidingActivityHelper mHelper; + + /* (non-Javadoc) + * @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle) + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mHelper = new SlidingActivityHelper(this); + mHelper.onCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#onPostCreate(android.os.Bundle) + */ + @Override + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mHelper.onPostCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#findViewById(int) + */ + @Override + public View findViewById(int id) { + View v = super.findViewById(id); + if (v != null) + return v; + return mHelper.findViewById(id); + } + + /* (non-Javadoc) + * @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle) + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mHelper.onSaveInstanceState(outState); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(int) + */ + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View) + */ + @Override + public void setContentView(View v) { + setContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + @Override + public void setContentView(View v, LayoutParams params) { + super.setContentView(v, params); + mHelper.registerAboveContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(int) + */ + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View) + */ + public void setBehindContentView(View v) { + setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + public void setBehindContentView(View v, LayoutParams params) { + mHelper.setBehindContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#getSlidingMenu() + */ + public SlidingMenu getSlidingMenu() { + return mHelper.getSlidingMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#toggle() + */ + public void toggle() { + mHelper.toggle(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showAbove() + */ + public void showContent() { + mHelper.showContent(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showBehind() + */ + public void showMenu() { + mHelper.showMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showSecondaryMenu() + */ + public void showSecondaryMenu() { + mHelper.showSecondaryMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setSlidingActionBarEnabled(boolean) + */ + public void setSlidingActionBarEnabled(boolean b) { + mHelper.setSlidingActionBarEnabled(b); + } + + /* (non-Javadoc) + * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent) + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + boolean b = mHelper.onKeyUp(keyCode, event); + if (b) return b; + return super.onKeyUp(keyCode, event); + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingListActivity.java b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingListActivity.java new file mode 100644 index 0000000..d28128d --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingListActivity.java @@ -0,0 +1,157 @@ +package com.jeremyfeinstein.slidingmenu.lib.app; + +import android.app.ListActivity; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.ListView; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; + +public class SlidingListActivity extends ListActivity implements SlidingActivityBase { + + private SlidingActivityHelper mHelper; + + /* (non-Javadoc) + * @see android.app.Activity#onCreate(android.os.Bundle) + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mHelper = new SlidingActivityHelper(this); + mHelper.onCreate(savedInstanceState); + ListView listView = new ListView(this); + listView.setId(android.R.id.list); + setContentView(listView); + } + + /* (non-Javadoc) + * @see android.app.Activity#onPostCreate(android.os.Bundle) + */ + @Override + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mHelper.onPostCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#findViewById(int) + */ + @Override + public View findViewById(int id) { + View v = super.findViewById(id); + if (v != null) + return v; + return mHelper.findViewById(id); + } + + /* (non-Javadoc) + * @see android.app.Activity#onSaveInstanceState(android.os.Bundle) + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mHelper.onSaveInstanceState(outState); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(int) + */ + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View) + */ + @Override + public void setContentView(View v) { + setContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + @Override + public void setContentView(View v, LayoutParams params) { + super.setContentView(v, params); + mHelper.registerAboveContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(int) + */ + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View) + */ + public void setBehindContentView(View v) { + setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + public void setBehindContentView(View v, LayoutParams params) { + mHelper.setBehindContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#getSlidingMenu() + */ + public SlidingMenu getSlidingMenu() { + return mHelper.getSlidingMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#toggle() + */ + public void toggle() { + mHelper.toggle(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showAbove() + */ + public void showContent() { + mHelper.showContent(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showBehind() + */ + public void showMenu() { + mHelper.showMenu(); + } + + /* + * (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showSecondaryMenu() + */ + public void showSecondaryMenu() { + mHelper.showSecondaryMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setSlidingActionBarEnabled(boolean) + */ + public void setSlidingActionBarEnabled(boolean b) { + mHelper.setSlidingActionBarEnabled(b); + } + + /* (non-Javadoc) + * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent) + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + boolean b = mHelper.onKeyUp(keyCode, event); + if (b) return b; + return super.onKeyUp(keyCode, event); + } + +} diff --git a/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingPreferenceActivity.java b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingPreferenceActivity.java new file mode 100644 index 0000000..2f5b375 --- /dev/null +++ b/src/com/jeremyfeinstein/slidingmenu/lib/app/SlidingPreferenceActivity.java @@ -0,0 +1,151 @@ +package com.jeremyfeinstein.slidingmenu.lib.app; + +import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; + +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +public class SlidingPreferenceActivity extends PreferenceActivity implements SlidingActivityBase { + + private SlidingActivityHelper mHelper; + + /* (non-Javadoc) + * @see android.app.Activity#onCreate(android.os.Bundle) + */ + @Override + public void onCreate(Bundle savedInstanceState) { + mHelper = new SlidingActivityHelper(this); + super.onCreate(savedInstanceState); + mHelper.onCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#onPostCreate(android.os.Bundle) + */ + @Override + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mHelper.onPostCreate(savedInstanceState); + } + + /* (non-Javadoc) + * @see android.app.Activity#findViewById(int) + */ + @Override + public View findViewById(int id) { + View v = super.findViewById(id); + if (v != null) + return v; + return mHelper.findViewById(id); + } + + /* (non-Javadoc) + * @see android.app.Activity#onSaveInstanceState(android.os.Bundle) + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mHelper.onSaveInstanceState(outState); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(int) + */ + @Override + public void setContentView(int id) { + setContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View) + */ + @Override + public void setContentView(View v) { + setContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + @Override + public void setContentView(View v, LayoutParams params) { + super.setContentView(v, params); + mHelper.registerAboveContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(int) + */ + public void setBehindContentView(int id) { + setBehindContentView(getLayoutInflater().inflate(id, null)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View) + */ + public void setBehindContentView(View v) { + setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setBehindContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + public void setBehindContentView(View v, LayoutParams params) { + mHelper.setBehindContentView(v, params); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#getSlidingMenu() + */ + public SlidingMenu getSlidingMenu() { + return mHelper.getSlidingMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#toggle() + */ + public void toggle() { + mHelper.toggle(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showAbove() + */ + public void showContent() { + mHelper.showContent(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showBehind() + */ + public void showMenu() { + mHelper.showMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#showSecondaryMenu() + */ + public void showSecondaryMenu() { + mHelper.showSecondaryMenu(); + } + + /* (non-Javadoc) + * @see com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivityBase#setSlidingActionBarEnabled(boolean) + */ + public void setSlidingActionBarEnabled(boolean b) { + mHelper.setSlidingActionBarEnabled(b); + } + + /* (non-Javadoc) + * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent) + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + boolean b = mHelper.onKeyUp(keyCode, event); + if (b) return b; + return super.onKeyUp(keyCode, event); + } +} |
