Skip to content

Commit

Permalink
Explicit use of hardware layers for smoother scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
jfeinstein10 committed Jan 10, 2013
1 parent 4a53fb1 commit fa64e7a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 60 deletions.
24 changes: 13 additions & 11 deletions library/src/com/slidingmenu/lib/CustomViewAbove.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Build;
Expand Down Expand Up @@ -159,9 +158,11 @@ public CustomViewAbove(Context context, AttributeSet attrs) {
}

void initCustomViewAbove() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
// setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
setClickable(true);
setFocusable(true);
setWillNotDraw(false);
final Context context = getContext();
mScroller = new Scroller(context, sInterpolator);
final ViewConfiguration configuration = ViewConfiguration.get(context);
Expand Down Expand Up @@ -434,6 +435,8 @@ public void setContent(View v) {
if (mContent != null)
this.removeView(mContent);
mContent = v;
// mContent.setClickable(true);
mContent.setFocusable(true);
addView(mContent);
}

Expand Down Expand Up @@ -473,7 +476,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = r - l;
final int height = b - t;
final int height = b - t;
mContent.layout(0, 0, width, height);
}

Expand Down Expand Up @@ -639,7 +642,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
final float xDiff = Math.abs(dx);
final float y = MotionEventCompat.getY(ev, pointerIndex);
final float yDiff = Math.abs(y - mLastMotionY);
// if (DEBUG) Log.v(TAG, "onInterceptTouch moved to:(" + x + ", " + y + "), diff:(" + xDiff + ", " + yDiff + "), mLastMotionX:" + mLastMotionX);
if (DEBUG) Log.v(TAG, "onInterceptTouch moved to:(" + x + ", " + y + "), diff:(" + xDiff + ", " + yDiff + "), mLastMotionX:" + mLastMotionX);
if (xDiff > mTouchSlop && xDiff > yDiff && thisSlideAllowed(dx)) {
if (DEBUG) Log.v(TAG, "Starting drag! from onInterceptTouch");
startDrag();
Expand Down Expand Up @@ -721,8 +724,9 @@ public boolean onTouchEvent(MotionEvent ev) {
final float xDiff = Math.abs(dx);
final float y = MotionEventCompat.getY(ev, pointerIndex);
final float yDiff = Math.abs(y - mLastMotionY);
// if (DEBUG) Log.v(TAG, "onTouch moved to:(" + x + ", " + y + "), diff:(" + xDiff + ", " + yDiff + ")\nmIsBeingDragged:" + mIsBeingDragged + ", mLastMotionX:" + mLastMotionX);
if ((xDiff > mTouchSlop || mQuickReturn) && xDiff > yDiff && thisSlideAllowed(dx)) {
if (DEBUG) Log.v(TAG, "onTouch moved to:(" + x + ", " + y + "), diff:(" + xDiff + ", " + yDiff + ")\nmIsBeingDragged:" + mIsBeingDragged + ", mLastMotionX:" + mLastMotionX);
if ((xDiff > mTouchSlop || (mQuickReturn && xDiff > mTouchSlop / 4))
&& xDiff > yDiff && thisSlideAllowed(dx)) {
if (DEBUG) Log.v(TAG, "Starting drag! from onTouch");
startDrag();
mLastMotionX = x;
Expand Down Expand Up @@ -814,9 +818,8 @@ public void scrollTo(int x, int y) {
super.scrollTo(x, y);
mScrollX = x;
if (mEnabled)
mViewBehind.scrollBehindTo(mContent, x, y);
// if (mSelectorDrawable != null)
// invalidate();
mViewBehind.scrollBehindTo(mContent, x, y);
((SlidingMenu)getParent()).manageLayers(getPercentOpen());
}

private int determineTargetPage(float pageOffset, int velocity, int deltaX) {
Expand All @@ -834,7 +837,6 @@ private int determineTargetPage(float pageOffset, int velocity, int deltaX) {
}

protected float getPercentOpen() {
if (DEBUG) Log.v(TAG, ""+ Math.abs(mScrollX-mContent.getLeft()) / getBehindWidth());
return Math.abs(mScrollX-mContent.getLeft()) / getBehindWidth();
}

Expand Down
18 changes: 9 additions & 9 deletions library/src/com/slidingmenu/lib/CustomViewBehind.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public void setMode(int mode) {
if (mContent != null)
mContent.setVisibility(View.VISIBLE);
if (mSecondaryContent != null)
mSecondaryContent.setVisibility(View.GONE);
mSecondaryContent.setVisibility(View.INVISIBLE);
}
mMode = mode;
}
Expand Down Expand Up @@ -205,27 +205,27 @@ public int getMenuPage(int page) {
}

public void scrollBehindTo(View content, int x, int y) {
int vis = View.VISIBLE;
int vis = View.VISIBLE;
if (mMode == SlidingMenu.LEFT) {
if (x >= content.getLeft()) vis = View.GONE;
if (x >= content.getLeft()) vis = View.INVISIBLE;
scrollTo((int)((x + getBehindWidth())*mScrollScale), y);
} else if (mMode == SlidingMenu.RIGHT) {
if (x <= content.getLeft()) vis = View.GONE;
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.GONE : View.VISIBLE);
mSecondaryContent.setVisibility(x <= content.getLeft() ? View.GONE : View.VISIBLE);
vis = x == 0 ? View.GONE : View.VISIBLE;
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.GONE)
Log.v(TAG, "behind gone");
if (vis == View.INVISIBLE)
Log.v(TAG, "behind INVISIBLE");
setVisibility(vis);
}

Expand Down
51 changes: 45 additions & 6 deletions library/src/com/slidingmenu/lib/SlidingMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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;
Expand All @@ -13,14 +14,15 @@
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.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
Expand All @@ -29,6 +31,8 @@

public class SlidingMenu extends RelativeLayout {

private static final String TAG = "SlidingMenu";

public static final int SLIDING_WINDOW = 0;
public static final int SLIDING_CONTENT = 1;
private boolean mActionbarOverlay = false;
Expand Down Expand Up @@ -202,7 +206,7 @@ public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mViewAbove = new CustomViewAbove(context);
addView(mViewAbove, aboveParams);
// register the CustomViewBehind2 with the CustomViewAbove
// register the CustomViewBehind with the CustomViewAbove
mViewAbove.setCustomViewBehind(mViewBehind);
mViewBehind.setCustomViewAbove(mViewAbove);
mViewAbove.setOnPageChangeListener(new OnPageChangeListener() {
Expand Down Expand Up @@ -310,8 +314,8 @@ public void attachToActivity(Activity activity, int slideStyle, boolean actionba
// save ActionBar themes that have transparent assets
decorChild.setBackgroundResource(background);
decor.removeView(decorChild);
setContent(decorChild);
decor.addView(this);
setContent(decorChild);
break;
case SLIDING_CONTENT:
mActionbarOverlay = actionbarOverlay;
Expand Down Expand Up @@ -376,12 +380,13 @@ public void setMenu(View v) {
}

/**
* Retrieves the current menu.
* @return the current menu
* 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.
Expand Down Expand Up @@ -545,6 +550,15 @@ public void toggle(boolean animate) {
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.
Expand Down Expand Up @@ -945,9 +959,34 @@ protected boolean fitSystemWindows(Rect insets) {
int rightPadding = insets.right;
int topPadding = insets.top;
int bottomPadding = insets.bottom;
if (!mActionbarOverlay)
if (!mActionbarOverlay) {
Log.v(TAG, "setting padding!");
setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
}
return true;
}

private Handler mHandler = new Handler();

@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()) {
mHandler.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);
}
}
});
}
}

}
65 changes: 31 additions & 34 deletions library/src/com/slidingmenu/lib/app/SlidingActivityHelper.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.slidingmenu.lib.app;

import android.app.Activity;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;

import com.slidingmenu.lib.R;
Expand All @@ -17,15 +16,15 @@ 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;

/**
Expand Down Expand Up @@ -59,34 +58,31 @@ public void onPostCreate(Bundle savedInstanceState) {

mOnPostCreateCalled = true;

// get the window background
TypedArray a = mActivity.getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowBackground});
int background = a.getResourceId(0, 0);
a.recycle();

if (mEnableSlide) {
// move everything into the SlidingMenu
ViewGroup decor = (ViewGroup) mActivity.getWindow().getDecorView();
ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
// save ActionBar themes that have transparent assets
decorChild.setBackgroundResource(background);
decor.removeView(decorChild);
mSlidingMenu.setContent(decorChild);
decor.addView(mSlidingMenu);
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 {
// take the above view out of
ViewGroup parent = (ViewGroup) mViewAbove.getParent();
if (parent != null) {
parent.removeView(mViewAbove);
}
// save people from having transparent backgrounds
if (mViewAbove.getBackground() == null) {
mViewAbove.setBackgroundResource(background);
}
mSlidingMenu.setContent(mViewAbove);
parent.addView(mSlidingMenu, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
open = false;
secondary = false;
}
this.showContent();
new Handler().post(new Runnable() {
public void run() {
if (open) {
if (secondary) {
mSlidingMenu.showSecondaryMenu(false);
} else {
mSlidingMenu.showMenu(false);
}
} else {
mSlidingMenu.showContent(false);
}
}
});
}

/**
Expand Down Expand Up @@ -126,7 +122,8 @@ public View findViewById(int id) {
* @param outState Bundle in which to place your saved state.
*/
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean("menuOpen", mSlidingMenu.isMenuShowing());
outState.putBoolean("SlidingActivityHelper.open", mSlidingMenu.isMenuShowing());
outState.putBoolean("SlidingActivityHelper.secondary", mSlidingMenu.isSecondaryMenuShowing());
}

/**
Expand Down Expand Up @@ -195,7 +192,7 @@ public void showContent() {
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.
Expand Down

0 comments on commit fa64e7a

Please sign in to comment.