diff --git a/example/res/drawable/shadow_right.xml b/example/res/drawable/shadow_right.xml new file mode 100644 index 000000000..df27938c1 --- /dev/null +++ b/example/res/drawable/shadow_right.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/example/res/layout/test.xml b/example/res/layout/test.xml new file mode 100644 index 000000000..33281374a --- /dev/null +++ b/example/res/layout/test.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/example/src/com/slidingmenu/example/BaseActivity.java b/example/src/com/slidingmenu/example/BaseActivity.java index 7d23bf012..39741e857 100644 --- a/example/src/com/slidingmenu/example/BaseActivity.java +++ b/example/src/com/slidingmenu/example/BaseActivity.java @@ -12,6 +12,8 @@ import android.support.v4.app.ListFragment; import android.support.v4.view.ViewPager; import android.view.MenuItem; +import android.widget.FrameLayout; +import android.widget.LinearLayout; import com.slidingmenu.lib.SlidingMenu; import com.slidingmenu.lib.app.SlidingFragmentActivity; @@ -20,29 +22,22 @@ public class BaseActivity extends SlidingFragmentActivity { private int mTitleRes; protected ListFragment mFrag; - + public BaseActivity(int titleRes) { mTitleRes = titleRes; } - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - setTitle(mTitleRes); - // set the Behind View - setBehindContentView(R.layout.menu_frame); - FragmentTransaction t = this.getSupportFragmentManager().beginTransaction(); - mFrag = new SampleListFragment(); - t.replace(R.id.menu_frame, mFrag); - t.commit(); + setTitle(mTitleRes); + + addLeft(); // customize the SlidingMenu SlidingMenu sm = getSlidingMenu(); sm.setShadowWidthRes(R.dimen.shadow_width); - sm.setShadowDrawable(R.drawable.shadow); - sm.setBehindOffsetRes(R.dimen.actionbar_home_width); // customize the ActionBar if (Build.VERSION.SDK_INT >= 11) { @@ -50,16 +45,50 @@ public void onCreate(Bundle savedInstanceState) { } } + private void addLeft() { + FrameLayout left = new FrameLayout(this); + left.setId("LEFT".hashCode()); + setBehindLeftContentView(left); + getSupportFragmentManager() + .beginTransaction() + .replace("LEFT".hashCode(), new SampleListFragment()) + .commit(); + + SlidingMenu sm = getSlidingMenu(); + sm.setShadowDrawable(R.drawable.shadow, SlidingMenu.LEFT); + sm.setBehindOffsetRes(R.dimen.actionbar_home_width, SlidingMenu.LEFT); + } + + private void addRight() { + FrameLayout right = new FrameLayout(this); + right.setId("RIGHT".hashCode()); + this.setBehindRightContentView(right); + getSupportFragmentManager() + .beginTransaction() + .replace("RIGHT".hashCode(), new SampleListFragment()) + .commit(); + + SlidingMenu sm = getSlidingMenu(); + sm.setShadowDrawable(R.drawable.shadow_right, SlidingMenu.RIGHT); + sm.setBehindOffsetRes(R.dimen.actionbar_home_width, SlidingMenu.RIGHT); + } + +// @Override +// public void onResume() { +// super.onResume(); +// getSlidingMenu().showAbove(); +// } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: - toggle(); + toggle(SlidingMenu.LEFT); return true; } return super.onOptionsItemSelected(item); } - + public class PagerAdapter extends FragmentPagerAdapter { private List mFragments = new ArrayList(); private ViewPager mPager; @@ -68,6 +97,8 @@ public PagerAdapter(FragmentManager fm, ViewPager vp) { super(fm); mPager = vp; mPager.setAdapter(this); + for (int i = 0; i < 3; i++) + addTab(new SampleListFragment()); } public void addTab(Fragment frag) { @@ -84,5 +115,5 @@ public int getCount() { return mFragments.size(); } } - + } diff --git a/example/src/com/slidingmenu/example/CustomAnimation.java b/example/src/com/slidingmenu/example/CustomAnimation.java index 63308dbcd..31eac6dba 100644 --- a/example/src/com/slidingmenu/example/CustomAnimation.java +++ b/example/src/com/slidingmenu/example/CustomAnimation.java @@ -27,8 +27,8 @@ public void onCreate(Bundle savedInstanceState) { SlidingMenu sm = getSlidingMenu(); setSlidingActionBarEnabled(true); - sm.setBehindScrollScale(0.0f); - sm.setBehindCanvasTransformer(mTransformer); + sm.setBehindScrollScale(0.0f, SlidingMenu.BOTH); + sm.setBehindCanvasTransformer(mTransformer, SlidingMenu.BOTH); } @Override diff --git a/example/src/com/slidingmenu/example/CustomRotateAnimation.java b/example/src/com/slidingmenu/example/CustomRotateAnimation.java index a9f8d65ff..55e734c37 100644 --- a/example/src/com/slidingmenu/example/CustomRotateAnimation.java +++ b/example/src/com/slidingmenu/example/CustomRotateAnimation.java @@ -4,6 +4,7 @@ import android.os.Bundle; import android.view.animation.Interpolator; +import com.slidingmenu.lib.SlidingMenu; import com.slidingmenu.lib.SlidingMenu.CanvasTransformer; public class CustomRotateAnimation extends CustomAnimation { @@ -31,7 +32,7 @@ public void transformCanvas(Canvas canvas, float percentOpen) { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - getSlidingMenu().setBehindScrollScale(1); + getSlidingMenu().setBehindScrollScale(1, SlidingMenu.BOTH); } } diff --git a/example/src/com/slidingmenu/example/PropertiesActivity.java b/example/src/com/slidingmenu/example/PropertiesActivity.java index 7f8bd4a1a..14f0f3015 100644 --- a/example/src/com/slidingmenu/example/PropertiesActivity.java +++ b/example/src/com/slidingmenu/example/PropertiesActivity.java @@ -15,15 +15,15 @@ public class PropertiesActivity extends BaseActivity { public PropertiesActivity() { super(R.string.properties); } - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setSlidingActionBarEnabled(true); - + setContentView(R.layout.properties); - + // touch mode stuff RadioGroup touchAbove = (RadioGroup) findViewById(R.id.touch_above); touchAbove.check(R.id.touch_above_margin); @@ -40,7 +40,7 @@ public void onCheckedChanged(RadioGroup group, int checkedId) { } } }); - + RadioGroup touchBehind = (RadioGroup) findViewById(R.id.touch_behind); touchBehind.check(R.id.touch_behind_margin); touchBehind.setOnCheckedChangeListener(new OnCheckedChangeListener() { @@ -57,7 +57,7 @@ public void onCheckedChanged(RadioGroup group, int checkedId) { } }); - + // scroll scale stuff SeekBar scrollScale = (SeekBar) findViewById(R.id.scroll_scale); scrollScale.setMax(1000); @@ -70,11 +70,11 @@ public void onProgressChanged(SeekBar seekBar, int progress, public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { - getSlidingMenu().setBehindScrollScale((float) seekBar.getProgress()/seekBar.getMax()); + getSlidingMenu().setBehindScrollScale((float) seekBar.getProgress()/seekBar.getMax(), SlidingMenu.BOTH); } }); - - + + // behind width stuff SeekBar behindWidth = (SeekBar) findViewById(R.id.behind_width); behindWidth.setMax(1000); @@ -88,11 +88,11 @@ public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { float percent = (float) seekBar.getProgress()/seekBar.getMax(); - getSlidingMenu().setBehindWidth((int) (percent * getSlidingMenu().getWidth())); + getSlidingMenu().setBehindWidth((int) (percent * getSlidingMenu().getWidth()), SlidingMenu.BOTH); } }); - - + + // fading stuff CheckBox fadeEnabled = (CheckBox) findViewById(R.id.fade_enabled); fadeEnabled.setChecked(true); diff --git a/example/src/com/slidingmenu/example/SlidingTitleBar.java b/example/src/com/slidingmenu/example/SlidingTitleBar.java index b781a1ba5..f66600120 100644 --- a/example/src/com/slidingmenu/example/SlidingTitleBar.java +++ b/example/src/com/slidingmenu/example/SlidingTitleBar.java @@ -1,6 +1,9 @@ package com.slidingmenu.example; +import com.slidingmenu.lib.SlidingMenu; + import android.os.Bundle; +import android.support.v4.view.ViewPager; public class SlidingTitleBar extends BaseActivity { @@ -14,11 +17,17 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // set the Above View - setContentView(R.layout.content_frame); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.content_frame, new SampleListFragment()) - .commit(); +// setContentView(R.layout.content_frame); +// getSupportFragmentManager() +// .beginTransaction() +// .replace(R.id.content_frame, new SampleListFragment()) +// .commit(); + + ViewPager vp = new ViewPager(this); + vp.setId("VP".hashCode()); + vp.setAdapter(new PagerAdapter(getSupportFragmentManager(), vp)); + setContentView(vp); + getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); setSlidingActionBarEnabled(true); } diff --git a/library/AndroidManifest.xml b/library/AndroidManifest.xml index 86b1a3a77..6e6ac9404 100644 --- a/library/AndroidManifest.xml +++ b/library/AndroidManifest.xml @@ -11,10 +11,18 @@ - - - - + + + + \ No newline at end of file diff --git a/library/res/drawable/custom_up.xml b/library/res/drawable/custom_up.xml new file mode 100644 index 000000000..189367d0a --- /dev/null +++ b/library/res/drawable/custom_up.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/library/res/values/attrs.xml b/library/res/values/attrs.xml index 461440384..d65a6c56f 100644 --- a/library/res/values/attrs.xml +++ b/library/res/values/attrs.xml @@ -17,16 +17,22 @@ + + + + + - + + - + - + diff --git a/library/res/values/styles.xml b/library/res/values/styles.xml new file mode 100644 index 000000000..3df4c7504 --- /dev/null +++ b/library/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/library/src/com/slidingmenu/lib/CustomUpIndicator.java b/library/src/com/slidingmenu/lib/CustomUpIndicator.java new file mode 100644 index 000000000..4384cadb6 --- /dev/null +++ b/library/src/com/slidingmenu/lib/CustomUpIndicator.java @@ -0,0 +1,45 @@ +package com.slidingmenu.lib; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +public class CustomUpIndicator extends Drawable { + + public static Paint mPaint; + private RectF mRect; + + @Override + public void draw(Canvas canvas) { + // TODO Auto-generated method stub + mPaint.setARGB(0, 255, 0, 0); + + mRect.left = 0.0f; + mRect.top = 0.0f; + mRect.right = 50.0f; + mRect.bottom = 50.0f; + + canvas.drawRect(mRect, mPaint); + } + + @Override + public int getOpacity() { + return PixelFormat.OPAQUE; + } + + @Override + public void setAlpha(int alpha) { + // TODO Auto-generated method stub + + } + + @Override + public void setColorFilter(ColorFilter cf) { + // TODO Auto-generated method stub + + } + +} diff --git a/library/src/com/slidingmenu/lib/CustomViewAbove.java b/library/src/com/slidingmenu/lib/CustomViewAbove.java index 1628d4717..aaa293f9b 100644 --- a/library/src/com/slidingmenu/lib/CustomViewAbove.java +++ b/library/src/com/slidingmenu/lib/CustomViewAbove.java @@ -1,7 +1,10 @@ package com.slidingmenu.lib; import android.content.Context; -import android.graphics.*; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v4.view.KeyEventCompat; @@ -48,14 +51,16 @@ public float getInterpolation(float t) { } }; - private FrameLayout mMenu; - private FrameLayout mContent; + private FrameLayout mMenuLeft; + private FrameLayout mMenuRight; + protected FrameLayout mContent; private int mCurItem; private Scroller mScroller; private int mShadowWidth; - private Drawable mShadowDrawable; + private Drawable mShadowDrawableLeft; + private Drawable mShadowDrawableRight; private boolean mScrollingCacheEnabled; @@ -90,8 +95,9 @@ public float getInterpolation(float t) { private int mFlingDistance; private boolean mLastTouchAllowed = false; - private final int mSlidingMenuThreshold = 10; - private CustomViewBehind mCustomViewBehind; + private final int mSlidingMenuThreshold = 16; + private CustomViewBehind mViewBehindLeft; + private CustomViewBehind mViewBehindRight; private boolean mEnabled = true; private OnPageChangeListener mOnPageChangeListener; @@ -183,13 +189,23 @@ void initCustomViewAbove(boolean isAbove) { setInternalPageChangeListener(new SimpleOnPageChangeListener() { public void onPageSelected(int position) { - if (mCustomViewBehind != null) { + if (mViewBehindLeft != null) { switch (position) { case 0: - mCustomViewBehind.setChildrenEnabled(true); + mViewBehindLeft.setChildrenEnabled(true); break; case 1: - mCustomViewBehind.setChildrenEnabled(false); + mViewBehindLeft.setChildrenEnabled(false); + break; + } + } + if (mViewBehindRight != null) { + switch (position) { + case 1: + mViewBehindRight.setChildrenEnabled(false); + break; + case 2: + mViewBehindRight.setChildrenEnabled(true); break; } } @@ -200,10 +216,12 @@ public void onPageSelected(int position) { final float density = context.getResources().getDisplayMetrics().density; mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); - mMenu = new FrameLayout(getContext()); - super.addView(mMenu); + mMenuLeft = new FrameLayout(getContext()); + super.addView(mMenuLeft); mContent = new FrameLayout(getContext()); super.addView(mContent); + mMenuRight = new FrameLayout(getContext()); + super.addView(mMenuRight); if (isAbove) { View v = new LinearLayout(getContext()); @@ -243,18 +261,24 @@ void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { } void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { - if (!always && mCurItem == item && mMenu != null && mContent != null) { + if (!always && mCurItem == item && mMenuLeft != null && mContent != null) { setScrollingCacheEnabled(false); return; } - if (item < 0) { - item = 0; - } else if (item >= 2) { - item = 1; + + int start = mViewBehindLeft == null ? 1 : 0; + int end = mViewBehindRight == null ? 1 : 2; + // TODO count accordingly + if (item < start) { + item = start; + } else if (item > end) { + item = end; } + final boolean dispatchSelected = mCurItem != item; mCurItem = item; - final int destX = getChildLeft(mCurItem); + final int destX = this.getDestScrollX(mCurItem); + if (dispatchSelected && mOnPageChangeListener != null) { mOnPageChangeListener.onPageSelected(item); } @@ -334,10 +358,16 @@ public int getShadowWidth() { * * @param d Drawable to display between pages */ - public void setShadowDrawable(Drawable d) { - mShadowDrawable = d; + public void setShadowDrawable(Drawable d, int side) { + if (side == SlidingMenu.LEFT) { + mShadowDrawableLeft = d; + } else if (side == SlidingMenu.RIGHT) { + mShadowDrawableRight = d; + } else if (side == SlidingMenu.BOTH) { + mShadowDrawableLeft = d; + mShadowDrawableRight = d; + } if (d != null) refreshDrawableState(); - setWillNotDraw(d == null); invalidate(); } @@ -346,21 +376,21 @@ public void setShadowDrawable(Drawable d) { * * @param resId Resource ID of a drawable to display between pages */ - public void setShadowDrawable(int resId) { - setShadowDrawable(getContext().getResources().getDrawable(resId)); + public void setShadowDrawable(int resId, int side) { + setShadowDrawable(getContext().getResources().getDrawable(resId), side); } @Override protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == mShadowDrawable; + return super.verifyDrawable(who) || who == mShadowDrawableLeft || who == mShadowDrawableRight; } @Override protected void drawableStateChanged() { super.drawableStateChanged(); - final Drawable d = mShadowDrawable; + final Drawable d = mShadowDrawableLeft; if (d != null && d.isStateful()) { d.setState(getDrawableState()); } @@ -376,11 +406,31 @@ float distanceInfluenceForSnapDuration(float f) { return (float) FloatMath.sin(f); } - public int getDestScrollX() { - if (isMenuOpen()) { - return getBehindWidth(); + public int getDestScrollX(int i) { + switch (i) { + case 0: + return 0; + case 1: + return mContent.getLeft(); + case 2: + return mContent.getLeft() + mViewBehindRight.getWidth(); + } + throw new RuntimeException("This should never happen!"); + } + + public int getRightScrollBound() { + if (mViewBehindRight != null) { + return mContent.getLeft() + mViewBehindRight.getWidth(); } else { + return mContent.getLeft(); + } + } + + public int getLeftScrollBound() { + if (mViewBehindLeft != null) { return 0; + } else { + return mContent.getLeft(); } } @@ -393,28 +443,49 @@ public int getChildRight(int i) { return getChildLeft(i) + getChildWidth(i); } - public boolean isMenuOpen() { + public boolean isRightOpen() { + if (mViewBehindRight == null) + return false; + + return getCurrentItem() == 2; + } + + public boolean isLeftOpen() { + if (mViewBehindLeft == null) { + return false; + } + return getCurrentItem() == 0; } public int getCustomWidth() { - int i = isMenuOpen()? 0 : 1; + int i = 1; + i = isLeftOpen()? 0 : i; + i = isRightOpen()? 2 : i; return getChildWidth(i); } public int getChildWidth(int i) { - if (i <= 0) { - return getBehindWidth(); - } else { - return getChildAt(i).getWidth(); - } + try { + switch (i) { + case 0: + return mViewBehindLeft.getWidth(); + case 1: + return mContent.getWidth(); + case 2: + return mViewBehindRight.getWidth(); + } + } catch (NullPointerException e) { } + return 0; } public int getBehindWidth() { - if (mCustomViewBehind == null) { - return 0; + if (mViewBehindLeft != null) { + return mViewBehindLeft.getWidth(); + } else if (mViewBehindRight != null) { + return mViewBehindRight.getWidth(); } else { - return mCustomViewBehind.getWidth(); + return 0; } } @@ -455,10 +526,14 @@ void smoothScrollTo(int x, int y, int velocity) { int dy = y - sy; if (dx == 0 && dy == 0) { completeScroll(); - if (isMenuOpen()) { + if (isLeftOpen()) { + if (mOpenedListener != null) + mOpenedListener.onOpened(SlidingMenu.LEFT); + } else if (isRightOpen()) { if (mOpenedListener != null) - mOpenedListener.onOpened(); + mOpenedListener.onOpened(SlidingMenu.RIGHT); } else { + if (mClosedListener != null) mClosedListener.onClosed(); } @@ -490,21 +565,26 @@ void smoothScrollTo(int x, int y, int velocity) { } protected void setMenu(View v) { - if (mMenu.getChildCount() > 0) { - mMenu.removeAllViews(); + if (mMenuLeft.getChildCount() > 0) { + mMenuLeft.removeAllViews(); } - mMenu.addView(v); + mMenuLeft.addView(v); } public void setContent(View v) { if (mContent.getChildCount() > 0) { mContent.removeAllViews(); } - mContent.addView(v); + if (v != null) + mContent.addView(v); } - public void setCustomViewBehind(CustomViewBehind cvb) { - mCustomViewBehind = cvb; + public void setViewBehindLeft(CustomViewBehind cvb) { + mViewBehindLeft = cvb; + } + + public void setViewBehindRight(CustomViewBehind cvb) { + mViewBehindRight = cvb; } @Override @@ -519,7 +599,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mContent.measure(contentWidth, contentHeight); final int menuWidth = getChildMeasureSpec(widthMeasureSpec, 0, getBehindWidth()); - mMenu.measure(menuWidth, contentHeight); + mMenuLeft.measure(menuWidth, contentHeight); + mMenuRight.measure(menuWidth, contentHeight); } @Override @@ -541,10 +622,10 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { final int height = b - t; int contentLeft = getChildLeft(1); - float percentOpen = getPercentOpen(); - int offset = (int) (mScrollX * (1 - mScrollScale)); - mMenu.layout(0, 0, width, height); + mMenuLeft.layout(0, 0, width, height); mContent.layout(contentLeft, 0, contentLeft + width, height); + mMenuRight.layout(contentLeft + width, 0, contentLeft + 2*width, height); + this.setCurrentItemInternal(mCurItem, false, true); } @@ -616,9 +697,12 @@ private void completeScroll() { if (oldX != x || oldY != y) { scrollTo(x, y); } - if (isMenuOpen()) { + if (isLeftOpen()) { if (mOpenedListener != null) - mOpenedListener.onOpened(); + mOpenedListener.onOpened(SlidingMenu.LEFT); + } else if (isRightOpen()) { + if (mOpenedListener != null) + mOpenedListener.onOpened(SlidingMenu.RIGHT); } else { if (mClosedListener != null) mClosedListener.onClosed(); @@ -647,12 +731,22 @@ protected int getTouchModeBehind() { } private boolean thisTouchAllowed(MotionEvent ev) { - if (isMenuOpen()) { + int x = (int) (ev.getX() + mScrollX); + if (isLeftOpen()) { + switch (mTouchModeBehind) { + case SlidingMenu.TOUCHMODE_FULLSCREEN: + return true; + case SlidingMenu.TOUCHMODE_MARGIN: + return x >= getBehindWidth() && x <= getWidth(); + default: + return false; + } + } else if (isRightOpen()) { switch (mTouchModeBehind) { case SlidingMenu.TOUCHMODE_FULLSCREEN: return true; case SlidingMenu.TOUCHMODE_MARGIN: - return ev.getX() >= getBehindWidth() && ev.getX() <= getWidth(); + return x <= mContent.getRight(); default: return false; } @@ -663,12 +757,35 @@ private boolean thisTouchAllowed(MotionEvent ev) { case SlidingMenu.TOUCHMODE_MARGIN: int pixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mSlidingMenuThreshold, getResources().getDisplayMetrics()); - return ev.getX() >= 0 && ev.getX() <= pixels; + int left = mContent.getLeft(); + int right = mContent.getRight(); + boolean bool = false; + if (mViewBehindLeft != null) + bool |= (x >= left && x <= pixels + left); + if (mViewBehindRight != null) + bool |= (x <= right && x >= right - pixels); + return bool; default: return false; } } } + + private boolean thisSlideAllowed(float dx) { + boolean allowed = false; + if (isLeftOpen()) { + allowed = dx < 0; + } else if (isRightOpen()) { + allowed = dx > 0; + } else { + if (mViewBehindLeft != null) + allowed |= dx > 0; + if (mViewBehindRight != null) + allowed |= dx < 0; + } + Log.v(TAG, "this slide allowed " + allowed); + return allowed; + } private boolean mIsUnableToDrag; @@ -681,9 +798,6 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; - if (action == MotionEvent.ACTION_DOWN) - Log.v(TAG, "Received ACTION_DOWN"); - if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { mIsBeingDragged = false; mIsUnableToDrag = false; @@ -714,7 +828,7 @@ else if (mIsUnableToDrag) final float xDiff = Math.abs(dx); final float y = MotionEventCompat.getY(ev, pointerIndex); final float yDiff = Math.abs(y - mLastMotionY); - if (xDiff > mTouchSlop && xDiff > yDiff) { + if (xDiff > mTouchSlop && xDiff > yDiff && thisSlideAllowed(dx)) { if (DEBUG) Log.v(TAG, "Starting drag! from onInterceptTouch"); mIsBeingDragged = true; mLastMotionX = x; @@ -725,15 +839,13 @@ else if (mIsUnableToDrag) break; case MotionEvent.ACTION_DOWN: - mActivePointerId = ev.getAction() & ((Build.VERSION.SDK_INT >= 8) ? MotionEvent.ACTION_POINTER_INDEX_MASK : - MotionEvent.ACTION_POINTER_ID_MASK); - Log.v(TAG, "active pointer id : " + mActivePointerId); + mActivePointerId = ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK; mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, mActivePointerId); mLastMotionY = MotionEventCompat.getY(ev, mActivePointerId); if (thisTouchAllowed(ev)) { mIsBeingDragged = false; mIsUnableToDrag = false; - if (isMenuOpen() && mInitialMotionX > getBehindWidth()) + if ((isLeftOpen() || isRightOpen()) && mTouchModeBehind == SlidingMenu.TOUCHMODE_MARGIN) return true; } else { mIsUnableToDrag = true; @@ -816,8 +928,8 @@ public boolean onTouchEvent(MotionEvent ev) { mLastMotionX = x; float oldScrollX = getScrollX(); float scrollX = oldScrollX + deltaX; - final float leftBound = 0; - final float rightBound = getBehindWidth(); + final float leftBound = getLeftScrollBound(); + final float rightBound = getRightScrollBound(); if (scrollX < leftBound) { scrollX = leftBound; } else if (scrollX > rightBound) { @@ -835,23 +947,24 @@ public boolean onTouchEvent(MotionEvent ev) { velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( velocityTracker, mActivePointerId); - final int widthWithMargin = getChildWidth(mCurItem) + mShadowWidth; + final int widthWithMargin = getChildWidth(mCurItem); final int scrollX = getScrollX(); - final int currentPage = scrollX / widthWithMargin; final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin; final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, activePointerIndex); final int totalDelta = (int) (x - mInitialMotionX); - int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, + int nextPage = determineTargetPage(mCurItem, pageOffset, initialVelocity, totalDelta); setCurrentItemInternal(nextPage, true, true, initialVelocity); mActivePointerId = INVALID_POINTER; endDrag(); - } else if (isMenuOpen()) { + } else if (isLeftOpen()) { // close the menu setCurrentItem(1); + } else if (isRightOpen()) { + setCurrentItem(1); } break; case MotionEvent.ACTION_CANCEL: @@ -879,84 +992,110 @@ public boolean onTouchEvent(MotionEvent ev) { return true; } - private float mScrollScale; + private float mScrollScaleLeft; + private float mScrollScaleRight; - public float getScrollScale() { - return mScrollScale; + public float getScrollScale(int side) { + if (side == SlidingMenu.LEFT) { + return mScrollScaleLeft; + } else { + return mScrollScaleRight; + } } - public void setScrollScale(float f) { + public void setScrollScale(float f, int side) { if (f < 0 && f > 1) - throw new IllegalStateException("ScrollScale must be between 0 and 1"); - mScrollScale = f; + throw new IllegalArgumentException("ScrollScale must be between 0 and 1"); + if (side == SlidingMenu.LEFT) { + mScrollScaleLeft = f; + } else if (side == SlidingMenu.RIGHT) { + mScrollScaleRight = f; + } else if (side == SlidingMenu.BOTH) { + mScrollScaleLeft = f; + mScrollScaleRight = f; + } } @Override public void scrollTo(int x, int y) { super.scrollTo(x, y); mScrollX = x; - if (mCustomViewBehind != null && mEnabled) { - mCustomViewBehind.scrollTo((int)(x*mScrollScale), y); + // adjust visibility so we don't have any layout issues + if (mViewBehindLeft != null) { + if (x < getBehindWidth()) { + if (mViewBehindLeft.getVisibility() != View.VISIBLE) { + mViewBehindLeft.setVisibility(View.VISIBLE); + } + } else if (mViewBehindLeft.getVisibility() != View.INVISIBLE){ + mViewBehindLeft.setVisibility(View.INVISIBLE); + } + } + if (mViewBehindRight != null) { + if (x > mContent.getLeft()) { + if (mViewBehindRight.getVisibility() != View.VISIBLE) { + mViewBehindRight.setVisibility(View.VISIBLE); + } + } else if (mViewBehindRight.getVisibility() != View.INVISIBLE){ + mViewBehindRight.setVisibility(View.INVISIBLE); + } } - if (mShadowDrawable != null || mSelectorDrawable != null) + // scroll the behind views + if (mViewBehindLeft != null && mEnabled) { + mViewBehindLeft.scrollTo((int)(x*mScrollScaleLeft), y); + } + if (mViewBehindRight != null && mEnabled) { + int x2 = (int) ((x - mContent.getLeft() - mViewBehindRight.getWidth()) * mScrollScaleRight); + Log.v(TAG, "scrolling right to " + x2); + mViewBehindRight.scrollTo(x2, y); + } + + if (mShadowDrawableLeft != null || mSelectorDrawable != null) invalidate(); } private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { int targetPage; - if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { - targetPage = velocity > 0 ? currentPage : currentPage + 1; + if (Math.abs(deltaX) > (float)mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { + targetPage = velocity > 0 ? currentPage - 1 : currentPage + 1; } else { - targetPage = (int) (currentPage + pageOffset + 0.5f); + targetPage = (int) ((deltaX > 0) ? + (currentPage + pageOffset - 0.5f) : (currentPage - pageOffset + 0.5f)); + if ((deltaX > 0 && targetPage > currentPage) || (deltaX < 0 && targetPage < currentPage)) + targetPage = currentPage; } return targetPage; } - protected float getPercentOpen() { - return (getBehindWidth() - mScrollX) / getBehindWidth(); + protected float getPercentOpenLeft() { + return (getBehindWidth() - mScrollX) / mViewBehindLeft.getWidth(); + } + + protected float getPercentOpenRight() { + return (getWidth() - (mContent.getRight() - mScrollX)) / mViewBehindRight.getWidth(); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); final int behindWidth = getBehindWidth(); - // Draw the margin drawable if needed. - if (mShadowWidth > 0 && mShadowDrawable != null) { - final int left = behindWidth - mShadowWidth; - mShadowDrawable.setBounds(left, 0, left + mShadowWidth, getHeight()); - mShadowDrawable.draw(canvas); + // Draw the margin drawable if needed + if (mShadowWidth > 0) { + if (mShadowDrawableLeft != null) { + final int left = behindWidth - mShadowWidth; + mShadowDrawableLeft.setBounds(left, 0, left + mShadowWidth, getHeight()); + mShadowDrawableLeft.draw(canvas); + } + if (mShadowDrawableRight != null) { + mShadowDrawableRight.setBounds(mContent.getRight(), 0, mContent.getRight() + mShadowWidth, getHeight()); + mShadowDrawableRight.draw(canvas); + } } if (mFadeEnabled) - onDrawBehindFade(canvas, getPercentOpen()); + onDrawBehindFade(canvas); if (mSelectorEnabled) - onDrawMenuSelector(canvas, getPercentOpen()); - } - - /** - * Pads our content window so that it fits within the system windows. - * @param insets The insets by which we need to offset our view. - * @return True since we handled the padding change. - */ - @Override - protected boolean fitSystemWindows(Rect insets) { - - if (mContent != null) { - int leftPadding = mContent.getPaddingLeft() + insets.left; - int rightPadding = mContent.getPaddingRight() + insets.right; - int topPadding = mContent.getPaddingTop() + insets.top; - int bottomPadding = mContent.getPaddingBottom() + insets.bottom; - mContent.setPadding(leftPadding, topPadding, rightPadding, bottomPadding); - return true; - } - - return super.fitSystemWindows(insets); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); + onDrawMenuSelector(canvas); } // variables for drawing @@ -970,21 +1109,31 @@ protected void onDraw(Canvas canvas) { private Bitmap mSelectorDrawable; private View mSelectedView; - - private void onDrawBehindFade(Canvas canvas, float openPercent) { - final int alpha = (int) (mFadeDegree * 255 * Math.abs(1-openPercent)); - if (alpha > 0) { - mBehindFadePaint.setColor(Color.argb(alpha, 0, 0, 0)); - canvas.drawRect(0, 0, getBehindWidth(), getHeight(), mBehindFadePaint); + private void onDrawBehindFade(Canvas canvas) { + int alpha; + if (mViewBehindLeft != null) { + alpha = (int) (mFadeDegree * 255 * Math.abs(1-getPercentOpenLeft())); + if (alpha > 0) { + mBehindFadePaint.setColor(Color.argb(alpha, 0, 0, 0)); + canvas.drawRect(0, 0, getBehindWidth(), getHeight(), mBehindFadePaint); + } + } + if (mViewBehindRight != null) { + alpha = (int) (mFadeDegree * 255 * Math.abs(1-getPercentOpenRight())); + if (alpha > 0) { + mBehindFadePaint.setColor(Color.argb(alpha, 0, 0, 0)); + canvas.drawRect(mContent.getRight(), 0, mContent.getRight() + mViewBehindRight.getWidth(), + getHeight(), mBehindFadePaint); + } } } - private void onDrawMenuSelector(Canvas canvas, float openPercent) { + private void onDrawMenuSelector(Canvas canvas) { if (mSelectorDrawable != null && mSelectedView != null) { String tag = (String) mSelectedView.getTag(R.id.selected_view); if (tag.equals(TAG+"SelectedView")) { int right = getChildLeft(1); - int left = (int) (right - mSelectorDrawable.getWidth() * openPercent); + int left = (int) (right - mSelectorDrawable.getWidth() * getPercentOpenLeft()); canvas.save(); canvas.clipRect(left, 0, right, getHeight()); diff --git a/library/src/com/slidingmenu/lib/CustomViewBehind.java b/library/src/com/slidingmenu/lib/CustomViewBehind.java index 7fe8d3829..abd134381 100644 --- a/library/src/com/slidingmenu/lib/CustomViewBehind.java +++ b/library/src/com/slidingmenu/lib/CustomViewBehind.java @@ -8,23 +8,26 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.Transformation; +import android.widget.RelativeLayout; import com.slidingmenu.lib.SlidingMenu.CanvasTransformer; public class CustomViewBehind extends CustomViewAbove { private static final String TAG = "CustomViewBehind"; + public static final int LEFT = 0; + public static final int RIGHT = 1; private CustomViewAbove mViewAbove; + private int mMode; private CanvasTransformer mTransformer; private boolean mChildrenEnabled; - public CustomViewBehind(Context context) { - this(context, null); - } - - public CustomViewBehind(Context context, AttributeSet attrs) { - super(context, attrs, false); + public CustomViewBehind(Context context, int mode) { + super(context); + if (mode != LEFT && mode != RIGHT) + throw new IllegalStateException("mode must be LEFT or RIGHT"); + mMode = mode; } public void setCustomViewAbove(CustomViewAbove customViewAbove) { @@ -45,10 +48,17 @@ public void setCanvasTransformer(CanvasTransformer t) { public int getChildLeft(int i) { return 0; } + + @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); + } @Override public int getCustomWidth() { - int i = isMenuOpen()? 0 : 1; + int i = isLeftOpen()? 0 : 1; return getChildWidth(i); } @@ -66,11 +76,6 @@ public int getBehindWidth() { return params.width; } - @Override - public void setContent(View v) { - super.setMenu(v); - } - public void setChildrenEnabled(boolean enabled) { mChildrenEnabled = enabled; } @@ -96,7 +101,16 @@ public boolean onTouchEvent(MotionEvent e) { protected void dispatchDraw(Canvas canvas) { if (mTransformer != null) { canvas.save(); - mTransformer.transformCanvas(canvas, mViewAbove.getPercentOpen()); + float percent = 0.0f; + switch (mMode) { + case LEFT: + percent = mViewAbove.getPercentOpenLeft(); + break; + case RIGHT: + percent = mViewAbove.getPercentOpenRight(); + break; + } + mTransformer.transformCanvas(canvas, percent); super.dispatchDraw(canvas); canvas.restore(); } else diff --git a/library/src/com/slidingmenu/lib/SlidingMenu.java b/library/src/com/slidingmenu/lib/SlidingMenu.java index 3564719ec..e7cd4fc93 100644 --- a/library/src/com/slidingmenu/lib/SlidingMenu.java +++ b/library/src/com/slidingmenu/lib/SlidingMenu.java @@ -15,6 +15,7 @@ import android.support.v4.os.ParcelableCompat; import android.support.v4.os.ParcelableCompatCreatorCallbacks; import android.util.AttributeSet; +import android.util.Log; import android.view.Display; import android.view.LayoutInflater; import android.view.View; @@ -27,20 +28,27 @@ public class SlidingMenu extends RelativeLayout { + public static final String TAG = "SlidingMenu"; + public static final int TOUCHMODE_MARGIN = 0; public static final int TOUCHMODE_FULLSCREEN = 1; + public static final int LEFT = 0x0100; + public static final int RIGHT = 0x1000; + public static final int BOTH = LEFT | RIGHT; + private CustomViewAbove mViewAbove; - private CustomViewBehind mViewBehind; + private CustomViewBehind mViewBehindLeft; + private CustomViewBehind mViewBehindRight; private OnOpenListener mOpenListener; private OnCloseListener mCloseListener; - private boolean mSlidingEnabled; + private boolean mSlidingEnabled; + private int mMode; public static void attachSlidingMenu(Activity activity, SlidingMenu sm, boolean slidingTitle) { - if (sm.getParent() != null) - throw new IllegalStateException("SlidingMenu cannot be attached to another view when" + + throw new IllegalArgumentException("SlidingMenu cannot be attached to another view when" + " calling the static method attachSlidingMenu"); if (slidingTitle) { @@ -70,7 +78,7 @@ public interface OnOpenListener { } public interface OnOpenedListener { - public void onOpened(); + public void onOpened(int side); } public interface OnCloseListener { @@ -95,25 +103,20 @@ public SlidingMenu(Context context, AttributeSet attrs) { 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); + // above view LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); mViewAbove = new CustomViewAbove(context); addView(mViewAbove, aboveParams); - // register the CustomViewBehind2 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_LEFT_OPEN = 0; public static final int POSITION_CLOSE = 1; + public static final int POSITION_RIGHT_OPEN = 2; public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } public void onPageSelected(int position) { - if (position == POSITION_OPEN && mOpenListener != null) { + if ((position == POSITION_LEFT_OPEN || position == POSITION_RIGHT_OPEN) && mOpenListener != null) { mOpenListener.onOpen(); } else if (position == POSITION_CLOSE && mCloseListener != null) { mCloseListener.onClose(); @@ -125,31 +128,37 @@ public void onPageSelected(int position) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); // set the above and behind views if defined in xml int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1); - if (viewAbove != -1) + if (viewAbove != -1) { setContent(viewAbove); - int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1); - if (viewBehind != -1) - setMenu(viewBehind); - int touchModeAbove = ta.getInt(R.styleable.SlidingMenu_aboveTouchMode, TOUCHMODE_MARGIN); + } + int viewBehindLeft = ta.getResourceId(R.styleable.SlidingMenu_viewBehindLeft, -1); + if (viewBehindLeft != -1) { + mMode |= LEFT; + setViewBehind(viewBehindLeft, LEFT); + } + int viewBehindRight = ta.getResourceId(R.styleable.SlidingMenu_viewBehindRight, -1); + if (viewBehindRight != -1) { + mMode |= RIGHT; + setViewBehind(viewBehindRight, RIGHT); + } + int touchModeAbove = ta.getInt(R.styleable.SlidingMenu_touchModeAbove, TOUCHMODE_MARGIN); setTouchModeAbove(touchModeAbove); - int touchModeBehind = ta.getInt(R.styleable.SlidingMenu_behindTouchMode, TOUCHMODE_MARGIN); + 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) + 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); + } else if (offsetBehind != -1) { + setBehindOffset(offsetBehind, mMode); + } else if (widthBehind != -1) { + setBehindWidth(widthBehind, mMode); + } float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.33f); - setBehindScrollScale(scrollOffsetBehind); + setBehindScrollScale(scrollOffsetBehind, mMode); int shadowRes = ta.getResourceId(R.styleable.SlidingMenu_shadowDrawable, -1); if (shadowRes != -1) { - setShadowDrawable(shadowRes); + setShadowDrawable(shadowRes, mMode); } int shadowWidth = (int) ta.getDimension(R.styleable.SlidingMenu_shadowWidth, 0); setShadowWidth(shadowWidth); @@ -164,6 +173,38 @@ else if (widthBehind != -1) setSelectorDrawable(selectorRes); } + private void initializeLeft() { + if (mViewBehindLeft == null) { + LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mViewBehindLeft = new CustomViewBehind(getContext(), CustomViewBehind.LEFT); + addView(mViewBehindLeft, 0, behindParams); + mViewAbove.setViewBehindLeft(mViewBehindLeft); + mViewBehindLeft.setCustomViewAbove(mViewAbove); + } + } + + private void initializeRight() { + if (mViewBehindRight == null) { + LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mViewBehindRight = new CustomViewBehind(getContext(), CustomViewBehind.RIGHT); + addView(mViewBehindRight, 0, behindParams); + mViewAbove.setViewBehindRight(mViewBehindRight); + mViewBehindRight.setCustomViewAbove(mViewAbove); + } + } + + public void removeViewBehind(int side) { + if (isLeft(side)) { + mViewAbove.setViewBehindLeft(null); + removeView(mViewBehindLeft); + mViewBehindLeft = null; + } else if (isRight(side)) { + mViewAbove.setViewBehindRight(null); + removeView(mViewBehindRight); + mViewBehindRight = null; + } + } + public void setContent(int res) { setContent(LayoutInflater.from(getContext()).inflate(res, null)); } @@ -174,13 +215,54 @@ public void setContent(View v) { showAbove(); } - public void setMenu(int res) { - setMenu(LayoutInflater.from(getContext()).inflate(res, null)); + public void setViewBehind(int res, int side) { + setViewBehind(LayoutInflater.from(getContext()).inflate(res, null), side); + } + + public void setViewBehind(View v, int side) { + checkSide(side); + if (side == LEFT) { + initializeLeft(); + if (v == null) { + removeViewBehind(LEFT); + } else { + initializeLeft(); + mViewBehindLeft.setContent(v); + mViewBehindLeft.invalidate(); + } + } else { + initializeRight(); + if (v == null) { + removeViewBehind(RIGHT); + } else { + initializeRight(); + mViewBehindRight.setContent(v); + mViewBehindRight.invalidate(); + } + } + } + + private void checkSide(int side) { + if (!isLeft(side) && !isRight(side)) + throw new IllegalArgumentException("Side must be SlidingMenu.LEFT or SlidingMenu.RIGHT"); + } + + private void checkSideStrict(int side) { + checkSide(side); + if (isLeft(side) && mViewBehindLeft == null) + throw new IllegalArgumentException("You have to add a behind left " + + "view before you can reference it"); + if (isRight(side) && mViewBehindRight == null) + throw new IllegalArgumentException("You have to add a behind right " + + "view before you can reference it"); + } + + private boolean isLeft(int side) { + return (side & LEFT) == LEFT; } - public void setMenu(View v) { - mViewBehind.setMenu(v); - mViewBehind.invalidate(); + private boolean isRight(int side) { + return (side & RIGHT) == RIGHT; } public void setSlidingEnabled(boolean b) { @@ -191,30 +273,20 @@ public boolean isSlidingEnabled() { return mViewAbove.isSlidingEnabled(); } - /** - * - * @param b Whether or not the SlidingMenu is in a static mode - * (i.e. nothing is moving and everything is showing) - */ - 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); - } - } - /** * Shows the behind view */ - public void showBehind() { - mViewAbove.setCurrentItem(0); + public void showBehind(int side) { + checkSideStrict(side); + + if (isLeft(side) && isRight(side)) + throw new IllegalArgumentException("Can't show both left and right"); + + if (isLeft(side)) { + mViewAbove.setCurrentItem(0); + } else if (isRight(side)) { + mViewAbove.setCurrentItem(2); + } } /** @@ -225,35 +297,64 @@ public void showAbove() { } /** - * + * * @return Whether or not the behind view is showing */ public boolean isBehindShowing() { - return mViewAbove.getCurrentItem() == 0; + return mViewAbove.getCurrentItem() == 0 || mViewAbove.getCurrentItem() == 2; } /** - * + * * @return The margin on the right of the screen that the behind view scrolls to */ - public int getBehindOffset() { - return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin; + public int getBehindOffset(int side) { + checkSideStrict(side); + if (isLeft(side)) { + return ((RelativeLayout.LayoutParams)mViewBehindLeft.getLayoutParams()).rightMargin; + } else { + return ((RelativeLayout.LayoutParams)mViewBehindRight.getLayoutParams()).leftMargin; + } } /** - * + * * @param i The margin 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); + public void setBehindOffset(int i, int side) { + checkSideStrict(side); + if (isLeft(side)) { + // behind left + RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mViewBehindLeft.getLayoutParams()); + int bottom = params.bottomMargin; + int top = params.topMargin; + int left = params.leftMargin; + params.setMargins(left, top, i, bottom); + } + if (isRight(side)) { + // behind right + RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mViewBehindRight.getLayoutParams()); + int bottom = params.bottomMargin; + int top = params.topMargin; + int right = params.rightMargin; + Log.v(TAG, "left margin" + i); + params.setMargins(i, top, right, bottom); + } + requestLayout(); + showAbove(); + } + + /** + * + * @param res The dimension resource to be set as the behind offset + */ + public void setBehindOffsetRes(int res, int side) { + int i = (int) getContext().getResources().getDimension(res); + setBehindOffset(i, side); } @SuppressWarnings("deprecation") - public void setBehindWidth(int i) { + public void setBehindWidth(int i, int side) { int width; Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); @@ -267,37 +368,34 @@ public void setBehindWidth(int i) { } catch (Exception e) { width = display.getWidth(); } - setBehindOffset(width-i); - } - - /** - * - * @param res The dimension resource to be set as the behind offset - */ - public void setBehindOffsetRes(int res) { - int i = (int) getContext().getResources().getDimension(res); - setBehindOffset(i); + setBehindOffset(width-i, side); } /** - * + * * @return The scale of the parallax scroll */ - public float getBehindScrollScale() { - return mViewAbove.getScrollScale(); + public float getBehindScrollScale(int side) { + return mViewAbove.getScrollScale(side); } /** - * + * * @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) { - mViewAbove.setScrollScale(f); + public void setBehindScrollScale(float f, int side) { + mViewAbove.setScrollScale(f, side); } - public void setBehindCanvasTransformer(CanvasTransformer t) { - mViewBehind.setCanvasTransformer(t); + public void setBehindCanvasTransformer(CanvasTransformer t, int side) { + checkSideStrict(side); + if (isLeft(side)) { + mViewBehindLeft.setCanvasTransformer(t); + } + if (isRight(side)) { + mViewBehindRight.setCanvasTransformer(t); + } } public int getTouchModeAbove() { @@ -306,26 +404,26 @@ public int getTouchModeAbove() { public void setTouchModeAbove(int i) { if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN) { - throw new IllegalStateException("TouchMode must be set to either" + + throw new IllegalArgumentException("TouchMode must be set to either" + "TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN."); } mViewAbove.setTouchMode(i); } public int getTouchModeBehind() { - return mViewBehind.getTouchMode(); + return mViewAbove.getTouchModeBehind(); } public void setTouchModeBehind(int i) { if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN) { - throw new IllegalStateException("TouchMode must be set to either" + + throw new IllegalArgumentException("TouchMode must be set to either " + "TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN."); } - mViewBehind.setTouchMode(i); + mViewAbove.setTouchModeBehind(i); } - public void setShadowDrawable(int resId) { - mViewAbove.setShadowDrawable(resId); + public void setShadowDrawable(int resId, int side) { + mViewAbove.setShadowDrawable(resId, side); } public void setShadowWidthRes(int resId) { @@ -380,6 +478,7 @@ public void setOnClosedListener(OnClosedListener listener) { private static class SavedState extends BaseSavedState { boolean mBehindShowing; + int mMode; public SavedState(Parcelable superState) { super(superState); @@ -387,7 +486,8 @@ public SavedState(Parcelable superState) { public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); - out.writeBooleanArray(new boolean[]{mBehindShowing}); + out.writeValue(mBehindShowing); + out.writeInt(mMode); } public static final Parcelable.Creator CREATOR @@ -404,9 +504,8 @@ public SavedState[] newArray(int size) { SavedState(Parcel in) { super(in); - boolean[] showing = new boolean[1]; - in.readBooleanArray(showing); - mBehindShowing = showing[0]; + mBehindShowing = (Boolean) in.readValue(null); + mMode = in.readInt(); } } @@ -415,6 +514,7 @@ protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.mBehindShowing = isBehindShowing(); + ss.mMode = mMode; return ss; } @@ -429,7 +529,7 @@ protected void onRestoreInstanceState(Parcelable state) { super.onRestoreInstanceState(ss.getSuperState()); if (ss.mBehindShowing) { - showBehind(); + showBehind(ss.mMode); } else { showAbove(); } @@ -438,13 +538,14 @@ protected void onRestoreInstanceState(Parcelable state) { @Override protected boolean fitSystemWindows(Rect insets) { - int leftPadding = getPaddingLeft() + insets.left; - int rightPadding = getPaddingRight() + insets.right; - int topPadding = getPaddingTop() + insets.top; - int bottomPadding = getPaddingBottom() + insets.bottom; - this.setPadding(leftPadding, topPadding, rightPadding, bottomPadding); + int leftPadding = getPaddingLeft() + insets.left; + int rightPadding = getPaddingRight() + insets.right; + int topPadding = insets.top; + int bottomPadding = insets.bottom; + this.setPadding(leftPadding, topPadding, rightPadding, bottomPadding); - return super.fitSystemWindows(insets); + // return false to propagate the fit to our child views + return false; } } \ No newline at end of file diff --git a/library/src/com/slidingmenu/lib/app/SlidingActivity.java b/library/src/com/slidingmenu/lib/app/SlidingActivity.java index fb74ec180..88341b1c9 100644 --- a/library/src/com/slidingmenu/lib/app/SlidingActivity.java +++ b/library/src/com/slidingmenu/lib/app/SlidingActivity.java @@ -49,32 +49,46 @@ public void setContentView(View v, LayoutParams params) { mHelper.registerAboveContentView(v, params); } - public void setBehindContentView(int id) { - setBehindContentView(getLayoutInflater().inflate(id, null)); + // behind left view + public void setBehindLeftContentView(int id) { + setBehindLeftContentView(getLayoutInflater().inflate(id, null)); } - public void setBehindContentView(View v) { - setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + public void setBehindLeftContentView(View v) { + setBehindLeftContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } - public void setBehindContentView(View v, LayoutParams params) { - mHelper.setBehindContentView(v, params); + public void setBehindLeftContentView(View v, LayoutParams params) { + mHelper.setBehindLeftContentView(v); + } + + // behind right view + public void setBehindRightContentView(int id) { + setBehindRightContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindRightContentView(View v) { + setBehindRightContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + public void setBehindRightContentView(View v, LayoutParams params) { + mHelper.setBehindRightContentView(v); } public SlidingMenu getSlidingMenu() { return mHelper.getSlidingMenu(); } - public void toggle() { - mHelper.toggle(); + public void toggle(int side) { + mHelper.toggle(side); } public void showAbove() { mHelper.showAbove(); } - public void showBehind() { - mHelper.showBehind(); + public void showBehind(int side) { + mHelper.showBehind(side); } public void setSlidingActionBarEnabled(boolean b) { diff --git a/library/src/com/slidingmenu/lib/app/SlidingActivityBase.java b/library/src/com/slidingmenu/lib/app/SlidingActivityBase.java index 319b86e75..14f0b4a0a 100644 --- a/library/src/com/slidingmenu/lib/app/SlidingActivityBase.java +++ b/library/src/com/slidingmenu/lib/app/SlidingActivityBase.java @@ -7,14 +7,16 @@ public interface SlidingActivityBase { - public void setBehindContentView(View v, LayoutParams p); + public void setBehindLeftContentView(View v, LayoutParams p); + + public void setBehindRightContentView(View v, LayoutParams p); public SlidingMenu getSlidingMenu(); - public void toggle(); + public void toggle(int side); public void showAbove(); - public void showBehind(); + public void showBehind(int side); } diff --git a/library/src/com/slidingmenu/lib/app/SlidingActivityHelper.java b/library/src/com/slidingmenu/lib/app/SlidingActivityHelper.java index 85ba50fd7..bab2cba8d 100644 --- a/library/src/com/slidingmenu/lib/app/SlidingActivityHelper.java +++ b/library/src/com/slidingmenu/lib/app/SlidingActivityHelper.java @@ -19,11 +19,13 @@ public class SlidingActivityHelper { private SlidingMenu mSlidingMenu; private View mViewAbove; - private View mViewBehind; + private View mViewBehindLeft; + private View mViewBehindRight; private boolean mBroadcasting = false; private boolean mOnPostCreateCalled = false; private boolean mEnableSlide = true; + private boolean mUseCustomUp = false; public SlidingActivityHelper(Activity activity) { mActivity = activity; @@ -31,16 +33,21 @@ public SlidingActivityHelper(Activity activity) { public void onCreate(Bundle savedInstanceState) { mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null); +// mActivity.getTheme().applyStyle(R.style.CustomUp, true); } public void onPostCreate(Bundle savedInstanceState) { - if (mViewBehind == null || mViewAbove == null) { - throw new IllegalStateException("Both setBehindContentView must be called " + + if ((mViewBehindLeft == null && mViewBehindRight == null) || mViewAbove == null) { + throw new IllegalStateException("Both setBehind[Left|Right]ContentView must be called " + "in onCreate in addition to setContentView."); } + if (mViewBehindLeft == null) + mSlidingMenu.setViewBehind(null, SlidingMenu.LEFT); + if (mViewBehindRight == null) + mSlidingMenu.setViewBehind(null, SlidingMenu.RIGHT); mOnPostCreateCalled = true; - + // get the window background TypedArray a = mActivity.getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowBackground}); int background = a.getResourceId(0, 0); @@ -75,6 +82,12 @@ public void setSlidingActionBarEnabled(boolean b) { mEnableSlide = b; } + public void useCustomUpIndicator() { + if (mOnPostCreateCalled) + throw new IllegalStateException("useCustomUpIndicator must be called in onCreate."); + mUseCustomUp = true; + } + public View findViewById(int id) { View v; if (mSlidingMenu != null) { @@ -95,20 +108,25 @@ public void setContentView(View v) { mActivity.setContentView(v); } - public void setBehindContentView(View v, LayoutParams params) { - mViewBehind = v; - mSlidingMenu.setMenu(mViewBehind); + public void setBehindLeftContentView(View v) { + mViewBehindLeft = v; + mSlidingMenu.setViewBehind(mViewBehindLeft, SlidingMenu.LEFT); + } + + public void setBehindRightContentView(View v) { + mViewBehindRight = v; + mSlidingMenu.setViewBehind(mViewBehindRight, SlidingMenu.RIGHT); } public SlidingMenu getSlidingMenu() { return mSlidingMenu; } - public void toggle() { + public void toggle(int side) { if (mSlidingMenu.isBehindShowing()) { showAbove(); } else { - showBehind(); + showBehind(side); } } @@ -116,8 +134,8 @@ public void showAbove() { mSlidingMenu.showAbove(); } - public void showBehind() { - mSlidingMenu.showBehind(); + public void showBehind(int side) { + mSlidingMenu.showBehind(side); } public boolean onKeyUp(int keyCode, KeyEvent event) { diff --git a/library/src/com/slidingmenu/lib/app/SlidingFragmentActivity.java b/library/src/com/slidingmenu/lib/app/SlidingFragmentActivity.java index 8f4651017..cd294654d 100644 --- a/library/src/com/slidingmenu/lib/app/SlidingFragmentActivity.java +++ b/library/src/com/slidingmenu/lib/app/SlidingFragmentActivity.java @@ -49,32 +49,46 @@ public void setContentView(View v, LayoutParams params) { mHelper.registerAboveContentView(v, params); } - public void setBehindContentView(int id) { - setBehindContentView(getLayoutInflater().inflate(id, null)); + // behind left view + public void setBehindLeftContentView(int id) { + setBehindLeftContentView(getLayoutInflater().inflate(id, null)); } - public void setBehindContentView(View v) { - setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + public void setBehindLeftContentView(View v) { + setBehindLeftContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } - public void setBehindContentView(View v, LayoutParams params) { - mHelper.setBehindContentView(v, params); + public void setBehindLeftContentView(View v, LayoutParams params) { + mHelper.setBehindLeftContentView(v); } + // behind right view + public void setBehindRightContentView(int id) { + setBehindRightContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindRightContentView(View v) { + setBehindRightContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + public void setBehindRightContentView(View v, LayoutParams params) { + mHelper.setBehindRightContentView(v); + } + public SlidingMenu getSlidingMenu() { return mHelper.getSlidingMenu(); } - public void toggle() { - mHelper.toggle(); + public void toggle(int side) { + mHelper.toggle(side); } public void showAbove() { mHelper.showAbove(); } - public void showBehind() { - mHelper.showBehind(); + public void showBehind(int side) { + mHelper.showBehind(side); } public void setSlidingActionBarEnabled(boolean b) { diff --git a/library/src/com/slidingmenu/lib/app/SlidingListActivity.java b/library/src/com/slidingmenu/lib/app/SlidingListActivity.java index 38860653a..3b589d392 100644 --- a/library/src/com/slidingmenu/lib/app/SlidingListActivity.java +++ b/library/src/com/slidingmenu/lib/app/SlidingListActivity.java @@ -53,32 +53,46 @@ public void setContentView(View v, LayoutParams params) { mHelper.registerAboveContentView(v, params); } - public void setBehindContentView(int id) { - setBehindContentView(getLayoutInflater().inflate(id, null)); + // behind left view + public void setBehindLeftContentView(int id) { + setBehindLeftContentView(getLayoutInflater().inflate(id, null)); } - public void setBehindContentView(View v) { - setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + public void setBehindLeftContentView(View v) { + setBehindLeftContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } - public void setBehindContentView(View v, LayoutParams params) { - mHelper.setBehindContentView(v, params); + public void setBehindLeftContentView(View v, LayoutParams params) { + mHelper.setBehindLeftContentView(v); + } + + // behind right view + public void setBehindRightContentView(int id) { + setBehindRightContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindRightContentView(View v) { + setBehindRightContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + public void setBehindRightContentView(View v, LayoutParams params) { + mHelper.setBehindRightContentView(v); } public SlidingMenu getSlidingMenu() { return mHelper.getSlidingMenu(); } - public void toggle() { - mHelper.toggle(); + public void toggle(int side) { + mHelper.toggle(side); } public void showAbove() { mHelper.showAbove(); } - public void showBehind() { - mHelper.showBehind(); + public void showBehind(int side) { + mHelper.showBehind(side); } public void setSlidingActionBarEnabled(boolean b) { diff --git a/library/src/com/slidingmenu/lib/app/SlidingMapActivity.java b/library/src/com/slidingmenu/lib/app/SlidingMapActivity.java index 27fbea3ef..b2af04af8 100644 --- a/library/src/com/slidingmenu/lib/app/SlidingMapActivity.java +++ b/library/src/com/slidingmenu/lib/app/SlidingMapActivity.java @@ -50,32 +50,46 @@ public void setContentView(View v, LayoutParams params) { mHelper.registerAboveContentView(v, params); } - public void setBehindContentView(int id) { - setBehindContentView(getLayoutInflater().inflate(id, null)); + // behind left view + public void setBehindLeftContentView(int id) { + setBehindLeftContentView(getLayoutInflater().inflate(id, null)); } - public void setBehindContentView(View v) { - setBehindContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + public void setBehindLeftContentView(View v) { + setBehindLeftContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } - public void setBehindContentView(View v, LayoutParams params) { - mHelper.setBehindContentView(v, params); + public void setBehindLeftContentView(View v, LayoutParams params) { + mHelper.setBehindLeftContentView(v); + } + + // behind right view + public void setBehindRightContentView(int id) { + setBehindRightContentView(getLayoutInflater().inflate(id, null)); + } + + public void setBehindRightContentView(View v) { + setBehindRightContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + public void setBehindRightContentView(View v, LayoutParams params) { + mHelper.setBehindRightContentView(v); } public SlidingMenu getSlidingMenu() { return mHelper.getSlidingMenu(); } - public void toggle() { - mHelper.toggle(); + public void toggle(int side) { + mHelper.toggle(side); } public void showAbove() { mHelper.showAbove(); } - public void showBehind() { - mHelper.showBehind(); + public void showBehind(int side) { + mHelper.showBehind(side); } public void setSlidingActionBarEnabled(boolean b) {