亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Android雙向滑動菜單完全解析,教你如何一分鐘

系統 1836 0

轉載請注明出處: http://blog.csdn.net/guolin_blog/article/details/9671609

記得在很早之前,我寫了一篇關于Android滑動菜單的文章,其中有一個朋友在評論中留言,希望我可以幫他將這個滑動菜單改成雙向滑動的方式。當時也沒想花太多時間,簡單修改了一下就發給了他,結果沒想到后來卻有一大批的朋友都來問我要這份雙向滑動菜單的代碼。由于這份代碼寫得很不用心,我發了部分朋友之后實在不忍心繼續發下去了,于是決定專門寫一篇文章來介紹更好的Android雙向滑動菜單的實現方法。

在開始動手之前先來講一下實現原理,在一個Activity的布局中需要有三部分,一個是左側菜單的布局,一個是右側菜單的布局,一個是內容布局。左側菜單居屏幕左邊緣對齊,右側菜單居屏幕右邊緣對齊,然后內容布局占滿整個屏幕,并壓在了左側菜單和右側菜單的上面。當用戶手指向右滑動時,將右側菜單隱藏,左側菜單顯示,然后通過偏移內容布局的位置,就可以讓左側菜單展現出來。同樣的道理,當用戶手指向左滑動時,將左側菜單隱藏,右側菜單顯示,也是通過偏移內容布局的位置,就可以讓右側菜單展現出來。原理示意圖所下所示:

Android雙向滑動菜單完全解析,教你如何一分鐘實現雙向滑動特效

介紹完了原理,我們就開始動手實現吧。新建一個Android項目,項目名就叫做BidirSlidingLayout。然后新建我們最主要的BidirSlidingLayout類,這個類就是實現雙向滑動菜單功能的核心類,代碼如下所示:

    public class BidirSlidingLayout extends RelativeLayout implements OnTouchListener {

	/**
	 * 滾動顯示和隱藏左側布局時,手指滑動需要達到的速度。
	 */
	public static final int SNAP_VELOCITY = 200;

	/**
	 * 滑動狀態的一種,表示未進行任何滑動。
	 */
	public static final int DO_NOTHING = 0;

	/**
	 * 滑動狀態的一種,表示正在滑出左側菜單。
	 */
	public static final int SHOW_LEFT_MENU = 1;

	/**
	 * 滑動狀態的一種,表示正在滑出右側菜單。
	 */
	public static final int SHOW_RIGHT_MENU = 2;

	/**
	 * 滑動狀態的一種,表示正在隱藏左側菜單。
	 */
	public static final int HIDE_LEFT_MENU = 3;

	/**
	 * 滑動狀態的一種,表示正在隱藏右側菜單。
	 */
	public static final int HIDE_RIGHT_MENU = 4;

	/**
	 * 記錄當前的滑動狀態
	 */
	private int slideState;

	/**
	 * 屏幕寬度值。
	 */
	private int screenWidth;

	/**
	 * 在被判定為滾動之前用戶手指可以移動的最大值。
	 */
	private int touchSlop;

	/**
	 * 記錄手指按下時的橫坐標。
	 */
	private float xDown;

	/**
	 * 記錄手指按下時的縱坐標。
	 */
	private float yDown;

	/**
	 * 記錄手指移動時的橫坐標。
	 */
	private float xMove;

	/**
	 * 記錄手指移動時的縱坐標。
	 */
	private float yMove;

	/**
	 * 記錄手機抬起時的橫坐標。
	 */
	private float xUp;

	/**
	 * 左側菜單當前是顯示還是隱藏。只有完全顯示或隱藏時才會更改此值,滑動過程中此值無效。
	 */
	private boolean isLeftMenuVisible;

	/**
	 * 右側菜單當前是顯示還是隱藏。只有完全顯示或隱藏時才會更改此值,滑動過程中此值無效。
	 */
	private boolean isRightMenuVisible;

	/**
	 * 是否正在滑動。
	 */
	private boolean isSliding;

	/**
	 * 左側菜單布局對象。
	 */
	private View leftMenuLayout;

	/**
	 * 右側菜單布局對象。
	 */
	private View rightMenuLayout;

	/**
	 * 內容布局對象。
	 */
	private View contentLayout;

	/**
	 * 用于監聽滑動事件的View。
	 */
	private View mBindView;

	/**
	 * 左側菜單布局的參數。
	 */
	private MarginLayoutParams leftMenuLayoutParams;

	/**
	 * 右側菜單布局的參數。
	 */
	private MarginLayoutParams rightMenuLayoutParams;

	/**
	 * 內容布局的參數。
	 */
	private RelativeLayout.LayoutParams contentLayoutParams;

	/**
	 * 用于計算手指滑動的速度。
	 */
	private VelocityTracker mVelocityTracker;

	/**
	 * 重寫BidirSlidingLayout的構造函數,其中獲取了屏幕的寬度和touchSlop的值。
	 * 
	 * @param context
	 * @param attrs
	 */
	public BidirSlidingLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		screenWidth = wm.getDefaultDisplay().getWidth();
		touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
	}

	/**
	 * 綁定監聽滑動事件的View。
	 * 
	 * @param bindView
	 *            需要綁定的View對象。
	 */
	public void setScrollEvent(View bindView) {
		mBindView = bindView;
		mBindView.setOnTouchListener(this);
	}

	/**
	 * 將界面滾動到左側菜單界面,滾動速度設定為-30.
	 */
	public void scrollToLeftMenu() {
		new LeftMenuScrollTask().execute(-30);
	}

	/**
	 * 將界面滾動到右側菜單界面,滾動速度設定為-30.
	 */
	public void scrollToRightMenu() {
		new RightMenuScrollTask().execute(-30);
	}

	/**
	 * 將界面從左側菜單滾動到內容界面,滾動速度設定為30.
	 */
	public void scrollToContentFromLeftMenu() {
		new LeftMenuScrollTask().execute(30);
	}

	/**
	 * 將界面從右側菜單滾動到內容界面,滾動速度設定為30.
	 */
	public void scrollToContentFromRightMenu() {
		new RightMenuScrollTask().execute(30);
	}

	/**
	 * 左側菜單是否完全顯示出來,滑動過程中此值無效。
	 * 
	 * @return 左側菜單完全顯示返回true,否則返回false。
	 */
	public boolean isLeftLayoutVisible() {
		return isLeftMenuVisible;
	}

	/**
	 * 右側菜單是否完全顯示出來,滑動過程中此值無效。
	 * 
	 * @return 右側菜單完全顯示返回true,否則返回false。
	 */
	public boolean isRightLayoutVisible() {
		return isRightMenuVisible;
	}

	/**
	 * 在onLayout中重新設定左側菜單、右側菜單、以及內容布局的參數。
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed) {
			// 獲取左側菜單布局對象
			leftMenuLayout = getChildAt(0);
			leftMenuLayoutParams = (MarginLayoutParams) leftMenuLayout.getLayoutParams();
			// 獲取右側菜單布局對象
			rightMenuLayout = getChildAt(1);
			rightMenuLayoutParams = (MarginLayoutParams) rightMenuLayout.getLayoutParams();
			// 獲取內容布局對象
			contentLayout = getChildAt(2);
			contentLayoutParams = (RelativeLayout.LayoutParams) contentLayout.getLayoutParams();
			contentLayoutParams.width = screenWidth;
			contentLayout.setLayoutParams(contentLayoutParams);
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		createVelocityTracker(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// 手指按下時,記錄按下時的坐標
			xDown = event.getRawX();
			yDown = event.getRawY();
			// 將滑動狀態初始化為DO_NOTHING
			slideState = DO_NOTHING;
			break;
		case MotionEvent.ACTION_MOVE:
			xMove = event.getRawX();
			yMove = event.getRawY();
			// 手指移動時,對比按下時的坐標,計算出移動的距離。
			int moveDistanceX = (int) (xMove - xDown);
			int moveDistanceY = (int) (yMove - yDown);
			// 檢查當前的滑動狀態
			checkSlideState(moveDistanceX, moveDistanceY);
			// 根據當前滑動狀態決定如何偏移內容布局
			switch (slideState) {
			case SHOW_LEFT_MENU:
				contentLayoutParams.rightMargin = -moveDistanceX;
				checkLeftMenuBorder();
				contentLayout.setLayoutParams(contentLayoutParams);
				break;
			case HIDE_LEFT_MENU:
				contentLayoutParams.rightMargin = -leftMenuLayoutParams.width - moveDistanceX;
				checkLeftMenuBorder();
				contentLayout.setLayoutParams(contentLayoutParams);
			case SHOW_RIGHT_MENU:
				contentLayoutParams.leftMargin = moveDistanceX;
				checkRightMenuBorder();
				contentLayout.setLayoutParams(contentLayoutParams);
				break;
			case HIDE_RIGHT_MENU:
				contentLayoutParams.leftMargin = -rightMenuLayoutParams.width + moveDistanceX;
				checkRightMenuBorder();
				contentLayout.setLayoutParams(contentLayoutParams);
			default:
				break;
			}
			break;
		case MotionEvent.ACTION_UP:
			xUp = event.getRawX();
			int upDistanceX = (int) (xUp - xDown);
			if (isSliding) {
				// 手指抬起時,進行判斷當前手勢的意圖
				switch (slideState) {
				case SHOW_LEFT_MENU:
					if (shouldScrollToLeftMenu()) {
						scrollToLeftMenu();
					} else {
						scrollToContentFromLeftMenu();
					}
					break;
				case HIDE_LEFT_MENU:
					if (shouldScrollToContentFromLeftMenu()) {
						scrollToContentFromLeftMenu();
					} else {
						scrollToLeftMenu();
					}
					break;
				case SHOW_RIGHT_MENU:
					if (shouldScrollToRightMenu()) {
						scrollToRightMenu();
					} else {
						scrollToContentFromRightMenu();
					}
					break;
				case HIDE_RIGHT_MENU:
					if (shouldScrollToContentFromRightMenu()) {
						scrollToContentFromRightMenu();
					} else {
						scrollToRightMenu();
					}
					break;
				default:
					break;
				}
			} else if (upDistanceX < touchSlop && isLeftMenuVisible) {
				// 當左側菜單顯示時,如果用戶點擊一下內容部分,則直接滾動到內容界面
				scrollToContentFromLeftMenu();
			} else if (upDistanceX < touchSlop && isRightMenuVisible) {
				// 當右側菜單顯示時,如果用戶點擊一下內容部分,則直接滾動到內容界面
				scrollToContentFromRightMenu();
			}
			recycleVelocityTracker();
			break;
		}
		if (v.isEnabled()) {
			if (isSliding) {
				// 正在滑動時讓控件得不到焦點
				unFocusBindView();
				return true;
			}
			if (isLeftMenuVisible || isRightMenuVisible) {
				// 當左側或右側布局顯示時,將綁定控件的事件屏蔽掉
				return true;
			}
			return false;
		}
		return true;
	}

	/**
	 * 根據手指移動的距離,判斷當前用戶的滑動意圖,然后給slideState賦值成相應的滑動狀態值。
	 * 
	 * @param moveDistanceX
	 *            橫向移動的距離
	 * @param moveDistanceY
	 *            縱向移動的距離
	 */
	private void checkSlideState(int moveDistanceX, int moveDistanceY) {
		if (isLeftMenuVisible) {
			if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX < 0) {
				isSliding = true;
				slideState = HIDE_LEFT_MENU;
			}
		} else if (isRightMenuVisible) {
			if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX > 0) {
				isSliding = true;
				slideState = HIDE_RIGHT_MENU;
			}
		} else {
			if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX > 0
					&& Math.abs(moveDistanceY) < touchSlop) {
				isSliding = true;
				slideState = SHOW_LEFT_MENU;
				contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
				contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
				contentLayout.setLayoutParams(contentLayoutParams);
				// 如果用戶想要滑動左側菜單,將左側菜單顯示,右側菜單隱藏
				leftMenuLayout.setVisibility(View.VISIBLE);
				rightMenuLayout.setVisibility(View.GONE);
			} else if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX < 0
					&& Math.abs(moveDistanceY) < touchSlop) {
				isSliding = true;
				slideState = SHOW_RIGHT_MENU;
				contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
				contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
				contentLayout.setLayoutParams(contentLayoutParams);
				// 如果用戶想要滑動右側菜單,將右側菜單顯示,左側菜單隱藏
				rightMenuLayout.setVisibility(View.VISIBLE);
				leftMenuLayout.setVisibility(View.GONE);
			}
		}
	}

	/**
	 * 在滑動過程中檢查左側菜單的邊界值,防止綁定布局滑出屏幕。
	 */
	private void checkLeftMenuBorder() {
		if (contentLayoutParams.rightMargin > 0) {
			contentLayoutParams.rightMargin = 0;
		} else if (contentLayoutParams.rightMargin < -leftMenuLayoutParams.width) {
			contentLayoutParams.rightMargin = -leftMenuLayoutParams.width;
		}
	}

	/**
	 * 在滑動過程中檢查右側菜單的邊界值,防止綁定布局滑出屏幕。
	 */
	private void checkRightMenuBorder() {
		if (contentLayoutParams.leftMargin > 0) {
			contentLayoutParams.leftMargin = 0;
		} else if (contentLayoutParams.leftMargin < -rightMenuLayoutParams.width) {
			contentLayoutParams.leftMargin = -rightMenuLayoutParams.width;
		}
	}

	/**
	 * 判斷是否應該滾動將左側菜單展示出來。如果手指移動距離大于左側菜單寬度的1/2,或者手指移動速度大于SNAP_VELOCITY,
	 * 就認為應該滾動將左側菜單展示出來。
	 * 
	 * @return 如果應該將左側菜單展示出來返回true,否則返回false。
	 */
	private boolean shouldScrollToLeftMenu() {
		return xUp - xDown > leftMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
	}

	/**
	 * 判斷是否應該滾動將右側菜單展示出來。如果手指移動距離大于右側菜單寬度的1/2,或者手指移動速度大于SNAP_VELOCITY,
	 * 就認為應該滾動將右側菜單展示出來。
	 * 
	 * @return 如果應該將右側菜單展示出來返回true,否則返回false。
	 */
	private boolean shouldScrollToRightMenu() {
		return xDown - xUp > rightMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
	}

	/**
	 * 判斷是否應該從左側菜單滾動到內容布局,如果手指移動距離大于左側菜單寬度的1/2,或者手指移動速度大于SNAP_VELOCITY,
	 * 就認為應該從左側菜單滾動到內容布局。
	 * 
	 * @return 如果應該從左側菜單滾動到內容布局返回true,否則返回false。
	 */
	private boolean shouldScrollToContentFromLeftMenu() {
		return xDown - xUp > leftMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
	}

	/**
	 * 判斷是否應該從右側菜單滾動到內容布局,如果手指移動距離大于右側菜單寬度的1/2,或者手指移動速度大于SNAP_VELOCITY,
	 * 就認為應該從右側菜單滾動到內容布局。
	 * 
	 * @return 如果應該從右側菜單滾動到內容布局返回true,否則返回false。
	 */
	private boolean shouldScrollToContentFromRightMenu() {
		return xUp - xDown > rightMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
	}

	/**
	 * 創建VelocityTracker對象,并將觸摸事件加入到VelocityTracker當中。
	 * 
	 * @param event
	 *            右側布局監聽控件的滑動事件
	 */
	private void createVelocityTracker(MotionEvent event) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);
	}

	/**
	 * 獲取手指在綁定布局上的滑動速度。
	 * 
	 * @return 滑動速度,以每秒鐘移動了多少像素值為單位。
	 */
	private int getScrollVelocity() {
		mVelocityTracker.computeCurrentVelocity(1000);
		int velocity = (int) mVelocityTracker.getXVelocity();
		return Math.abs(velocity);
	}

	/**
	 * 回收VelocityTracker對象。
	 */
	private void recycleVelocityTracker() {
		mVelocityTracker.recycle();
		mVelocityTracker = null;
	}

	/**
	 * 使用可以獲得焦點的控件在滑動的時候失去焦點。
	 */
	private void unFocusBindView() {
		if (mBindView != null) {
			mBindView.setPressed(false);
			mBindView.setFocusable(false);
			mBindView.setFocusableInTouchMode(false);
		}
	}

	class LeftMenuScrollTask extends AsyncTask<Integer, Integer, Integer> {

		@Override
		protected Integer doInBackground(Integer... speed) {
			int rightMargin = contentLayoutParams.rightMargin;
			// 根據傳入的速度來滾動界面,當滾動到達邊界值時,跳出循環。
			while (true) {
				rightMargin = rightMargin + speed[0];
				if (rightMargin < -leftMenuLayoutParams.width) {
					rightMargin = -leftMenuLayoutParams.width;
					break;
				}
				if (rightMargin > 0) {
					rightMargin = 0;
					break;
				}
				publishProgress(rightMargin);
				// 為了要有滾動效果產生,每次循環使線程睡眠一段時間,這樣肉眼才能夠看到滾動動畫。
				sleep(15);
			}
			if (speed[0] > 0) {
				isLeftMenuVisible = false;
			} else {
				isLeftMenuVisible = true;
			}
			isSliding = false;
			return rightMargin;
		}

		@Override
		protected void onProgressUpdate(Integer... rightMargin) {
			contentLayoutParams.rightMargin = rightMargin[0];
			contentLayout.setLayoutParams(contentLayoutParams);
			unFocusBindView();
		}

		@Override
		protected void onPostExecute(Integer rightMargin) {
			contentLayoutParams.rightMargin = rightMargin;
			contentLayout.setLayoutParams(contentLayoutParams);
		}
	}

	class RightMenuScrollTask extends AsyncTask<Integer, Integer, Integer> {

		@Override
		protected Integer doInBackground(Integer... speed) {
			int leftMargin = contentLayoutParams.leftMargin;
			// 根據傳入的速度來滾動界面,當滾動到達邊界值時,跳出循環。
			while (true) {
				leftMargin = leftMargin + speed[0];
				if (leftMargin < -rightMenuLayoutParams.width) {
					leftMargin = -rightMenuLayoutParams.width;
					break;
				}
				if (leftMargin > 0) {
					leftMargin = 0;
					break;
				}
				publishProgress(leftMargin);
				// 為了要有滾動效果產生,每次循環使線程睡眠一段時間,這樣肉眼才能夠看到滾動動畫。
				sleep(15);
			}
			if (speed[0] > 0) {
				isRightMenuVisible = false;
			} else {
				isRightMenuVisible = true;
			}
			isSliding = false;
			return leftMargin;
		}

		@Override
		protected void onProgressUpdate(Integer... leftMargin) {
			contentLayoutParams.leftMargin = leftMargin[0];
			contentLayout.setLayoutParams(contentLayoutParams);
			unFocusBindView();
		}

		@Override
		protected void onPostExecute(Integer leftMargin) {
			contentLayoutParams.leftMargin = leftMargin;
			contentLayout.setLayoutParams(contentLayoutParams);
		}
	}

	/**
	 * 使當前線程睡眠指定的毫秒數。
	 * 
	 * @param millis
	 *            指定當前線程睡眠多久,以毫秒為單位
	 */
	private void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
  
以上代碼注釋已經寫得非常詳細,我再來簡單解釋一下。首先在onLayout()方法中分別獲取到左側菜單、右側菜單和內容布局的參數,并將內容布局的寬度重定義成屏幕的寬度,這樣就可以保證內容布局既能覆蓋住下面的菜單布局,還能偏移出屏幕。然后在onTouch()方法中監聽觸屏事件,以判斷用戶手勢的意圖。這里事先定義好了幾種滑動狀態,DO_NOTHING表示沒有進行任何滑動,SHOW_LEFT_MENU表示用戶想要滑出左側菜單,SHOW_RIGHT_MENU表示用戶想要滑出右側菜單,HIDE_LEFT_MENU表示用戶想要隱藏左側菜單,HIDE_RIGHT_MENU表示用戶想要隱藏右側菜單,在checkSlideState()方法中判斷出用戶到底是想進行哪一種滑動操作,并給slideState變量賦值,然后根據slideState的值決定如何偏移內容布局。接著當用戶手指離開屏幕時,會根據當前的滑動距離,決定后續的滾動方向,通過LeftMenuScrollTask和RightMenuScrollTask來完成完整的滑動過程。另外在滑動的過程,內容布局上的事件會被屏蔽掉,主要是通過一系列的return操作實現的,對這一部分不理解的朋友,請參閱 Android事件分發機制完全解析,帶你從源碼的角度徹底理解 。

然后我們看一下setScrollEvent方法,這個方法接收一個View作為參數,然后為這個View綁定了一個touch事件。這是什么意思呢?讓我們來想象一個場景,如果內容布局是一個LinearLayout,我可以通過監聽LinearLayout上的touch事件來控制它的偏移。但是如果內容布局的LinearLayout里面加入了一個ListView,而這個ListView又充滿了整個LinearLayout,這個時候LinearLayout將不可能再被touch到了,這個時候我們就需要將touch事件注冊到ListView上。setScrollEvent方法也就是提供了一個注冊接口,touch事件將會注冊到傳入的View上。

接下來打開或新建activity_main.xml文件,加入如下代碼:

    <com.example.bidirslidinglayout.BidirSlidingLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bidir_sliding_layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:id="@+id/left_menu"
        android:layout_width="270dip"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:background="#00ccff"
        android:visibility="invisible" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="This is left menu"
            android:textColor="#000000"
            android:textSize="28sp" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/right_menu"
        android:layout_width="270dip"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:background="#00ffcc"
        android:visibility="invisible" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="This is right menu"
            android:textColor="#000000"
            android:textSize="28sp" />
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/content"
        android:layout_width="320dip"
        android:layout_height="fill_parent"
        android:background="#e9e9e9" >

        <ListView
            android:id="@+id/contentList"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scrollbars="none"
            android:cacheColorHint="#00000000" >
        </ListView>
    </LinearLayout>

</com.example.bidirslidinglayout.BidirSlidingLayout>
  
可以看到,我們使用了自定義的BidirSlidingLayout作為根布局,然后依次加入了三個子布局分別作為左側菜單、右側菜單和內容的布局。左側菜單和右側菜單中都只是簡單地放入了一個TextView用于顯示一段文字,內容布局中放入了一個ListView。注意要讓左側菜單和父布局左邊緣對齊,右側菜單和父布局右邊緣對齊。

最后打開或者創建MainActivity作為程序的主Activity,代碼如下所示:

    public class MainActivity extends Activity {

	/**
	 * 雙向滑動菜單布局
	 */
	private BidirSlidingLayout bidirSldingLayout;

	/**
	 * 在內容布局上顯示的ListView
	 */
	private ListView contentList;

	/**
	 * ListView的適配器
	 */
	private ArrayAdapter<String> contentListAdapter;

	/**
	 * 用于填充contentListAdapter的數據源。
	 */
	private String[] contentItems = { "Content Item 1", "Content Item 2", "Content Item 3",
			"Content Item 4", "Content Item 5", "Content Item 6", "Content Item 7",
			"Content Item 8", "Content Item 9", "Content Item 10", "Content Item 11",
			"Content Item 12", "Content Item 13", "Content Item 14", "Content Item 15",
			"Content Item 16" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		bidirSldingLayout = (BidirSlidingLayout) findViewById(R.id.bidir_sliding_layout);
		contentList = (ListView) findViewById(R.id.contentList);
		contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
				contentItems);
		contentList.setAdapter(contentListAdapter);
		bidirSldingLayout.setScrollEvent(contentList);
	}

}
  
這里我們給ListView填充了幾條數據,又通過findViewById()方法獲取到了BidirSlidingLayout對象,然后調用它的setScrollEvent()方法,將ListView進行綁定,這樣就可以通過左右滑動ListView來展示左側菜單和右側菜單了。

好了,全部編碼工作都已完成,現在讓我們運行一下程序吧,效果如下圖所示:

Android雙向滑動菜單完全解析,教你如何一分鐘實現雙向滑動特效

看起來還是挺不錯的吧!并且更重要的是,以后我們在項目的任何地方都可以輕松加入雙向滑動菜單功能,只需要以下兩步即可:

1.在Acitivty的layout中引入我們自定義的BidirSlidingLayout布局,并且給這個布局要加入三個直接子元素。

2.在Activity中通過setScrollEvent方法,給一個View注冊touch事件。

如此一來,一分鐘實現雙向滑動菜單功能妥妥的。

好了,今天的講解到此結束,有疑問的朋友請在下面留言。

源碼下載,請點擊這里

Android雙向滑動菜單完全解析,教你如何一分鐘實現雙向滑動特效


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产系列在线播放 | 色老头福影院韩国激情影院 | 在线观看一级毛片 | 亚洲a免费 | 操操操干干干 | 青春草禁区视频在线观看 | 99热久热这里只精品 | 狠狠狠色丁香婷婷综合久久五月 | 欧美视频在线一区二区三区 | 9久久免费国产精品特黄 | 欧美成人午夜精品一区二区 | 日本高清一级做a爱过程免费视频 | 毛片91 | 奇米福利视频 | 色偷偷免费视频 | 国产精品欧美一区二区三区不卡 | 欧美另类亚洲一区二区 | 日本黄色网址免费 | www.精品视频 | 日韩一区二区中文字幕 | 日韩特级毛片免费观看视频 | 色综合成人丁香 | 天天干夜夜做 | 曰本女人一级毛片看一级毛 | 久久视频在线看 | 国产激情| 哪里有毛片 | 精品欧美高清一区二区免费 | 久久久久久久久久免免费精品 | 成人免费aa在线观看 | 久久精品中文字幕久久 | 四虎影院在线播放视频 | 欧美一级毛片免费大全 | 欧美精品一区二区三区观 | 久久久久久久久66精品片 | 爽爽影院免费观看视频 | 一级aa 毛片高清免费看 | 久久久久国产一级毛片高清板 | 久久精品视频9 | 色婷婷精品免费视频 | 久操视频免费在线观看 |