Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 開源SlidingMenu的bug修改

Android 開源SlidingMenu的bug修改

編輯:關於Android編程

SlidingMenu相信大家都已經很熟悉了 ,源代碼托管在 https://github.com/jfeinstein10/SlidingMenu。首先我要感謝下原作者的大無畏精神,因為開源而偉大,哈哈。如果我們的項目中只想用到SlidingMenu,那我們就要把SlidingMenu這個控件給抽離出來了。這個是我抽離出來的的SlidingMenu控件源代碼(大家有需要的可以下載學習下)。如下:

SlidingMenu控件源代碼

我也很自豪的將這個開源控件運用在自己公司的項目中了,可是經公司的測試人員測試後,發現一個問題,SlidingMenu來回的快速切換(當SlidingMenu打開時,一個手指點擊SlidingMenu的下方布局(代碼中:自定義的CustomViewBehind),另一個手指同時點擊SlidingMenu的上方布局(CustomViewAbove)),頻繁的如此操作會出現這個一個現象(不是必現的哦):當SlidingMenu關閉後,任憑我怎麼點擊布局上面的控件,事件都不響應了,起初以為是應用卡死了,可是按設備上的退出,應用可以正常退出。那我初步定位原因就是CustomViewAbove這個自定義的ViewGroup把手勢事件給攔截了,以致於子View接受不到事件,就響應不了了。

那我們可以直接去看SlidingMenu控件的源代碼了,找到CustomViewAbove.java,然後我們找到這個方法onInterceptTouchEvent(),這個方法是ViewGroup的一個方法,目的是在系統向該ViewGroup及其各個childView觸發onTouchEvent()之前對相關事件進行一次攔截.如果onInterceptTouchEvent返回true,就表示該ViewGroup不會將事件向它的子childView傳遞了;返回false,就不攔截事件了。因此我覺得CustomViewAbove.java中的在上面那個現象中onInterceptTouchEvent方法返回true了,所以各種手勢事件都不響應了。我們看代碼吧:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

if (!mEnabled)
return false;

final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;

if (DEBUG)
if (action == MotionEvent.ACTION_DOWN)
Log.v(TAG, "Received ACTION_DOWN");

if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP
|| (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) {
endDrag();
return false;
}

switch (action) {
case MotionEvent.ACTION_MOVE:
determineDrag(ev);
break;
case MotionEvent.ACTION_DOWN:
int index = MotionEventCompat.getActionIndex(ev);
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
if (mActivePointerId == INVALID_POINTER)
break;
mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, index);
mLastMotionY = MotionEventCompat.getY(ev, index);
if (thisTouchAllowed(ev)) {
mIsBeingDragged = false;
mIsUnableToDrag = false;
if (isMenuOpen() && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
mQuickReturn = true;
}
} else {
mIsUnableToDrag = true;
}
break;
case MotionEventCompat.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
}

if (!mIsBeingDragged) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
}
return mIsBeingDragged || mQuickReturn;
}
看源代碼發現,onInterceptTouchEvent返回true或者false是由mIsBeingDragged(是否正在拖拽) 和 mQuickReturn(是否快速返回)兩個成員變量決定的。因此在某個特殊場景下,合理狀況是當SlidngMenu已經

關閉了,那IsBeingDragged和 mQuickReturn應該同時為false,但上述那個現象的原因就是IsBeingDragged或者mQuickReturn為true。說明頻繁的非常規操作,我們沒處理好這兩個變量。看源代碼,我發現每次ACTION_DOWN

時應該置IsBeingDragged和 mQuickReturn為false,因為ACTION_DOWN事件發生時,不可能正在拖拽或者SlidingMenu

快速關閉。見我添加的這兩行代碼(如下):

case MotionEvent.ACTION_DOWN:
mIsBeingDragged = false;
mQuickReturn = false;

OK,這個BUG就這樣解決了,說明在每次SlidingMenu關閉後IsBeingDragged和 mQuickReturn的值有問題,所以我決定在每次ACTION_DOWN將這兩個變量都置false。源代碼還是很多的,想要全部弄清楚還是要花時間滴,只能先針對現象解決問題啦。





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved