我创建了一个自定义AlertDialog来显示Spinner和一些EditText元素。当我选择菜单选项时,会启动此自定义AlertDialog。一切正常,直到我实际选择微调器来尝试选择一个项目,此时我得到了BadTokenException。我已经读过其他StackOverflow帖子,说类似的异常是尝试使用getApplicationContext()而不是传递Activity.this来显示diaglog的结果。我没有明确地将getApplicationContext()传递给与此AlertDialog相关的任何内容。
要设置此自定义AlertDiaglog,我创建了一个包含Spinner和EditText元素的布局文件,然后使AlertDialog使用该布局:
LayoutInflater inflater = (LayoutInflater)getApplication().getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_layout, (ViewGroup)findViewById(R.id.custom_layout_root));
spinner = (Spinner)layout.findViewById(R.id.custom_layout_spinner);
ArrayAdapter adap = ArrayAdapter.createFromResource(Activity.this, R.array.data, android.R.layout.simple_spinner_item);
adap.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adap);
spinner.setOnItemSelectedListener(new SpinnerItemListener());
AlertDialog.Builder dialog = new AlertDialog.Builder(Activity.this);
dialog.setTitle("Title");
dialog.setPositiveButton("Ok", new Dialog.OnClickListener() ...
...
dialog.show();
此代码均可正常显示AlertDialog。但是,当我真正触摸Spinner时,我遇到了以下问题:
Thread [<3> main] (Suspended (exception WindowManager$BadTokenException))
ViewRoot.handleMessage(Message) line: 1704
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 123
ActivityThread.main(String[]) line: 4203
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 791
ZygoteInit.main(String[]) line: 549
NativeStart.main(String[]) line: not available [native method]
有没有人知道发生了什么?异常消息说:
Unable to add window -- token null is not for an application
我相信这是其他人已经看到的这类问题的消息,所以我假设ApplicationContext在某个地方混合,但我不知道在哪里。我的清单设置为minSdk为1.5,目标SDK为1.6。
答案 0 :(得分:8)
我已经读过其他StackOverflow帖子说类似的异常是尝试使用getApplicationContext()显示diaglog而不是传递Activity.this的结果。
我没有明确地将getApplicationContext()传递给与此AlertDialog相关的任何内容。
大概这段代码实际上 就是这么做 - 你要求 Application
使用其上下文来访问服务,而不是目前 Window
:
LayoutInflater inflater =
(LayoutInflater) getApplication().getSystemService(LAYOUT_INFLATER_SERVICE);
您是否只能将其替换为以下版本,因为您从AlertDialog
启动了Activity
?
LayoutInflater inflater =
(LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
甚至更简单:
LayoutInflater inflater = getLayoutInflater();
答案 1 :(得分:2)
我在这个奇怪的问题上失去了很多时间,但最后我解决了如下问题。看看这段代码:
/**
* Initializes the body of the screen that serves a user to edit a new question.
*/
private void onStart_initializeNewQuestion()
{
/**
* 0. Local variables.
*/
Spinner spinner, spinner2;
ArrayAdapter<CharSequence> arrayAdapter;
EditText editText;
/**
* 1. Inflate the layout, and configure useful pointers.
*/
this.viewGroup_body_newquestion= (ViewGroup) this.layoutInflater.inflate(R.layout.create_survey_newquestion, null);
/**
* 2. Populate the spinner with user choices, and then set responding spinner to user selections
*/
spinner= (Spinner) this.viewGroup_body_newquestion.findViewById(R.id.create_survey_newquestion_spinner_questionType);
// Create an ArrayAdapter using the string array and a default spinner layout
arrayAdapter= ArrayAdapter.createFromResource(this, R.array.create_surveys_newquestion_spinnerOptions,
android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(arrayAdapter);
// spinner.setOnItemSelectedListener(this);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
{
String choice;
choice= parent.getItemAtPosition(pos).toString();
U.e(U.VERBOSE, "CreateSurveyActivity.onStart_initializeNewQuestion(listener@spinner_questionType): " + choice);
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
spinner2= new Spinner(this);
spinner2.setAdapter(arrayAdapter);
spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
{
String choice;
choice= parent.getItemAtPosition(pos).toString();
U.e(U.VERBOSE, "CreateSurveyActivity.onStart_initializeNewQuestion(listener@spinner_questionType): " + choice);
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
LinearLayout linearLayout= (LinearLayout) this.viewGroup_body_newquestion.getChildAt(0);
linearLayout.addView(spinner2);
}
Look spinner vs spinner2:spinner存在于一个膨胀的布局中(其根是一个ScrollView),spinner2是以编程方式创建的,这是一个Activity对象。
由于我无法更改spinner1上下文以与此上下文一致,最后我直接在此上下文中创建了一个新的Spinner。因此,当spinner2工作时,微调器不起作用。
PS:使用的布局inflater用于夸大许多其他布局:
this.layoutInflater= (LayoutInflater) this.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
PS2:Christopher提供的解决方案允许继续使用原始微调器,因此它是更好的解决方案! :)强>