What is the correct way to handle orientation changes when a custom alertdialog has an open counter?

In my application, I have a custom AlertDialog (handled by the system using showDialog ()) that contains a tab with two tabs. There is a spinner on one of the tabs. I can rotate my screen without problems until the counter is open (the counter dialog box is displayed). If the rotator is open during rotation, I get the following:

FATAL EXCEPTION: main java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200) at android.view.Window$LocalWindowManager.removeView(Window.java:432) at android.app.Dialog.dismissDialog(Dialog.java:278) at android.app.Dialog.access$000(Dialog.java:71) at android.app.Dialog$1.run(Dialog.java:111) at android.app.Dialog.dismiss(Dialog.java:268) at android.widget.Spinner.onDetachedFromWindow(Spinner.java:89) at android.view.View.dispatchDetachedFromWindow(View.java:6173) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1164) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1162) at android.view.ViewRoot.dispatchDetachedFromWindow(ViewRoot.java:1746) at android.view.ViewRoot.doDie(ViewRoot.java:2757) at android.view.ViewRoot.handleMessage(ViewRoot.java:1995) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3683) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at dalvik.system.NativeStart.main(Native Method) 

So...

1 - Is it possible to programmatically close the counter during onPause() ?

2 - Is there any other method I should use?

3 - If there is no right solution, how can I catch this particular exception? (The bad practice that I know, but the failure must be stopped, and since the activity is restored properly after the destruction, it does not matter in any way.

... And please, for the sake of love for everything holy, do not suggest adding android:configChanges="orientation" in your declaration of work. It amazes me how often this is accepted as an official correction for orientation issues.

Change Additional Information

Here is my dialog creation code for the link:

 static final int ID_DIALOG_CHOOSER = 1; int pref_location; private Dialog dialog; ... protected Dialog onCreateDialog(int id) { switch(id) { case ID_DIALOG_CHOOSER: dialog = show(ID_DIALOG_CHOOSER); break; } return dialog; } ... showDialog(DialogView.ID_DIALOG_CHOOSER); ... Dialog show(final int dialogType) { if (dialogType == ID_DIALOG_CHOOSER) { AlertDialog.Builder builder = new AlertDialog.Builder(this); // inflate tabhost layout View tabHostLayout = (View) inflater.inflate(R.layout.tabhost_layout, null); FrameLayout tabContent = (FrameLayout) tabHostLayout.findViewById(android.R.id.tabcontent); // inflate tab content layouts and add to tabhost layout LinearLayout tab1 = (LinearLayout) inflater.inflate(R.layout.dialog_tab1, null); tabContent.addView(tab1); LinearLayout tab2 = (LinearLayout) inflater.inflate(R.layout.dialog_tab2, null); tabContent.addView(tab2); // tab setup TabHost tabHost = (TabHost) tabHostLayout.findViewById(R.id.TabHost_Dialog_Tabs); tabHost.setup(); TabHost.TabSpec tab_1 = tabHost.newTabSpec("Category 1"); tab_1.setContent(R.id.LinearLayout_Dialog_Tab1_Content); tab_1.setIndicator(this.getResources().getString(R.string.dialog_tab1), this.getResources().getDrawable(R.drawable.tabhost_icon_selector)); tabHost.addTab(tab_1); TabHost.TabSpec tab_2 = tabHost.newTabSpec("Category 2"); tab_2.setContent(R.id.LinearLayout_Dialog_Tab2_Content); tab_2.setIndicator(this.getResources().getString(R.string.dialog_tab2), this.getResources().getDrawable(R.drawable.tabhost_icon_selector)); tabHost.addTab(tab_2); // spinner setup final Spinner spinner_location = (Spinner) tab1.findViewById(R.id.Spinner_Dialog_Location); String[] locationArrayVals = null; ArrayAdapter<CharSequence> adapter_location = null; locationArrayVals = this.getResources().getStringArray(R.array.location_array_vals); adapter_location = ArrayAdapter.createFromResource(this, R.array.location_array_listdisplay, android.R.layout.simple_spinner_item); adapter_location.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner_location.setAdapter(adapter_location); // ok button Button button_ok = (Button) tab1.findViewById(R.id.Button_Dialog_OK); button_ok.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { pref_location = spinner_location.getSelectedItemPosition(); dialog.dismiss(); } }); // create dialog builder.setTitle("Location") .setView(tabHost) .setCancelable(true); dialog = builder.create(); } return dialog; } 

Edit using a temporary workaround

For everyone that is interested, I managed to at least stop the crash by subclassing spinner and overriding onDetachedFromWindow() as follows:

 public static class CatchingSpinner extends Spinner { public CatchingSpinner(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDetachedFromWindow() { try { super.onDetachedFromWindow(); } catch (IllegalArgumentException e) { // do whatever } } } 

As I said, a workaround. Still working on a solution.: /

+6
source share
3 answers

I have found the best solution. In fact, it’s not so difficult to replace Spinner with a button that looks and behaves like a Spinner (except for a breakdown, fortunately).

 <Button android:background="@android:drawable/btn_dropdown" android:gravity="left|center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" /> 

 public void showSpinner() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(_spinnerPrompt); builder.setSingleChoiceItems(_spinnerOptions, _spinnerSelection, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int item) { _spinnerSelection = item; _pseudoSpinner.setText(_spinnerOptions[item]); _restoreSpinnerOnRestart = false; dialog.dismiss(); } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { _restoreSpinnerOnRestart = false; } }); AlertDialog alert = builder.create(); _restoreSpinnerOnRestart = true; alert.show(); } @Override public Bundle onSaveInstanceState() { Bundle state = super.onSaveInstanceState(); state.putBoolean(STATE_SPINNER_RESTORE, _restoreSpinnerOnRestart); state.putInt(STATE_SPINNER_SELECTION, _spinnerSelection); return state; }; @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); _spinnerSelection = savedInstanceState.getInt(STATE_SPINNER_SELECTION, -1); _restoreSpinnerOnRestart = savedInstanceState.getBoolean(STATE_SPINNER_RESTORE); _pseudoSpinner.setText(_spinnerOptions[_spinnerSelection]); if (_restoreSpinnerOnRestart) { showSpinner(); } }; 
+3
source

Ok, I think I found your problem: dialog.dismiss();
You are doing a really strange thing: you are creating a dialogue through activity, but say that do not quit so as not to distract him, these are two different approaches that you cannot mix. You should choose one of the methods: dialog.show and dialog.dismiss or activity.showDialog () and activity.dismissDialog () <- this is better because changing the orientation of the handles.
What you have to do is just remove the dialog from the class variables, use activity.showDialog everywhere. Probably your problem was rejecting the dialog in onClick. Just use YourActivityName.this.dismissDialog (DIALOG_NUMBER) and it should work.
More about the dialog box from the developers site - I had such problems, and I have a lot of time to find out how it works, but after all - the dialogs are not so complicated;)

+1
source

I had a similar failure. I worked around disabling orientation changes when a dialog is displayed.

 @Override public void onDismiss(DialogInterface dialog) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } @Override public void onShow(DialogInterface dialog) { int loadedOrientation = getResources().getConfiguration().orientation; int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; if (loadedOrientation == Configuration.ORIENTATION_LANDSCAPE) { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } else if (loadedOrientation == Configuration.ORIENTATION_PORTRAIT) { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; } setRequestedOrientation(requestedOrientation); } 

NOTE. I really found that there is no reliable way to lock the screen .

+1
source

Source: https://habr.com/ru/post/894075/


All Articles