Android 左边滑动菜单栏

来源:互联网 发布:室内温度测试软件 编辑:程序博客网 时间:2024/06/11 05:20

1、SlidingMenuView类


package com.zhuixingba.view;import com.zhuixingba.main.R;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewGroup;import android.view.ViewParent;import android.widget.Scroller;/** * EffectSpace *  * @author lance *  */public class SlidingMenuView extends ViewGroup {private static String LOG_TAG = "SlidingMenuView";private static final int INVALID_SCREEN = -1;private static final int SNAP_VELOCITY = 1000;private int mDefaultScreen = 1;private int mCurrentScreen;private int mNextScreen = INVALID_SCREEN;private Scroller mScroller;private VelocityTracker mVelocityTracker;private float mLastMotionX;private float mLastMotionY;private final static int TOUCH_STATE_REST = 0;private final static int TOUCH_STATE_SCROLLING = 1;public int mTouchState = TOUCH_STATE_REST;private boolean mAllowLongPress;private boolean mLocked;private int mTouchSlop;public int totalWidth = 0;private CloseAnimation closeAnimation;public SlidingMenuView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SlidingMenuView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initWorkspace();postDelayed(new Runnable() {@Overridepublic void run() {scrollTo(findViewById(R.id.main_left_menu).getWidth(), 0);}}, 50);}private void initWorkspace() {mScroller = new Scroller(getContext());mCurrentScreen = mDefaultScreen;mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();}boolean isDefaultScreenShowing() {return mCurrentScreen == mDefaultScreen;}public int getCurrentScreen() {return mCurrentScreen;}public void setCurrentScreen(int currentScreen) {mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));invalidate();}void showDefaultScreen() {setCurrentScreen(mDefaultScreen);}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {scrollTo(mScroller.getCurrX(), mScroller.getCurrY());} else if (mNextScreen != INVALID_SCREEN) {mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));mNextScreen = INVALID_SCREEN;clearChildrenCache();}if (closeAnimation != null) {closeAnimation.closeMenuAnimation();}}@Overridepublic void scrollTo(int x, int y) {super.scrollTo(x, y);postInvalidate();}@Overrideprotected void dispatchDraw(Canvas canvas) {final int scrollX = getScrollX();super.dispatchDraw(canvas);canvas.translate(scrollX, 0);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);measureViews(widthMeasureSpec, heightMeasureSpec);}public void measureViews(int widthMeasureSpec, int heightMeasureSpec) {View v1 = findViewById(R.id.main_left_menu);v1.measure(v1.getLayoutParams().width + v1.getLeft() + v1.getRight(), heightMeasureSpec);View v2 = findViewById(R.id.main_body);v2.measure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {int childLeft = 0;final int count = getChildCount();for (int i = 0; i < count; i++) {final View child = getChildAt(i);if (child.getVisibility() != View.GONE) {final int childWidth = child.getMeasuredWidth();child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());childLeft += childWidth;}}totalWidth = childLeft;}@Overridepublic boolean dispatchUnhandledMove(View focused, int direction) {if (direction == View.FOCUS_LEFT) {if (getCurrentScreen() > 0) {snapToScreen(getCurrentScreen() - 1);return true;}} else if (direction == View.FOCUS_RIGHT) {if (getCurrentScreen() < getChildCount() - 1) {snapToScreen(getCurrentScreen() + 1);return true;}}return super.dispatchUnhandledMove(focused, direction);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {if (mLocked) {return true;}final int action = ev.getAction();if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {return true;}final float x = ev.getX();final float y = ev.getY();switch (action) {case MotionEvent.ACTION_MOVE:final int xDiff = (int) Math.abs(x - mLastMotionX);final int yDiff = (int) Math.abs(y - mLastMotionY);final int touchSlop = mTouchSlop;boolean xMoved = xDiff > touchSlop;boolean yMoved = yDiff > touchSlop;if (xMoved || yMoved) {if (xMoved) {// Scroll if the user moved far enough along the X axismTouchState = TOUCH_STATE_SCROLLING;enableChildrenCache();}// Either way, cancel any pending longpressif (mAllowLongPress) {mAllowLongPress = false;// Try canceling the long press. It could also have been// scheduled// by a distant descendant, so use the mAllowLongPress flag// to block// everythingfinal View currentScreen = getChildAt(mCurrentScreen);currentScreen.cancelLongPress();}}break;case MotionEvent.ACTION_DOWN:// Remember location of down touchmLastMotionX = x;mLastMotionY = y;mAllowLongPress = true;mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:// Release the dragclearChildrenCache();mTouchState = TOUCH_STATE_REST;mAllowLongPress = false;break;}/* * The only time we want to intercept motion events is if we are in the * drag mode. */return mTouchState != TOUCH_STATE_REST;}void enableChildrenCache() {final int count = getChildCount();for (int i = 0; i < count; i++) {final View layout = (View) getChildAt(i);layout.setDrawingCacheEnabled(true);}}void clearChildrenCache() {final int count = getChildCount();for (int i = 0; i < count; i++) {final View layout = (View) getChildAt(i);layout.setDrawingCacheEnabled(false);}}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (mLocked) {return true;}if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(ev);final int action = ev.getAction();final float x = ev.getX();switch (action) {case MotionEvent.ACTION_DOWN:/* * If being flinged and user touches, stop the fling. isFinished * will be false if being flinged. */if (!mScroller.isFinished()) {mScroller.abortAnimation();}// Remember where the motion event startedmLastMotionX = x;break;case MotionEvent.ACTION_MOVE:if (mTouchState == TOUCH_STATE_SCROLLING) {// Scroll to follow the motion eventfinal int deltaX = (int) (mLastMotionX - x);mLastMotionX = x;if (deltaX < 0) {if (getScrollX() > 0) {scrollBy(Math.max(-getScrollX(), deltaX), 0);}} else if (deltaX > 0) {final int availableToScroll = getChildAt(getChildCount() - 1).getRight() - getScrollX()- getWidth();if (availableToScroll > 0) {scrollBy(Math.min(availableToScroll, deltaX), 0);}}}break;case MotionEvent.ACTION_UP:if (mTouchState == TOUCH_STATE_SCROLLING) {final VelocityTracker velocityTracker = mVelocityTracker;velocityTracker.computeCurrentVelocity(1000);int velocityX = (int) velocityTracker.getXVelocity();if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {// Fling hard enough to move leftsnapToScreen(mCurrentScreen - 1);} else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {// Fling hard enough to move rightsnapToScreen(mCurrentScreen + 1);} else {snapToDestination();}if (mVelocityTracker != null) {mVelocityTracker.recycle();mVelocityTracker = null;}}mTouchState = TOUCH_STATE_REST;break;case MotionEvent.ACTION_CANCEL:mTouchState = TOUCH_STATE_REST;}return true;}protected void snapToDestination() {int whichScreen = 0;int count = getChildCount();int start = 0;int end = 0;int viewWidth = 0;int tend = 0;int tstart = 0;final int scrollX = getScrollX();for (int i = 0; i < count; i++) {viewWidth = getChildAt(i).getWidth();tend = end + viewWidth / 2;if (i != 0) {viewWidth = getChildAt(i - 1).getWidth();}tstart -= viewWidth;if (scrollX > tstart && scrollX < tend) {break;}start += viewWidth;end += viewWidth;whichScreen++;}snapToScreen(whichScreen);}/** * 正常点击的切屏动画 *  * @param whichScreen *            1代表侧边收起 ,0代表展开侧边 *  */public void snapToScreen(int whichScreen) {enableChildrenCache();whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));boolean changingScreens = whichScreen != mCurrentScreen;mNextScreen = whichScreen;View focusedChild = getFocusedChild();if (focusedChild != null && changingScreens && focusedChild == getChildAt(mCurrentScreen)) {focusedChild.clearFocus();}int newX = 0;for (int i = 0; i < whichScreen; i++) {newX += getChildAt(i).getWidth();}newX = Math.min(totalWidth - getWidth(), newX);final int delta = newX - getScrollX();// mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) *// 2);mScroller.startScroll(getScrollX(), 0, delta, 0, 500);invalidate();}/** *  * 点击左侧菜单的切屏动画 *  * @param whichScreen */public void closeMenu_1(int whichScreen) {enableChildrenCache();whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));boolean changingScreens = whichScreen != mCurrentScreen;mNextScreen = whichScreen;View focusedChild = getFocusedChild();if (focusedChild != null && changingScreens && focusedChild == getChildAt(mCurrentScreen)) {focusedChild.clearFocus();}int newX = 0;for (int i = 0; i < whichScreen; i++) {newX += getChildAt(i).getWidth();}newX = Math.min(totalWidth - getWidth(), newX);final int delta = newX - getScrollX();mScroller.startScroll(getScrollX(), 0, delta - getWidth(), 0, 260);invalidate();}/** *  * 点击左侧菜单的切屏动画 *  * @param whichScreen */public void closeMenu_2(int whichScreen) {enableChildrenCache();whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));boolean changingScreens = whichScreen != mCurrentScreen;mNextScreen = whichScreen;View focusedChild = getFocusedChild();if (focusedChild != null && changingScreens && focusedChild == getChildAt(mCurrentScreen)) {focusedChild.clearFocus();}int newX = 0;for (int i = 0; i < whichScreen; i++) {newX += getChildAt(i).getWidth();}newX = Math.min(totalWidth - getWidth(), newX);final int delta = newX - getScrollX();mScroller.startScroll(getScrollX(), 0, getWidth(), 0, 500);invalidate();}public int getScreenForView(View v) {int result = -1;if (v != null) {ViewParent vp = v.getParent();int count = getChildCount();for (int i = 0; i < count; i++) {if (vp == getChildAt(i)) {return i;}}}return result;}public void unlock() {mLocked = false;}public void lock() {mLocked = true;}void moveToDefaultScreen() {snapToScreen(mDefaultScreen);getChildAt(mDefaultScreen).requestFocus();}@Overrideprotected void onFinishInflate() {// TODO Auto-generated method stubsuper.onFinishInflate();View child;for (int i = 0; i < getChildCount(); i++) {child = getChildAt(i);child.setFocusable(true);child.setClickable(true);}}public void setCloseAnimation(CloseAnimation closeAnimation) {this.closeAnimation = closeAnimation;}public interface CloseAnimation {public void closeMenuAnimation();}}

1、MainActivity主界面

package com.zhuixingba.main;import com.zhuixingba.view.SlidingMenuView;import com.zhuixingba.view.SlidingMenuView.CloseAnimation;import android.os.Bundle;import android.app.ActivityGroup;import android.content.Intent;import android.util.Log;import android.view.KeyEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.Toast;public class MainActivity extends ActivityGroup implements OnClickListener {public static SlidingMenuView slidingMenuView;private ViewGroup tabcontent;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);slidingMenuView = (SlidingMenuView) findViewById(R.id.main_menu_view);tabcontent = (ViewGroup) slidingMenuView.findViewById(R.id.main_body);initView();}/** * 初始化控件 */private void initView() {// 加载主页Intent i = new Intent(this, HomePageActivity.class);View v = getLocalActivityManager().startActivity(HomePageActivity.class.getName(), i).getDecorView();tabcontent.removeAllViews();tabcontent.addView(v);findViewById(R.id.btn_homepage).setOnClickListener(this);findViewById(R.id.btn_stars).setOnClickListener(this);findViewById(R.id.btn_personal).setOnClickListener(this);findViewById(R.id.btn_hotapp).setOnClickListener(this);findViewById(R.id.btn_set).setOnClickListener(this);findViewById(R.id.btn_exit).setOnClickListener(this);tabcontent.setOnClickListener(this);}/** * 点击事件 */@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.btn_homepage:// 首页showActivity(HomePageActivity.class);break;case R.id.btn_stars:// 关注明星showActivity(StarsActivity.class);break;case R.id.btn_personal:// 个人资料showActivity(PersonalActivity.class);break;case R.id.btn_hotapp:// 热点应用showActivity(HotAPPActivity.class);break;case R.id.btn_set:// 设置showActivity(SetActivity.class);break;case R.id.btn_exit:// 退出this.finish();break;case R.id.main_body:slidingMenuView.snapToScreen(1);break;default:break;}}/** * 切换Activity的方法 *  * @param c *            参数为Activity */private void showActivity(Class<?> c) {Intent i = new Intent(this, c);View view = getLocalActivityManager().startActivity(c.getName(), i).getDecorView();tabcontent.removeAllViews();tabcontent.addView(view);slidingMenuView.setCloseAnimation(new CloseAnimation() {@Overridepublic void closeMenuAnimation() {// TODO Auto-generated method stubif (-slidingMenuView.getScrollX() == getWindowManager().getDefaultDisplay().getWidth()- (slidingMenuView.totalWidth - getWindowManager().getDefaultDisplay().getWidth())) {slidingMenuView.closeMenu_2(1);}}});slidingMenuView.closeMenu_1(1);}private long exitTime = 0;@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {if (slidingMenuView.getCurrentScreen() == 1) {if ((System.currentTimeMillis() - exitTime) > 2000) {Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();} else {finish();System.exit(0);}} else {slidingMenuView.snapToScreen(1);}return true;} else if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_DOWN) {if (slidingMenuView.getCurrentScreen() == 1) {slidingMenuView.snapToScreen(0);} else {slidingMenuView.snapToScreen(1);}return true;}return super.onKeyDown(keyCode, event);}}

3、MainActivity界面xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <com.zhuixingba.view.SlidingMenuView        android:id="@+id/main_menu_view"        android:layout_width="fill_parent"        android:layout_height="fill_parent" >        <LinearLayout            android:id="@+id/main_left_menu"            android:layout_width="240dip"            android:layout_height="fill_parent"            android:background="@android:color/darker_gray"            android:orientation="vertical"            android:padding="5dip" >            <Button                android:id="@+id/btn_homepage"                android:layout_width="240dip"                android:layout_height="wrap_content"                android:text="@string/left_menu_homepage" />            <Button                android:id="@+id/btn_stars"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="@string/left_menu_stars" />            <Button                android:id="@+id/btn_personal"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="@string/left_menu_personal" />            <Button                android:id="@+id/btn_hotapp"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="@string/left_menu_hotapp" />            <Button                android:id="@+id/btn_set"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="@string/left_menu_set" />            <Button                android:id="@+id/btn_exit"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="@string/left_menu_exit" />        </LinearLayout>        <FrameLayout            android:id="@+id/main_body"            android:layout_width="fill_parent"            android:layout_height="fill_parent" >        </FrameLayout>    </com.zhuixingba.view.SlidingMenuView></RelativeLayout>

4、菜单界面点击显示左边菜单事件


if (MainActivity.slidingMenuView.getCurrentScreen() == 1) {MainActivity.slidingMenuView.snapToScreen(0);} else {MainActivity.slidingMenuView.snapToScreen(1);}



0 0
原创粉丝点击