Предотвращение отклонения диалога при повороте экрана в Android
Я пытаюсь запретить отклонения диалогов, построенных с помощью Alert builder, после перезапуска Activity.
Если я перегружаю метод onConfigurationChanged, я могу это сделать успешно и reset макет для исправления ориентации, но я теряю липкую текстовую функцию edittext. Поэтому при решении диалогового вопроса я создал эту проблему edittext.
Если я сохраню строки из edittext и переназначаю их в изменении onCofiguration, они по-прежнему по умолчанию имеют начальное значение, а не то, что было введено перед вращением. Даже если я могу заставить invalidate, похоже, обновить их.
Мне действительно нужно решить либо проблему диалога, либо проблему edittext.
Спасибо за помощь.
Ответы
Ответ 1
Лучший способ избежать этой проблемы в настоящее время - использовать 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+
Этот ответ помогает объяснить эти три других вопроса (и их ответы):
Ответ 2
// 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);
}
Ответ 3
Если вы меняете макет при изменении ориентации, я бы не поместил 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();
, чтобы получить объект.
Ответ 4
На этот вопрос был дан ответ давным-давно.
Но это не-хаки и простое решение, которое я использую для себя.
Я сделал этот вспомогательный класс для себя, чтобы вы могли использовать его и в своем приложении.
Использование:
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;
}
}
}
Ответ 5
Очень простой подход - создать диалоги из метода onCreateDialog()
(см. примечание ниже). Вы показываете их через showDialog()
. Таким образом, Android обрабатывает вращение для вас, и вам не нужно вызывать dismiss()
в onPause()
, чтобы избежать WindowLeak, и вам также не нужно восстанавливать диалог. Из документов:
Показать диалог, управляемый этим действием. Вызов onCreateDialog (int, Bundle) будет производиться с тем же идентификатором, когда в первый раз это вызвано для данного идентификатора. После этого диалог будет автоматически сохранен и восстановлен.
Для получения дополнительной информации см. Android docs showDialog(). Надеюсь, это поможет кому-то!
Примечание.. Если вы используете AlertDialog.Builder, не вызывайте show()
из onCreateDialog()
, тогда вызывайте create()
. Если вы используете ProgressDialog, просто создайте объект, задайте нужные параметры и вернете его. В заключение, show()
внутри onCreateDialog()
вызывает проблемы, просто создайте экземпляр диалогового окна и верните его. Это должно сработать! (У меня возникли проблемы с использованием showDialog() из onCreate(), фактически не отображая диалог, но если вы используете его в onResume() или в обратном вызове прослушивателя, он работает хорошо).
Ответ 6
Вы можете объединить методы Диалог onSave/onRestore с помощью методов Activity onSave/onRestore, чтобы сохранить состояние диалогового окна.
Примечание. Этот метод работает для этих "простых" диалогов, таких как отображение предупреждающего сообщения. Он не будет воспроизводить содержимое 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());
}
Ответ 7
Просто добавьте android: configChanges = "ориентация" с вашей деятельностью
в AndroidManifest.xml
Пример:
<activity
android:name=".YourActivity"
android:configChanges="orientation"
android:label="@string/app_name"></activity>
Ответ 8
Просто используйте
ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize
и приложение будет знать, как обрабатывать вращение и размер экрана.