SlidingMenu//滑动菜单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";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*//**使用setTouchModeAbove()的常量.允许SlidingMenu在屏幕的边缘通过一个猛击的手势打开.*/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*//**使用setTouchModeAbove()的常量.允许SlidingMenu在屏幕的任何地方通过一个猛击的手势打开.*/public static final int TOUCHMODE_FULLSCREEN = 1;/** Constant value for use with setTouchModeAbove(). Denies the SlidingMenu to be opened with a swipe* gesture*//**使用setTouchModeAbove()的常量.不允许SlidingMenu通过一个猛击的手势打开.*/public static final int TOUCHMODE_NONE = 2;/** Constant value for use with setMode(). Puts the menu to the left of the content.*//**方法setMode()使用的常量.把菜单放在内容的左边*/public static final int LEFT = 0;/** Constant value for use with setMode(). Puts the menu to the right of the content.*//**方法setMode()使用的常量.把菜单放在内容的右边*/public static final int RIGHT = 1;/** Constant value for use with setMode(). Puts menus to the left and right of the content.*//**方法setMode()使用的常量.把菜单放在内容的左边和右边*/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*//*** 接收打开事件的监听接口.* 对处理打开事件感兴趣的类实现这个接口,并且这个对象和那个类一起建立了,*那个类是通过使用组件代码的addOnOpenListener方法的一个组件被注册的。* 当打开事件发生时,那个对象的适当方法会被调用.*/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*//*** 接收已经打开事件的监听接口.* 对处理已经打开事件感兴趣的类实现这个接口,并且这个对象和那个类一起建立了,*那个类是通过使用组件代码的addOnOpenListener方法的一个组件被注册的。* 当打开事件发生时,那个对象的适当方法会被调用.*/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*//*** 接收关闭事件的监听接口.* 对处理关闭事件感兴趣的类实现这个接口,并且这个对象和那个类一起建立了,*那个类是通过使用组件代码的addOnOpenListener方法的一个组件被注册的。* 当打开事件发生时,那个对象的适当方法会被调用.*/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*//*** 接收已经关闭事件的监听接口.* 对处理已经关闭事件感兴趣的类实现这个接口,并且这个对象和那个类一起建立了,*那个类是通过使用组件代码的addOnOpenListener方法的一个组件被注册的。* 当打开事件发生时,那个对象的适当方法会被调用.*/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.*实例化一个新的SlidingMenu* @param context the associated Context*/public SlidingMenu(Context context) {this(context, null);}/*** Instantiates a new SlidingMenu and attach to Activity.*实例化一个新的SlidingMenu并且附加一个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.*实例化一个新的SlidingMenu* @param context the associated Context* @param attrs the attrs*/public SlidingMenu(Context context, AttributeSet attrs) {this(context, attrs, 0);}/*** Instantiates a new SlidingMenu.*实例化一个新的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 CustomViewAbovemViewAbove.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 xmlint 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);elsesetBehindOffset(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* 附加这个SlidingMenu到全部的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* 附加这个SlidingMenu到全部的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 backgroundTypedArray 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 assetsdecorChild.setBackgroundResource(background);decor.removeView(decorChild);decor.addView(this);setContent(decorChild);break;case SLIDING_CONTENT:mActionbarOverlay = actionbarOverlay;// take the above view out ofViewGroup 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 backgroundsif (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*//**设置SlidingMenu应该出现在那一边.参数必须是SlidingMenu.Left或者是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.*返回这个SlidingMenu所在的目前的那一边.*返回目前的模式,要么是SlidingMenu.LEFT要么是SlidingMenu.Right* @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)*设置是否这个SlidingMenu在一个静态的模式(例如,什么都没有移动并且每一样都在显示)* @param b true to set static mode, false to disable static mode.*参数 b,true:静态模式,false:非静态模式*/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* 参数:animate,true时,动画过度,false时忽略动画*/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* 参数:animate,true时,动画过度,false时忽略动画*/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* 参数:animate,true时,动画过度,false时忽略动画*/public void showContent(boolean animate) {mViewAbove.setCurrentItem(1, animate);}/*** Toggle the SlidingMenu. If it is open, it will be closed, and vice versa.* 切换SlidingMenu.如果它是打开的,它将关闭,反之亦然.* */public void toggle() {toggle(true);}/*** Toggle the SlidingMenu. If it is open, it will be closed, and vice versa.*切换SlidingMenu.如果它是打开的,它将关闭,反之亦然.* @param animate true to animate the transition, false to ignore animation* 参数:animate,true时,动画过度,false时忽略动画*/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.* 参数i 边缘,后面的视图滑动到屏幕右边,用像素表示.*/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.* 参数 resID,尺寸资源的id作为后面的偏移被设置.当菜单打开时,它将在屏幕的右边留下这个宽度的距离(类似:页边空白)*/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* 参数i,用像素表示的新的上面的偏移*/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.* 参数resID,尺寸的资源id作为上面的偏移被设置.*/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* 参数i,滑动菜单将要打开的宽度,用像素表示.*/@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.* 参数 res,尺寸的资源id作为后面的偏移被设置.*/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}*控制SlidingMenu是否可以通过一个猛击的手势被打开.选项是TOUCHMODE_MARGIN,TOUCHMODE_FULLSCREEN,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}*控制SlidingMenu是否可以通过一个猛击的手势被打开.选项是TOUCHMODE_MARGIN,TOUCHMODE_FULLSCREEN,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.* 参数 resID,尺寸资源id作为阴影宽度被设置.*/public void setShadowWidthRes(int resId) {setShadowWidth((int)getResources().getDimension(resId));}/*** Sets the shadow width.*设置阴影的宽度.* @param pixels the new shadow width, in pixels* 参数pixels,用像素表示的新的阴影的宽度.*/public void setShadowWidth(int pixels) {mViewBehind.setShadowWidth(pixels);}/*** Enables or disables the SlidingMenu's fade in and out*SlidingMenu淡入淡出是否可用.* @param b true to enable fade, false to disable it* 参数b,true为可用,false为不可用.*/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)}*设置SlidingMenu淡入淡出多少.Fade必须可用* @param f the new fade degree, between 0.0f and 1.0f* 参数f,新的褪色的程度,在0.0f和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*设置OnOpenListner监听.当SlidingMenu被打开时调用.* @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* 为第二个菜单设置OnOpenListner监听.当第二个菜单被打开时调用.* @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*设置OnClosedListener的监听.当任何一个SlidingMenu被关闭时被调用.* @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*设置OnOpenedListener的监听.当SlidingMenu被打开时会被调用.* @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*设置OnClosedListener的监听.当SlidingMenu被关闭时会被调用.* @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()*/@Overrideprotected 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)*/@Overrideprotected 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")@Overrideprotected 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;}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);}}});}}}