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;

		}

	}

	

}

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

 

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

 

 

/**
* @author 张兴业
*  iOS入门群:83702688
*  android开发进阶群:241395671
*  我的新浪微博:@张兴业TBOW
*  我的邮箱:xy-zhang#163.com#->@)
*/



你可能感兴趣的:(android ui)