Development Tip

뒤로 버튼을 감지하지만 dialogfragment를 닫지 않음

yourdevel 2020. 11. 25. 21:19
반응형

뒤로 버튼을 감지하지만 dialogfragment를 닫지 않음


사용자가 EditText 필드 내부를 누를 때 팝업되는 특수 키보드를 포함하는 부동 대화 상자에 대한 dialogfragment가 있습니다 (일반 IME가 표시되지 않음).

사용자가 뒤로 버튼 (일반 IME 서비스와 마찬가지로)을 눌렀을 때 키보드를 닫고 (visibility = GONE) 대화 상자가 계속 표시되도록하고 싶습니다. 그러나 SO 및 다른 곳에서 상당히 광범위한 독서에서 볼 수있는 한 이렇게하는 방법은없는 것 같습니다.

대화 상자를 취소 할 수 없도록 설정하면 대화 상자를 취소 할 수 없기 때문에 onCancel () 또는 onDismiss ()에서 알림을받지 못합니다.

대화 상자를 취소 가능으로 설정하면 알림이 표시되지만 대화 상자가 닫힙니다.

조각이 대화 상자의 수명주기를 처리 할 수 ​​있도록 시스템으로 대체 되었기 때문에 조각의 대화 상자에 onKeyListener를 연결할 수 없습니다.

이것을 할 방법이 있습니까? 아니면 Fragment 시스템의 목적을 위해 핵심 이벤트 감지에 대한 액세스가 완전히 차단 되었습니까?


가장 좋은 방법과 가장 깨끗한 방법은 onCreateDialog ()에서 만든 대화 상자에서 onBackPressed ()를 재정의하는 것입니다.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(getActivity(), getTheme()){
        @Override
        public void onBackPressed() {
            //do your stuff
        }
    };
}

나는 당신과 같은 문제가 있었고 onKeyListener를 dialogfragment에 연결하여 수정했습니다.

onResume()DialogFragment를 확장하는 클래스 의 메서드 에 다음 코드를 넣습니다.

    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
        }
    });

여기서 발견 할 수있는 문제 중 하나는이 코드가 두 번 실행된다는 것입니다. 하나는 사용자가 뒤로 버튼을 눌렀을 때이고 다른 하나는 사용자가 그것을 누르기 위해 떠날 때입니다. 이 경우 이벤트별로 필터링해야합니다.

@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;
         }
   });

Now your dialog will be called with the "setCancelable" to false, meaning nothing (no outside clicks) can cancel it and shut it down, and allowing (from within the dialog itself) only the back button to close it.

Ganbatte!


How has no one suggested this?

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;
}

Use Fragment onCancel override method. It's called when you press back. here is a sample:

@Override
public void onCancel(DialogInterface dialog) {
    super.onCancel(dialog);

    // Add you codition
}

When creating the dialog, override both onBackPressed and 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
                    ...
            }
        };

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity(), getTheme()) {
        @Override
        public void onBackPressed() {
            //your code
        }
    };

    return dialog;
}

Use onDismiss() callback of DialogFragment with a closeActivity flag

private var closeActivity: Boolean = true    

override fun onDismiss(dialog: DialogInterface?) {
        super.onDismiss(dialog)

        if (closeActivity) {
            activity!!.finish()
        }
    }

참고URL : https://stackoverflow.com/questions/21307858/detect-back-button-but-dont-dismiss-dialogfragment

반응형