Android 開(kāi)發(fā)之Dialog中隱藏鍵盤(pán)的正確使用方法
Android 開(kāi)發(fā)之Dialog中隱藏鍵盤(pán)的正確使用方法
場(chǎng)景:彈出一個(gè)Dialog,里面有一個(gè)EditText,用來(lái)輸入內(nèi)容,因?yàn)檩斎霑r(shí),需要彈出鍵盤(pán),所以當(dāng)Dialog消失時(shí),鍵盤(pán)要一起隱藏。
現(xiàn)在我們做一個(gè)自定義的Dialog
MyDialog extends Dialog
一開(kāi)始認(rèn)為這個(gè)功能很容易實(shí)現(xiàn),于是寫(xiě)了下面的代碼
//Dialog的構(gòu)造函數(shù)中寫(xiě) this.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { hideKeyBoard(); } }); //edContent是輸入框 public void hideKeyBoard(){ InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(edContent.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); }
運(yùn)行之后,發(fā)現(xiàn)根本無(wú)法隱藏,看看hideSoftInputFromWindow中干了啥
public boolean hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver) { checkFocus(); synchronized (mH) { if (mServedView == null || mServedView.getWindowToken() != windowToken) { return false; } try { return mService.hideSoftInput(mClient, flags, resultReceiver); } catch (RemoteException e) { } return false; } }
跟蹤進(jìn)去發(fā)現(xiàn)參數(shù) windowToken 是 null,而且 mServedView 也是null,所以直接返回false,無(wú)法隱藏。
也就是說(shuō),你監(jiān)聽(tīng)Cancel或者Dismiss都是不行的,因?yàn)榇藭r(shí)Dialog已經(jīng)消失,用于輸入的服務(wù)窗體已經(jīng)是null了,所以你要想 隱藏鍵盤(pán),就需要在Dismiss之前處理,那這個(gè)入口在哪呢?
為了當(dāng)點(diǎn)擊空白處時(shí),可以隱藏Dialog,所以我們?cè)跇?gòu)造函數(shù)中加了一句話
this.setCanceledOnTouchOutside(true);
所以當(dāng)我們點(diǎn)擊空白區(qū)域時(shí),會(huì)觸發(fā)Dialog的onTouchEvent
public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) { cancel(); return true; } return false; }
這里會(huì)調(diào)用基類(lèi)Window的shouldCloseOnTouch方法,來(lái)判斷是否可以關(guān)閉,這里我們看到如果滿足,就直接cancel()了,
public void cancel() { if (!mCanceled && mCancelMessage != null) { mCanceled = true; // Obtain a new message so this dialog can be re-used Message.obtain(mCancelMessage).sendToTarget(); } dismiss(); }
這里面就會(huì)dismiss掉Dialog,所以我們發(fā)現(xiàn),在dismiss前,我們根本無(wú)法干預(yù),真是個(gè)悲劇。所以我們只能重載onTouchEvent方法,并且自己判斷是否可以關(guān)閉(也就是把下面代碼遷移到你的代碼中!
public boolean shouldCloseOnTouch(Context context, MotionEvent event) { if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(context, event) && peekDecorView() != null) { return true; } return false; } private boolean isOutOfBounds(Context context, MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop(); final View decorView = getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); }
自己代碼中這樣
@Override public boolean onTouchEvent(MotionEvent event) { if (isShowing() && shouldCloseOnTouch(getContext(),event)){ hideKeyBoard(); } return super.onTouchEvent(event); } public boolean shouldCloseOnTouch(Context context, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(context, event) && getWindow().peekDecorView() != null) { return true; } return false; } private boolean isOutOfBounds(Context context, MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); }
如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
ASM的tree?api對(duì)匿名線程的hook操作詳解
這篇文章主要為大家介紹了ASM的tree?api對(duì)匿名線程的hook操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Android解決dialog彈出時(shí)無(wú)法捕捉Activity的back事件的方法
這篇文章主要介紹了Android解決dialog彈出時(shí)無(wú)法捕捉Activity的back事件的方法,涉及Android操作Activity事件的相關(guān)技巧,需要的朋友可以參考下2015-05-05Android自定義GestureDetector實(shí)現(xiàn)手勢(shì)ImageView
這篇文章主要為大家詳細(xì)介紹了Android自定義GestureDetector實(shí)現(xiàn)手勢(shì)ImageView的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03OpenGL Shader實(shí)例分析(7)雪花飄落效果
這篇文章主要為大家詳細(xì)介紹了OpenGL Shader實(shí)例分析第7篇,實(shí)現(xiàn)雪花飄落效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02SeekBar拖動(dòng)條的應(yīng)用實(shí)例
這篇文章主要為大家詳細(xì)介紹了SeekBar拖動(dòng)條的應(yīng)用實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10Flutter 狀態(tài)管理的實(shí)現(xiàn)
這篇文章主要介紹了Flutter 狀態(tài)管理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06安卓(Android)開(kāi)發(fā)之統(tǒng)計(jì)App啟動(dòng)時(shí)間
當(dāng)大家要改善APP啟動(dòng)速度優(yōu)化的時(shí)候,首先要知道App的啟動(dòng)時(shí)間,那么改如何統(tǒng)計(jì)時(shí)間呢,下面我們一起來(lái)看看。2016-08-08Android Chronometer控件實(shí)現(xiàn)計(jì)時(shí)器函數(shù)詳解
這篇文章主要為大家詳細(xì)介紹了Android Chronometer控件實(shí)現(xiàn)計(jì)時(shí)器函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04