BottomSheetDialogFragment
の最終解雇を聞くにはどうすればよいですか?最終解雇時にのみユーザーの変更を保存したい...
私は次のことを試しました:
方法1
これは、ダイアログが下にスワイプして閉じられた場合にのみ発生します(バックプレスまたは外側のタッチではありません)。
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
Dialog d = super.onCreateDialog(savedInstanceState);
d.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(Android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior behaviour = BottomSheetBehavior.from(bottomSheet);
behaviour.setState(BottomSheetBehavior.STATE_EXPANDED);
behaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN)
{
// Bottom Sheet was dismissed by user! But this is only fired, if dialog is swiped down! Not if touch outside dismissed the dialog or the back button
Toast.makeText(MainApp.get(), "HIDDEN", Toast.LENGTH_SHORT).show();
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}
});
return d;
}
方法2
これにより、最終的な解雇と、画面の回転やアクティビティのレクリエーションからの解雇を区別できません...
@Override
public void onDismiss(DialogInterface dialog)
{
super.onDismiss(dialog);
// this works fine but fires one time too often for my use case, it fires on screen rotation as well, although this is a temporarily dismiss only
Toast.makeText(MainApp.get(), "DISMISSED", Toast.LENGTH_SHORT).show();
}
質問
ユーザーがダイアログを終了したことを示すイベントを聞くにはどうすればよいですか?
SOに関する同様の質問はすべて、onDismiss
の使用を推奨していますが、以下が正しい解決策だと思います。
@Override
public void onCancel(DialogInterface dialog)
{
super.onCancel(dialog);
Toast.makeText(MainApp.get(), "CANCEL", Toast.LENGTH_SHORT).show();
}
これは次の場合に起動します:
* the user presses back
* the user presses outside of the dialog
これは起動しません:
* on screen rotation and activity recreation
ソリューション
onCancelとBottomSheetBehavior.BottomSheetCallback.onStateChangedを次のように組み合わせます:
public class Dailog extends BottomSheetDialogFragment
{
@Override
public void onCancel(DialogInterface dialog)
{
super.onCancel(dialog);
handleUserExit();
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
Dialog d = super.onCreateDialog(savedInstanceState);
d.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(Android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior behaviour = BottomSheetBehavior.from(bottomSheet);
behaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN)
{
handleUserExit();
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}
});
return d;
}
private void handleUserExit()
{
Toast.makeText(MainApp.get(), "TODO - SAVE data or similar", Toast.LENGTH_SHORT).show();
}
}
私はこの簡単なトリックを使用してこれを達成しました
val bottomSheetDialog = FeedbackFormsFragment.createInstance()
bottomSheetDialog.show((activity as FragmentActivity).supportFragmentManager, BOTTOM_SHEET)
// add some delay to allow the bottom sheet to be visible first so that the dialog is not null
Handler().postDelayed({
bottomSheetDialog.dialog?.setOnDismissListener {
// add code here
}
}, 1000)
@ prom85のメソッドは機能しますが、別のメソッドがあります。ある場合にBottomSheetDialogFragment
を却下し、別の場合には保持したい場合、それは機能しません。すべての場合にダイアログを閉じます。
たとえば、EditText
のBottomSheetDialogFragment
の内側にテキストを入力し、ときどき外側をクリックすると、警告なしにダイアログが閉じます。 https://medium.com/@anitas3791/Android-bottomsheetdialog-3871a6e9d538 を試しましたが、動作しますが、別のシナリオで。ダイアログを下にドラッグすると、ダイアログは閉じられます。外部をクリックしても、警告メッセージは表示されず、ダイアログは閉じられません。
そこで、私は https://stackoverflow.com/a/50734566/291414 から@shijoの素晴らしいアドバイスを使用しました。
これらの行をonActivityCreated
メソッド(またはonCreateView
の後の他のライフサイクルメソッド)に追加します。
_@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
View touchOutsideView = getDialog().getWindow()
.getDecorView()
.findViewById(Android.support.design.R.id.touch_outside);
touchOutsideView.setOnClickListener(yourClickListener);
}
_
私の場合、yourClickListener
でテキストを確認し、アラートを表示するか、ダイアログを閉じます。
_private fun checkAndDismiss() {
if (newText == oldText) {
dismissAllowingStateLoss()
} else {
showDismissAlert()
}
}
_
BottomSheetDialogFragment
を作成するとき、 https://stackoverflow.com/a/42679131/291414 のようにsetCancelable(false)
を呼び出さないでください。作業。そして、スタイルに_<item name="Android:windowCloseOnTouchOutside">false</item>
_を設定したり、onCreateDialog
にsetCanceledOnTouchOutside(false)
を設定したりしないでください。
キャンセル動作をオーバーライドする方法もいくつか試しましたが、成功しませんでした。
_<style name="BottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
<item name="Android:windowCloseOnTouchOutside">false</item>
</style>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.BottomSheetDialogTheme)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnShowListener {
val bottomSheet = dialog.findViewById<View>(
Android.support.design.R.id.design_bottom_sheet) as? FrameLayout
val behavior = BottomSheetBehavior.from(bottomSheet)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
//showing the different states.
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> dismiss() //if you want the modal to be dismissed when user drags the bottomsheet down
BottomSheetBehavior.STATE_EXPANDED -> {
}
BottomSheetBehavior.STATE_COLLAPSED -> {
}
BottomSheetBehavior.STATE_DRAGGING -> {
}
BottomSheetBehavior.STATE_SETTLING -> {
}
}
}
})
dialog.setOnCancelListener {
// Doesn't matter what you write here, the dialog will be closed.
}
dialog.setOnDismissListener {
// Doesn't matter what you write here, the dialog will be closed.
}
}
return dialog
}
override fun onCancel(dialog: DialogInterface?) {
// Doesn't matter what you write here, the dialog will be closed.
super.onCancel(dialog)
}
override fun onDismiss(dialog: DialogInterface?) {
// Doesn't matter what you write here, the dialog will be closed.
super.onDismiss(dialog)
}
_