问题描述
在我的应用程序我有一个自定义AlertDialog(使用的ShowDialog由系统处理()),其中包含有2个选项卡的tabhost。在选项卡中的一个是一个微调。只要我能转动我的屏幕没有问题的微调是不开放(显示微调对话框)。如果在旋转过程中的微调是开放的,我得到这样的:
In my app I have a custom AlertDialog (handled by the system using showDialog()) which contains a tabhost with 2 tabs. In one of the tabs is a spinner. I can rotate my screen without problems as long as the spinner isn't open (spinner dialog displayed). If the spinner is open during rotation, I get this:
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 - 是否可以在的onPause()
1 - Is it possible to programmatically close the spinner during onPause()
?
2 - 有没有我应该使用不同的方法
2 - Is there a different method I should be using?
3 - 如果没有妥善的解决办法,我怎么抓住这个特殊的例外? (不好的做法,我知道,但轰然需要停止,并且因为活性被破坏后重建本身正确,就不会反正无所谓。
3 - If there isn't a proper solution, how do I catch this particular Exception? (Bad practice I know, but the crashing needs to be stopped, and since the activity reconstructs itself properly after being destroyed, it wouldn't matter anyway.
......也请为所有的爱情是神圣的,不建议我加入安卓configChanges =定向
来我的活动宣言。我非常惊讶多久被接受为正式的修复,所有方向的问题。
... And please for the love of all that is holy, do not suggest that I add android:configChanges="orientation"
to my activity declaration. It amazes me how often that is accepted as the official fix-all for orientation issues.
修改,了解更多信息
下面是我的对话创造code,以供参考:
Here is my dialog creation code for reference:
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;
}
修改与临时解决方法
有关任何人感兴趣,我设法通过继承微调和覆盖 onDetachedFromWindow()
像这样至少停止崩溃:
For anybody interested I managed to at least stop the crashing by subclassing spinner and overriding onDetachedFromWindow()
like so:
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
}
}
}
就像我说的,一个解决办法。还是努力寻找解决方案。 :/
Like I said, a workaround. Still working on a solution. :/
推荐答案
我找到了一个更好的解决方案。这其实并不是那么难的一个按钮的外观和行为类似微调(除了崩溃,幸好)代替微调。
I found a better solution. It is actually not so hard to replace Spinner with a button that looks and behaves like Spinner (except the crash, 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();
}
};
这篇关于什么是正确的方式来处理方向变化时,自定义alertdialog有一个开放的微调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!