今天遇到了一個很詭異的問題,Android 的 setEnable(false) 沒有作用,網上找的很多方法還是沒用。會出現這種情況的有下面幾個場景:
- ListView中的子檢視setEnable(false)後點選仍然會相應onItemClick
- FrameLayout中上層試圖disable後,的確沒有響應事件,但是touch事件傳遞到下層檢視了
- ViewGroup呼叫setEnable(false),不會自動把子檢視設為disabled
針對第一個場景,同事給出了一個解決方法:設定一個空的onClickListener
1 2 3 4 5 6 7 |
view.setEnabled ( false ); view.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { // nothing, just to fix the bug that the view can be clicked. } } ); |
其實上面的做法就是消費點選事件但是什麼都不做,並不是一般情況下的不消費點選事件。在Android的View原始碼中我找到了產生這個效果的原因,具體看下面程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public boolean onTouchEvent(MotionEvent event) { final float x = event.getX(); final float y = event.getY(); final int viewFlags = mViewFlags; if ((viewFlags & ENABLED_MASK) == DISABLED) { if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { setPressed(false); } // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); } // ENABLED_MASK為DISABLED時,且isClickable()或isLongClickable()為true時,onTouchEvent 直接return true,消費了事件卻不做其他事情 // 而setOnClickListener時,會setClickable(true). ... } /** * Register a callback to be invoked when this view is clicked. If this view is not * clickable, it becomes clickable. * * @param l The callback that will run * * @ see #setClickable(boolean) */ public void setOnClickListener(OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; } |
場景分析
現在再來分析開始提到的三個場景:
- ListView的子試圖為disabled後不消費touch事件,接下來傳到ListView後呼叫onItemClick方法,所以子檢視自己消費touch事件,就不會傳遞下去了。
- FrameLayout中的上層檢視disabled後,傳遞到下面的檢視跟場景1是一樣的,都可以通過前面提過的解決方法解決,不過setOnClickListener可以用setClickable替代。
1 2 |
view.setEnabled(false); view.setClickable(true); |
3. ViewGroup設為disabled之後,子檢視仍然可以正常點選,這個問題網上很多人都說用遍歷子檢視逐個setEnable(false)的方法,不過都是用遞迴演算法實現的,下面我給出迴圈的實現方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public static void setEnabled(View view, boolean enabled) { if(null == view) { return; } if(view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; LinkedList<ViewGroup> queue = new LinkedList<ViewGroup>(); queue.add(viewGroup); // 遍歷viewGroup while(!queue.isEmpty()) { ViewGroup current = queue.removeFirst(); current.setEnabled(enabled); for(int i = 0; i < current.getChildCount(); i ++) { if(current.getChildAt(i) instanceof ViewGroup) { queue.addLast((ViewGroup) current.getChildAt(i)); }else { current.getChildAt(i).setEnabled(enabled); } } } }else { view.setEnabled(enabled); } } |
這篇文章就到這裡,有什麼問題歡迎大家與我溝通交流。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式