Предотвращение отклонения диалога при повороте экрана в Android

Я пытаюсь запретить отклонения диалогов, построенных с помощью Alert builder, после перезапуска Activity.

Если я перегружаю метод onConfigurationChanged, я могу это сделать и сбросить макет, чтобы исправить ориентацию, но я потерял липкую текстовую функцию edittext. Поэтому при решении проблемы диалога я создал эту проблему edittext.

Если я сохраню строки из edittext и переназначаю их в изменении onCofiguration, они по-прежнему по умолчанию имеют начальное значение, а не то, что было введено перед вращением. Даже если я могу заставить invalidate, похоже, обновить их.

Мне действительно нужно решить либо проблему диалога, либо проблему edittext.

Спасибо за помощь.

Solutions Collecting From Web of "Предотвращение отклонения диалога при повороте экрана в Android"

Лучший способ избежать этой проблемы в настоящее время – использовать DialogFragment .

Создайте новый класс, который расширяет DialogFragment . Переопределите onCreateDialog и верните старый Dialog или AlertDialog .

Затем вы можете показать его с помощью DialogFragment.show(fragmentManager, tag) .

Вот пример с Listener :

 public class MyDialogFragment extends DialogFragment { public interface YesNoListener { void onYes(); void onNo(); } @Override public void onAttach(Activity activity) { super.onAttach(activity); if (!(activity instanceof YesNoListener)) { throw new ClassCastException(activity.toString() + " must implement YesNoListener"); } } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(R.string.dialog_my_title) .setMessage(R.string.dialog_my_message) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ((YesNoListener) getActivity()).onYes(); } }) .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ((YesNoListener) getActivity()).onNo(); } }) .create(); } } 

И в Управлении вы вызываете:

 new MyDialogFragment().show(getSupportFragmentManager(), "tag"); // or getFragmentManager() in API 11+ 

Этот ответ смешивает эти три вопроса (и их ответы):

  • Android Лучший способ избежать диалогов, которые нужно отклонить после поворота устройства
  • Android DialogFragment vs Dialog
  • Как я могу показать DialogFragment с помощью пакета совместимости?
 // Prevent dialog dismiss when orientation changes private static void doKeepDialog(Dialog dialog){ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); lp.copyFrom(dialog.getWindow().getAttributes()); lp.width = WindowManager.LayoutParams.WRAP_CONTENT; lp.height = WindowManager.LayoutParams.WRAP_CONTENT; dialog.getWindow().setAttributes(lp); } 
 public static void doLogout(final Context context){ final AlertDialog dialog = new AlertDialog.Builder(context) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle(R.string.titlelogout) .setMessage(R.string.logoutconfirm) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ... } }) .setNegativeButton("No", null) .show(); doKeepDialog(dialog); } 

Если вы меняете макет при изменении ориентации, я бы не поставил android:configChanges="orientation" в вашем манифесте, потому что вы все равно воссоздаете представления.

Сохраните текущее состояние вашей активности (например, введенный текст, отображаемый диалог, данные и т. Д.), Используя следующие методы:

 @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); } 

Таким образом, активность снова проходит через CreateCreate, а затем вызывает метод onRestoreInstanceState, где вы можете снова установить значение EditText.

Если вы хотите хранить более сложные объекты, вы можете использовать

 @Override public Object onRetainNonConfigurationInstance() { } 

Здесь вы можете сохранить любой объект, а в onCreate вам просто нужно вызвать getLastNonConfigurationInstance(); Для получения объекта.

Очень простой подход – создать диалоги из метода onCreateDialog() (см. Примечание ниже). Вы показываете их через showDialog() . Таким образом, Android обрабатывает поворот для вас, и вам не нужно вызывать onPause() в onPause() чтобы избежать WindowLeak, и вам также не нужно восстанавливать диалог. Из документов:

Покажите диалог, управляемый этим действием. Вызов onCreateDialog (int, Bundle) будет выполнен с одним и тем же идентификатором в первый раз, когда это вызвано для данного идентификатора. После этого диалог будет автоматически сохранен и восстановлен.

Дополнительную информацию см. В разделе Android docs showDialog () . Надеюсь, это поможет кому-то!

Примечание. Если вы используете AlertDialog.Builder, не вызывайте show() из onCreateDialog() , тогда вызовите create() . Если вы используете ProgressDialog, просто создайте объект, установите необходимые параметры и верните его. В заключение, show() внутри onCreateDialog() вызывает проблемы, просто создайте экземпляр Dialog и верните его. Это должно сработать! (У меня возникли проблемы с использованием showDialog () из onCreate (), фактически не отображая диалог, но если вы используете его в onResume () или в обратном вызове прослушивателя, он работает хорошо).

На этот вопрос был дан ответ давным-давно.

Тем не менее это не хакерское и простое решение, которое я использую для себя.

Я сделал этот класс помощников для себя, поэтому вы можете использовать его и в своем приложении.

Использование:

 PersistentDialogFragment.newInstance( getBaseContext(), RC_REQUEST_CODE, R.string.message_text, R.string.positive_btn_text, R.string.negative_btn_text) .show(getSupportFragmentManager(), PersistentDialogFragment.TAG); 

Или

  PersistentDialogFragment.newInstance( getBaseContext(), RC_EXPLAIN_LOCATION, "Dialog title", "Dialog Message", "Positive Button", "Negative Button", false) .show(getSupportFragmentManager(), PersistentDialogFragment.TAG); public class ExampleActivity extends Activity implements PersistentDialogListener{ @Override void onDialogPositiveClicked(int requestCode) { switch(requestCode) { case RC_REQUEST_CODE: break; } } @Override void onDialogNegativeClicked(int requestCode) { switch(requestCode) { case RC_REQUEST_CODE: break; } } } 

Вы можете комбинировать методы onSave / onRestore Dialog с методами onSave / onRestore Activity, чтобы сохранить состояние диалогового окна .

Примечание. Этот метод работает для этих «простых» диалогов, таких как отображение предупреждающего сообщения. Он не будет воспроизводить содержимое WebView, встроенного в диалоговое окно. Если вы действительно хотите предотвратить смещение сложного диалога во время вращения, попробуйте метод Chung IW.

  @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); myDialog.onRestoreInstanceState(savedInstanceState.getBundle("DIALOG")); // Put your codes to retrieve the EditText contents and // assign them to the EditText here. } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // Put your codes to save the EditText contents and put them // to the outState Bundle here. outState.putBundle("DIALOG", myDialog.onSaveInstanceState()); } 

Просто добавьте android: configChanges = "ориентация" с вашим элементом активности в AndroidManifest.xml

Пример:

 <activity android:name=".YourActivity" android:configChanges="orientation" android:label="@string/app_name"></activity> 

Просто используйте

 ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize 

И приложение будет знать, как обрабатывать ротацию и размер экрана.