ユーザーがEditTextフィールド内を押すとポップアップする特別なキーボードを含むフローティングダイアログ用のダイアログフラグメントがあります(通常のIMEは表示されません)。
ユーザーが(通常のIMEサービスの場合と同様に)戻るボタンを押したときにキーボードを閉じて(表示= GONE)、ダイアログが表示されたままになるようにします。ただし、SOおよび他の場所でのかなり広範囲にわたる読み取りからわかる限り、これを行う方法はないようです。
ダイアログをキャンセル不可に設定した場合、ダイアログはキャンセルできないため、onCancel()またはonDismiss()から通知されません。
ダイアログをキャンセル可能に設定すると、通知が表示されますが、ダイアログは閉じられます。
フラグメントがダイアログのライフサイクルを処理できるように、システムによって置き換えられるため、フラグメント内のダイアログにonKeyListenerをアタッチできません。
これを行う方法はありますか?または、主要なイベントの検出へのアクセスは、フラグメントシステムの目的のために完全に隔離されていますか?
最善の方法で最もクリーンな方法は、onCreateDialog()で作成したダイアログでonBackPressed()をオーバーライドすることです。
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(getActivity(), getTheme()){
@Override
public void onBackPressed() {
//do your stuff
}
};
}
私はあなたと同じ問題を抱えていましたが、onKeyListenerをdialogfragmentにアタッチすることで修正しました。
DialogFragmentを拡張するクラスのメソッドonResume()
に次のコードを配置します。
getDialog().setOnKeyListener(new OnKeyListener()
{
@Override
public boolean onKey(Android.content.DialogInterface dialog, int keyCode,Android.view.KeyEvent event) {
if ((keyCode == Android.view.KeyEvent.KEYCODE_BACK))
{
//Hide your keyboard here!!!
return true; // pretend we've processed it
}
else
return false; // pass on to be processed as normal
}
});
ここで見つけることができる問題の1つは、このコードが2回実行されることです。1つはユーザーが戻るボタンを押すとき、もう1つはボタンを押して離れるときです。その場合、イベントでフィルタリングする必要があります。
@Override
public void onResume() {
super.onResume();
getDialog().setOnKeyListener(new OnKeyListener()
{
@Override
public boolean onKey(Android.content.DialogInterface dialog, int keyCode,
Android.view.KeyEvent event) {
if ((keyCode == Android.view.KeyEvent.KEYCODE_BACK))
{
//This is the filter
if (event.getAction()!=KeyEvent.ACTION_DOWN)
return true;
else
{
//Hide your keyboard here!!!!!!
return true; // pretend we've processed it
}
}
else
return false; // pass on to be processed as normal
}
});
}
Juan Pedro Martinezの回答の補遺として、このスレッドを見たときに特定の質問(私が持っていた質問)を明確にすると役立つと思いました。
新しいDialogFragmentを作成し、ユーザーがバックボタンを使用してのみキャンセルできるようにしたい場合は、ランダムな画面タッチがフラグメントを時期尚早にキャンセルしないようにします。これが使用するコードです。
DialogFragmentを呼び出すコードでは、キャンセル可能な設定をfalseに設定して、NOTHINGがフラグメントを破棄したり、画面に触れたりしないようにする必要があります。
DialogFragment mDialog= new MyDialogFragment();
mDialog.setCancelable(false);
mDialog.show(getFragmentManager(), "dialog");
次に、DialogFragment(この場合はMyDaialogFragment.Java)内で、onResumeオーバーライドコードを追加して、ダイアログに[戻る]ボタンをリッスンさせます。押されると、dismiss()を実行してフラグメントを閉じます。
@Override
public void onResume()
{
super.onResume();
getDialog().setOnKeyListener(new OnKeyListener()
{
@Override
public boolean onKey(Android.content.DialogInterface dialog,
int keyCode,Android.view.KeyEvent event)
{
if ((keyCode == Android.view.KeyEvent.KEYCODE_BACK))
{
// To dismiss the fragment when the back-button is pressed.
dismiss();
return true;
}
// Otherwise, do nothing else
else return false;
}
});
これで、ダイアログは "setCancelable"をfalseに設定して呼び出されます。つまり、何も(外部からのクリックは)キャンセルおよびシャットダウンできず、(ダイアログ自体から)戻るボタンのみを閉じることができます。
がんばって!
Fragment onCancelオーバーライドメソッドを使用します。戻るときに呼び出されます。サンプルは次のとおりです。
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
// Add you codition
}
誰もこれを提案していませんか?
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// Add back button listener
dialog.setOnKeyListener(new Dialog.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent keyEvent) {
// getAction to make sure this doesn't double fire
if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_UP) {
// Your code here
return true; // Capture onKey
}
return false; // Don't capture
}
});
return dialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity(), getTheme()) {
@Override
public void onBackPressed() {
//your code
}
};
return dialog;
}
ダイアログを作成するときに、onBackPressedとonTouchEventの両方をオーバーライドします。
final Dialog dialog = new Dialog(activity) {
@Override
public boolean onTouchEvent(final MotionEvent event) {
//note: all touch events that occur here are outside the dialog, yet their type is just touching-down
boolean shouldAvoidDismissing = ... ;
if (shouldAvoidDismissing)
return true;
return super.onTouchEvent(event);
}
@Override
public void onBackPressed() {
boolean shouldAvoidDismissing = ... ;
if (!shouldSwitchToInviteMode)
dismiss();
else
...
}
};
closeActivityフラグを指定してDialogFragmentのonDismiss()コールバックを使用する
private var closeActivity: Boolean = true
override fun onDismiss(dialog: DialogInterface?) {
super.onDismiss(dialog)
if (closeActivity) {
activity!!.finish()
}
}