Android 開發(fā)之Dialog中隱藏鍵盤的正確使用方法
Android 開發(fā)之Dialog中隱藏鍵盤的正確使用方法
場景:彈出一個(gè)Dialog,里面有一個(gè)EditText,用來輸入內(nèi)容,因?yàn)檩斎霑r(shí),需要彈出鍵盤,所以當(dāng)Dialog消失時(shí),鍵盤要一起隱藏。
現(xiàn)在我們做一個(gè)自定義的Dialog
MyDialog extends Dialog
一開始認(rèn)為這個(gè)功能很容易實(shí)現(xiàn),于是寫了下面的代碼
//Dialog的構(gòu)造函數(shù)中寫
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)根本無法隱藏,看看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,無法隱藏。
也就是說,你監(jiān)聽Cancel或者Dismiss都是不行的,因?yàn)榇藭r(shí)Dialog已經(jīng)消失,用于輸入的服務(wù)窗體已經(jīng)是null了,所以你要想 隱藏鍵盤,就需要在Dismiss之前處理,那這個(gè)入口在哪呢?
為了當(dāng)點(diǎn)擊空白處時(shí),可以隱藏Dialog,所以我們在構(gòu)造函數(shù)中加了一句話
this.setCanceledOnTouchOutside(true);
所以當(dāng)我們點(diǎn)擊空白區(qū)域時(shí),會觸發(fā)Dialog的onTouchEvent
public boolean onTouchEvent(MotionEvent event) {
if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
cancel();
return true;
}
return false;
}
這里會調(diào)用基類Window的shouldCloseOnTouch方法,來判斷是否可以關(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();
}
這里面就會dismiss掉Dialog,所以我們發(fā)現(xiàn),在dismiss前,我們根本無法干預(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));
}
如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
談?wù)凙ndroid的三種網(wǎng)絡(luò)通信方式
Android平臺有三種網(wǎng)絡(luò)接口可以使用,他們分別是:java.net.*(標(biāo)準(zhǔn)Java接口)、Org.apache接口和Android.net.*(Android網(wǎng)絡(luò)接口)。本文詳細(xì)的介紹,有興趣的可以了解一下。2017-01-01
Android實(shí)現(xiàn)跨進(jìn)程接口回掉的方法
這篇文章主要給大家介紹了關(guān)于Android如何實(shí)現(xiàn)跨進(jìn)程接口回掉的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Android自定義View模仿即刻點(diǎn)贊數(shù)字切換效果實(shí)例
有一個(gè)項(xiàng)目是仿即刻的點(diǎn)贊,這篇文章主要給大家介紹了關(guān)于Android自定義View模仿即刻點(diǎn)贊數(shù)字切換效果的相關(guān)資料,文中通過示例代碼介紹 的非常詳細(xì),需要的朋友可以參考下2022-12-12
Android開發(fā)之自定義view實(shí)現(xiàn)通訊錄列表A~Z字母提示效果【附demo源碼下載】
這篇文章主要介紹了Android開發(fā)之自定義view實(shí)現(xiàn)通訊錄列表A~Z字母提示效果,結(jié)合完整實(shí)例形式分析了Android獲取通訊錄列表及采用自定義view排列顯示的相關(guān)操作技巧,需要的朋友可以參考下2017-07-07
深入解讀Android開發(fā)中Activity的生命周期
這篇文章主要介紹了Android開發(fā)中Activity的生命周期,包括Activity的停止和銷毀等重要內(nèi)容,非常推薦!需要的朋友可以參考下2015-12-12
EditText限制小數(shù)點(diǎn)前后位數(shù)的實(shí)例
下面小編就為大家?guī)硪黄狤ditText限制小數(shù)點(diǎn)前后位數(shù)的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04
詳解Flutter如何在單個(gè)屏幕上實(shí)現(xiàn)多個(gè)列表
這篇文章主要為大家詳細(xì)介紹了Flutter如何在單個(gè)屏幕上實(shí)現(xiàn)多個(gè)列表,這些列表可以水平排列、網(wǎng)格格式、垂直排列,甚至是這些常用布局的組合,感興趣的小伙伴可以了解下2023-11-11
Android Handle原理(Looper,Handler和Message)三者關(guān)系案例詳解
這篇文章主要介紹了Android Handle原理(Looper,Handler和Message三者關(guān)系案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08

