SlidingMenu是Github上知名的开源项目,在这里就不多做介绍了。
本系列文章教大家分析和实现一个SlidingMenu。就SlidingMenu实现的功能点来说
public class SlidingMenu extends RelativeLayout { // private LinearLayout mLayout; // private LinearLayout mLayout2; private SlidingMenuAbove mAbove; private SlidingMenuBehind mBehind; /** * 填充Content的两种样式 */ public static final int SLIDING_WINDOW = 0; public static final int SLIDING_CONTENT = 1; public static final int LEFT = 0; public static final int RIGHT = 1; public static final int LEFT_RIGHT = 2; public SlidingMenu(Context context) { this(context, null); } public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initTestView(); mAbove = new SlidingMenuAbove(context); mBehind = new SlidingMenuBehind(context); LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); addView(mBehind, behindParams); addView(mAbove, aboveParams); } public SlidingMenu(Activity activity, int slidstyle) { this(activity, null); this.attachToActivity(activity, slidstyle); } // @Override // protected void onFinishInflate() { // super.onFinishInflate(); // // mLayout = (LinearLayout) findViewById(R.id.view1); // // mLayout2 = (LinearLayout) findViewById(R.id.view2); // } /** * 添加测试View */ private void initTestView() { } /** * 重载的attachToActivity方法 * * @param activity * 当前的Activity * @param slidstyle * 设置content的方式 */ public void attachToActivity(Activity activity, int slidstyle) { attachToActivity(activity, slidstyle, false); } /** * 获取Activity的content视图,获取方式有window和content两种方式, * 获取之后把它设置成为SlidingMenu的content部分,之后再把SlidingMenu整个视图设置为Activity的content * * @param activity * 当前的Activity视图 * @param slidstyle * 设置content的 方式 * @param actionbarOverlay * actionBar是否跟随 */ public void attachToActivity(Activity activity, int slidstyle, boolean actionbarOverlay) { TypedArray array = activity.getTheme().obtainStyledAttributes(new int[] { android.R.attr.windowBackground }); int background = array.getResourceId(0, 0); array.recycle(); switch (slidstyle) { case SLIDING_WINDOW: ViewGroup decorview = (ViewGroup) activity.getWindow().getDecorView(); ViewGroup decorChild = (ViewGroup) decorview.getChildAt(0); decorChild.setBackgroundResource(background); decorview.removeView(decorChild); decorview.addView(this); setContent(decorChild); break; case SLIDING_CONTENT: ViewGroup contentParent = (ViewGroup) activity.findViewById(android.R.id.content); View contentChild = contentParent.getChildAt(0); contentParent.removeView(contentChild); contentParent.addView(this); setContent(contentChild); if (contentChild.getBackground() == null) { contentChild.setBackgroundResource(background); } break; default: break; } } public void setContent(View content) { // mLayout2.removeView(content); // mLayout2.addView(content); mAbove.setContent(content); } }
public class SlidingMenuAbove extends ViewGroup { private final String TAG = SlidingMenuAbove.class.getSimpleName(); private boolean DEBUG = false; private Scroller mScroller; private int mTouchSlop; private VelocityTracker mTracker; private int mMinimumVelocity; private int mMaximumVelocity; private int mFlingDistance; private boolean mEnabled = true; private boolean mIsBeingDraged; private boolean mIsUnableToDrag; private boolean mQuickReturn; private float mLastMotionX; private float mLastMotionY; private float mInitialMotionX; private int mCurItem; private float mScrollX = 0.0f; protected int mActivePointerID = INVALID_POINTER; private static final int INVALID_POINTER = -1; private final static int MAX_SETTLE_DURATION = 600; private final static int MIN_DISTANCE_FOR_FLING = 25; private final static Interpolator S_INTERPOLATOR = new Interpolator() { @Override public float getInterpolation(float t) { t -= 1.0f; return t * t * t * t * t + 1.0f; } }; private View mContentView; public SlidingMenuAbove(Context context) { this(context, null); } public SlidingMenuAbove(Context context, AttributeSet attrs) { this(context, attrs, 0); } @SuppressLint("ResourceAsColor") public SlidingMenuAbove(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAboveView(); } private void initAboveView() {//这个先不用管,后面介绍 setWillNotDraw(false); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setFocusable(true); Context context = getContext(); mScroller = new Scroller(context, S_INTERPOLATOR); ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); /** * 密度,和判定为Fling动作的最小距离 */ final float density = context.getResources().getDisplayMetrics().density; mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); } @Override protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) { mContentView.layout(arg1, arg2, arg3, arg4); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getDefaultSize(0, widthMeasureSpec); int height = getDefaultSize(0, heightMeasureSpec); setMeasuredDimension(width, height); int contentWidth = getChildMeasureSpec(widthMeasureSpec, 0, width); int contentHeight = getChildMeasureSpec(heightMeasureSpec, 0, height); mContentView.measure(contentWidth, contentHeight); } public void setContent(View content) { if (mContentView != null) { this.removeView(mContentView); } mContentView = content; addView(mContentView); } }
public class SlidingMenuBehind extends ViewGroup { private TextView mTextView; public SlidingMenuBehind(Context context) { this(context, null); } public SlidingMenuBehind(Context context, AttributeSet attrs) { this(context, attrs, 0); } @SuppressLint("ResourceAsColor") public SlidingMenuBehind(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setBackgroundColor(android.R.color.holo_green_light); mTextView = new TextView(context); mTextView.setTextSize(50); mTextView.setText(SlidingMenuBehind.class.getSimpleName()); addView(mTextView); } @Override protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) { mTextView.layout(arg1, arg2, arg3, arg4); } }
public class SlidingMenuHelper { /** * Activity * <a>在给SlidingMenu的ContentView绑定当前的Activity的ContentView视图的时候会用到</a> */ private Activity mActivity; private SlidingMenu mSlidingMenu; public SlidingMenuHelper(Activity activity) { mActivity = activity; } /** * 对应Activity完成相应的初始化工作 * * @param savedInstanceState * 来自Activity的Bundle */ public void onCreate(Bundle savedInstanceState) { mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.sliding_menu, null); } /** * 当Activity再次加载时,比如,长时间锁屏,横竖屏切换时,读取从Bundle里存入的值 * * @param savedInstanceState * 填充Activity的Content的方式,window和content */ public void onPostCreate(Bundle savedInstanceState) { mSlidingMenu.attachToActivity(mActivity, SlidingMenu.SLIDING_WINDOW); } public View findViewById(int layoutId) { View v; if (mSlidingMenu != null) { v = mSlidingMenu.findViewById(layoutId); if (v != null) { return v; } } return null; } public SlidingMenu getSlidingMenu() { return mSlidingMenu; } }
/** * 侧滑菜单接口 * * @author mingwei * */ public interface SlidingBaseActivity { /** * 设置位于SlidingMenu后面的菜单视图 * * @param view * 菜单视图对象 * @param params * 菜单视图的布局参数 */ public void setBehindContentView(View view, LayoutParams params); /** * 设置位于SlidingMenu后面的菜单视图 * * @param view * 菜单视图对象 */ public void setBehindContentView(View view); /** * 设置位于SlidingMenu后面的菜单视图 * * @param layoutId * 菜单的布局id */ public void setBehindContentView(int layoutId); /** * 返回当前SlidingActivity的SlidingMenu对象 * * @return */ public SlidingMenu getSlidingMenu(); /** * 菜单切换 */ public void toggle(); /** * 显示Content部分 */ public void showContent(); /** * 显示Menu部分 */ public void showMenu(); /** * 显示第二Menu部分 */ public void showSecondaryMenu(); /** * 设置ActionBar是否跟随Content * * @param enable * ActionBar与Content是否联动 */ public void setSlidingActionBarEnabled(boolean enable); }
public class SlidingActivity extends Activity implements SlidingBaseActivity { SlidingMenuHelper mHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHelper = new SlidingMenuHelper(this); mHelper.onCreate(savedInstanceState); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mHelper.onPostCreate(savedInstanceState); } public View findViewById(int layoudId) { View v = super.findViewById(layoudId); if (v != null) { return v; } return mHelper.findViewById(layoudId); } @Override public void setContentView(int layoutResID) { setContentView(getLayoutInflater().inflate(layoutResID, null)); } @Override public void setContentView(View view) { setContentView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } @Override public void setContentView(View view, LayoutParams params) { super.setContentView(view, params); } @Override public void setBehindContentView(View view, LayoutParams params) { } @Override public void setBehindContentView(View view) { } @Override public void setBehindContentView(int layoutId) { } @Override public SlidingMenu getSlidingMenu() { return mHelper.getSlidingMenu(); } @Override public void toggle() { } @Override public void showContent() { } @Override public void showMenu() { } @Override public void showSecondaryMenu() { } @Override public void setSlidingActionBarEnabled(boolean enable) { } }
public class SlidingActivityDemo1 extends SlidingActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.sliding_activity_demo1); //TextView } }