Android UI开发第二十七篇――实现左右划出菜单

       年前就想写左右滑动菜单,苦于没有时间,一直拖到现在,这篇代码实现参考了网上流行的SlidingMenu,使用的FrameLayout布局,不是扩展的HorizontalScrollView。

       程序中自定义了菜单view:SlidingView,继承自ViewGroup,使用FrameLayout布局。重写了onInterceptTouchEvent(MotionEvent ev)方法实现ontouch的分发拦截,重写了onTouchEvent(MotionEvent ev)方法,实现左右滑动。

public class SlidingView extends ViewGroup {  	private FrameLayout mContainer; 	private Scroller mScroller; 	private VelocityTracker mVelocityTracker; 	private int mTouchSlop; 	private float mLastMotionX; 	private float mLastMotionY; 	private static final int SNAP_VELOCITY = 1000; 	private View mLeftView; 	private View mRightView;  	public SlidingView(Context context) { 		super(context); 		init(); 	}  	public SlidingView(Context context, AttributeSet attrs) { 		super(context, attrs); 		init(); 	}  	public SlidingView(Context context, AttributeSet attrs, int defStyle) { 		super(context, attrs, defStyle); 		init(); 	}  	@Override 	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 		super.onMeasure(widthMeasureSpec, heightMeasureSpec); 		mContainer.measure(widthMeasureSpec, heightMeasureSpec); 	}  	@Override 	protected void onLayout(boolean changed, int l, int t, int r, int b) { 		final int width = r - l; 		final int height = b - t; 		mContainer.layout(0, 0, width, height); 	}  	private void init() { 		mContainer = new FrameLayout(getContext()); 		mContainer.setBackgroundColor(0xff000000); 		mScroller = new Scroller(getContext()); 		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 		super.addView(mContainer); 	}  	public void setView(View v) { 		if (mContainer.getChildCount() > 0) { 			mContainer.removeAllViews(); 		} 		mContainer.addView(v); 	}  	@Override 	public void scrollTo(int x, int y) { 		super.scrollTo(x, y); 		postInvalidate(); 	}  	@Override 	public void computeScroll() { 		if (!mScroller.isFinished()) { 			if (mScroller.computeScrollOffset()) { 				int oldX = getScrollX(); 				int oldY = getScrollY(); 				int x = mScroller.getCurrX(); 				int y = mScroller.getCurrY(); 				if (oldX != x || oldY != y) { 					scrollTo(x, y); 				} 				// Keep on drawing until the animation has finished. 				invalidate(); 			} else { 				clearChildrenCache(); 			} 		} else { 			clearChildrenCache(); 		} 	}  	private boolean mIsBeingDragged;  	     /**      * 实现了ontouch的分发拦截      */ 	@Override 	public boolean onInterceptTouchEvent(MotionEvent ev) {  		final int action = ev.getAction(); 		final float x = ev.getX(); 		final float y = ev.getY();  		switch (action) { 		case MotionEvent.ACTION_DOWN: 			mLastMotionX = x; 			mLastMotionY = y; 			mIsBeingDragged = false; 			break;  		case MotionEvent.ACTION_MOVE: 			final float dx = x - mLastMotionX; 			final float xDiff = Math.abs(dx); 			final float yDiff = Math.abs(y - mLastMotionY); 			if (xDiff > mTouchSlop && xDiff > yDiff) { 				mIsBeingDragged = true; 				mLastMotionX = x; 			} 			Log.d("Sliding", "SlidingView_Touch:"+x+"|"+y); 			Log.d("Sliding", "SlidingView_Touch:"+xDiff+"|"+mTouchSlop+"|"+yDiff+"|"+mLastMotionY); 			Log.d("Sliding", "SlidingView_Touch:"+mIsBeingDragged); 			break;  		} 		return mIsBeingDragged; 	}  	@Override 	public boolean onTouchEvent(MotionEvent ev) {  		if (mVelocityTracker == null) { 			mVelocityTracker = VelocityTracker.obtain(); 		} 		mVelocityTracker.addMovement(ev);  		final int action = ev.getAction(); 		final float x = ev.getX(); 		final float y = ev.getY();  		switch (action) { 		case MotionEvent.ACTION_DOWN: 			if (!mScroller.isFinished()) { 				mScroller.abortAnimation(); 			} 			mLastMotionX = x; 			mLastMotionY = y; 			if (getScrollX() == -getLeftMenuWidth() 					&& mLastMotionX < getLeftMenuWidth()) { 				return false; 			}  			if (getScrollX() == getRightMenuWidth() 					&& mLastMotionX > getLeftMenuWidth()) { 				return false; 			}  			break; 		case MotionEvent.ACTION_MOVE: 			if (mIsBeingDragged) { 				enableChildrenCache(); 				final float deltaX = mLastMotionX - x; 				mLastMotionX = x; 				float oldScrollX = getScrollX(); 				float scrollX = oldScrollX + deltaX;  				if (deltaX < 0 && oldScrollX < 0) { // left view 					final float leftBound = 0; 					final float rightBound = -getLeftMenuWidth(); 					if (scrollX > leftBound) { 						scrollX = leftBound; 					} else if (scrollX < rightBound) { 						scrollX = rightBound; 					} 				} else if (deltaX > 0 && oldScrollX > 0) { // right view 					final float rightBound = getRightMenuWidth(); 					final float leftBound = 0; 					if (scrollX < leftBound) { 						scrollX = leftBound; 					} else if (scrollX > rightBound) { 						scrollX = rightBound; 					} 				}  				scrollTo((int) scrollX, getScrollY()); 				if (scrollX > 0) { 					mLeftView.setVisibility(View.GONE); 					mLeftView.clearFocus(); 					mRightView.setVisibility(View.VISIBLE); 					mRightView.requestFocus(); 				} else { 					mLeftView.setVisibility(View.VISIBLE); 					mLeftView.requestFocus(); 					mRightView.setVisibility(View.GONE); 					mRightView.clearFocus(); 				} 			} 			break; 		case MotionEvent.ACTION_CANCEL: 		case MotionEvent.ACTION_UP: 			if (mIsBeingDragged) { 				final VelocityTracker velocityTracker = mVelocityTracker; 				velocityTracker.computeCurrentVelocity(1000); 				int velocityX = (int) velocityTracker.getXVelocity(); 				velocityX = 0; 				int oldScrollX = getScrollX(); 				int dx = 0; 				if (oldScrollX < 0) { 					// 左边 					if (oldScrollX < -getLeftMenuWidth() / 2 							|| velocityX > SNAP_VELOCITY) { 						// 左侧页面划出 						dx = -getLeftMenuWidth() - oldScrollX;  					} else if (oldScrollX >= -getLeftMenuWidth() / 2 							|| velocityX < -SNAP_VELOCITY) { 						// 左侧页面关闭 						dx = -oldScrollX; 					} 				} else { 					// 右边 					if (oldScrollX > getRightMenuWidth() / 2 							|| velocityX < -SNAP_VELOCITY) { 						// 右侧页面划出 						dx = getRightMenuWidth() - oldScrollX;  					} else if (oldScrollX <= getRightMenuWidth() / 2 							|| velocityX > SNAP_VELOCITY) { 						// 右侧页面关闭 						dx = -oldScrollX; 					} 				}  				smoothScrollTo(dx); 				clearChildrenCache();  			}  			break;  		} 		if (mVelocityTracker != null) { 			mVelocityTracker.recycle(); 			mVelocityTracker = null; 		} 		return true; 	}  	private int getLeftMenuWidth() { 		if (mLeftView == null) { 			return 0; 		} 		return mLeftView.getWidth(); 	}  	private int getRightMenuWidth() { 		if (mRightView == null) { 			return 0; 		} 		return mRightView.getWidth(); 	}  	@Override 	protected void onDraw(Canvas canvas) { 		super.onDraw(canvas); 	}  	public View getRightView() { 		return mRightView; 	}  	public void setRightView(View mRightView) { 		this.mRightView = mRightView; 	}  	public View getMenuView() { 		return mLeftView; 	}  	public void setLeftView(View mLeftView) { 		this.mLeftView = mLeftView; 	}  	void toggle() { 		int menuWidth = mLeftView.getWidth(); 		int oldScrollX = getScrollX(); 		if (oldScrollX == 0) { 			smoothScrollTo(-menuWidth); 		} else if (oldScrollX == -menuWidth) { 			smoothScrollTo(menuWidth); 		} 	}  	/** 	 * 打开(关闭)左侧页面 	 */ 	public void showLeftView() { 		mLeftView.setVisibility(View.VISIBLE); 		mRightView.setVisibility(View.GONE); 		int menuWidth = mLeftView.getWidth(); 		int oldScrollX = getScrollX(); 		if (oldScrollX == 0) { 			smoothScrollTo(-menuWidth); 		} else if (oldScrollX == -menuWidth) { 			smoothScrollTo(menuWidth); 		} 	}  	/** 	 * 打开(关闭)右侧页面 	 */ 	public void showRightView() { 		mLeftView.setVisibility(View.GONE); 		mLeftView.clearFocus(); 		mRightView.setVisibility(View.VISIBLE); 		mRightView.requestFocus(); 		int menuWidth = mRightView.getWidth(); 		int oldScrollX = getScrollX(); 		if (oldScrollX == 0) { 			smoothScrollTo(menuWidth); 		} else if (oldScrollX == menuWidth) { 			smoothScrollTo(-menuWidth); 		} 	}  	/** 	 * 显示中间页面 	 */ 	public void showCenterView() { 		int menuWidth = mRightView.getWidth(); 		int oldScrollX = getScrollX(); 		if (oldScrollX == menuWidth) { 			showRightView(); 		} else if (oldScrollX == -menuWidth) { 			showLeftView(); 		} 	}  	void smoothScrollTo(int dx) { 		int duration = 500; 		int oldScrollX = getScrollX(); 		mScroller.startScroll(oldScrollX, getScrollY(), dx, getScrollY(), 				duration); 		invalidate(); 	}  	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); 		} 	}  }

SlidingMenu对SlidingView做了进一步封装处理:

public class SlidingMenu extends RelativeLayout {  	private SlidingView mSlidingView; 	private View mLeftView; 	private View mRightView; 	// menu width 	private int alignScreenWidth;  	public SlidingMenu(Context context) { 		super(context); 	}  	public SlidingMenu(Context context, AttributeSet attrs) { 		super(context, attrs); 	}  	public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { 		super(context, attrs, defStyle); 	}  	public void setAlignScreenWidth(int alignScreenWidth) { 		this.alignScreenWidth = alignScreenWidth; 	}  	public void setLeftView(View view) { 		LayoutParams behindParams = new LayoutParams(alignScreenWidth, 				LayoutParams.MATCH_PARENT); 		addView(view, behindParams); 		mLeftView = view; 	}  	public void setRightView(View view) { 		LayoutParams behindParams = new LayoutParams(alignScreenWidth, 				LayoutParams.MATCH_PARENT); 		behindParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); 		addView(view, behindParams); 		mRightView = view; 	}  	public void setCenterView(View view) { 		LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, 				LayoutParams.MATCH_PARENT); 		mSlidingView = new SlidingView(getContext()); 		addView(mSlidingView, aboveParams); 		mSlidingView.setView(view); 		mSlidingView.invalidate(); 		mSlidingView.setLeftView(mLeftView); 		mSlidingView.setRightView(mRightView); 	}  	public void showLeftView() { 		mSlidingView.showLeftView(); 	}  	public void showRightView() { 		mSlidingView.showRightView(); 	}  	public void showCenterView() { 		mSlidingView.showCenterView(); 	}  }

SlidingMenu的使用代码

public class SlidingActivity extends Activity implements OnClickListener{ 	SlidingMenu mSlidingMenu;  	@Override 	protected void onCreate(Bundle arg0) { 		super.onCreate(arg0); 		setContentView(R.layout.main);   		DisplayMetrics dm = new DisplayMetrics(); 		getWindowManager().getDefaultDisplay().getMetrics(dm);  		mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingMenu); 		mSlidingMenu.setAlignScreenWidth((dm.widthPixels / 5) * 2); 		 		View leftView=getLayoutInflater().inflate(R.layout.left_menu, null); 		View rightView=getLayoutInflater().inflate(R.layout.right_menu, null); 		View centerView=getLayoutInflater().inflate(R.layout.center, null); 		 		mSlidingMenu.setLeftView(leftView); 		mSlidingMenu.setRightView(rightView); 		mSlidingMenu.setCenterView(centerView);          		Button showLeftMenu=(Button)centerView.findViewById(R.id.center_left_btn); 		showLeftMenu.setOnClickListener(this); 		Button showRightMenu=(Button)centerView.findViewById(R.id.center_right_btn); 		showRightMenu.setOnClickListener(this); 	}  	@Override 	public void onClick(View v) { 		// TODO Auto-generated method stub 		switch (v.getId()) { 		case R.id.center_left_btn: 			mSlidingMenu.showLeftView(); 			break;         case R.id.center_right_btn:         	mSlidingMenu.showRightView(); 			break; 		default: 			break; 		} 	} 	 }
                                


代码:http://download.csdn.net/detail/xyz_lmn/5109965

/**
* @author 张兴业
* android开发进阶群: 241395671
*/

你可能感兴趣的:(android,UI,SlidingMenu,左右滑动菜单)