Android:Dialogでキーボードを隠すための注意点
4281 ワード
シーン:Dialogがポップアップされ、その中にEditTextがあり、内容を入力するために使用されます.入力時にキーボードをポップアップする必要があるので、Dialogが消えたとき、キーボードは一緒に隠します.
カスタムDialogを作成します
実行後、隠すことができないことに気づき、hideSoftInputFromWindowで何をしたか見てみましょう.
つまり、CancelやDismissを傍受するのはだめです.Dialogは消え、入力するサービスフォームはnullになっているので、キーボードを隠すには、Dismissの前に処理する必要があります.この入り口はどこですか.
空白をクリックすると、Dialogを隠すことができるように、コンストラクション関数に一言追加しました.
ここではベースクラスWindowのshouldCloseOnTouchメソッドを呼び出して閉じることができるかどうかを判断します.ここでは満足すれば、直接cancel()を見ることができます.
自分のコードの中でこのように
本当に少し仕方がなくて、今思い付いた方法はこのようにして、どなたがもっと良い方法があって、提供を歓迎します!
カスタムDialogを作成します
MyDialog extends Dialog
最初はこの機能が実現しやすいと思っていたので、次のコードを書きました.//Dialog
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);
}
実行後、隠すことができないことに気づき、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;
}
}
トレース中にパラメータwindowTokenがnullであり、mSerbedViewもnullであることが判明したため、直接falseに戻り、隠すことはできません.つまり、CancelやDismissを傍受するのはだめです.Dialogは消え、入力するサービスフォームはnullになっているので、キーボードを隠すには、Dismissの前に処理する必要があります.この入り口はどこですか.
空白をクリックすると、Dialogを隠すことができるように、コンストラクション関数に一言追加しました.
this.setCanceledOnTouchOutside(true);
空白領域をクリックするとDialogのonTouchEventがトリガーされます public boolean onTouchEvent(MotionEvent event) {
if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
cancel();
return true;
}
return false;
}
ここではベースクラスWindowのshouldCloseOnTouchメソッドを呼び出して閉じることができるかどうかを判断します.ここでは満足すれば、直接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を落とすので、dismissの前では介入できないことに気づきました.悲劇です.だから私たちはonTouchEventメソッドを再ロードして、自分で閉じることができるかどうかを判断するしかありません(つまり、次のコードをあなたのコードに移行します! 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));
}
本当に少し仕方がなくて、今思い付いた方法はこのようにして、どなたがもっと良い方法があって、提供を歓迎します!