我正在为Android开发一个PopUp窗口,它正在工作,我在其上添加了一个EditText和一个Button,当在ADV上运行时,这项工作正常,在设备上运行时,当我专注于EditText时,这会引发一个奇怪的异常。
android.view.WindowManager$BadTokenException: Unable to add window - - token android.view.ViewRoot&48163b18 is not valid; is your active running?
我不知道它是否重要,但我正在使用Swype输入的Galaxy Tab上运行。
现在我阅读了Window.showAtLocation的规范
public void showAtLocation (View parent, int gravity, int x, int y)
Display the content view in a popup window at the specified location. If the popup window cannot fit on screen, it will be clipped. [...]
Parameters
parent a parent view to get the getWindowToken() token from
[...]
问题就在于该令牌,但我如何将Activity令牌传递给它?
我还写了一个小代码来重现错误。
PopupWindow window = new PopupWindow(activity);
window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
window.setTouchable(true);
window.setFocusable(true);
EditText text = new EditText(activity);
text.setText("Dont touch, this crash!");
window.setContentView(text);
window.showAtLocation(arg0, Gravity.NO_GRAVITY, 10,10);
在AVD上运行一切正常,而在设备上崩溃并抛出我提到的错误。
我发现了一些新的东西,当我处于横向模式时,不会发生这种错误。
答案 0 :(得分:6)
谢谢你,TheRedPill! 我在PopupWindow内部的EditText表现出同样的问题。它适用于三星Galaxy S3,HTC One X,但在华为MediaPad FHD 10上崩溃了。一旦我开始编辑该应用程序就崩溃了。
您的解决方案:
editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
为我解决了这个问题。
堆栈跟踪是:
08-15 15:49:03.690: ERROR/AndroidRuntime(8692): FATAL EXCEPTION: main
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@417eefa8 is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:585)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:326)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
at android.view.Window$LocalWindowManager.addView(Window.java:547)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:988)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:845)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:809)
at android.widget.Editor$PinnedPopupWindow.updatePosition(Editor.java:2147)
at android.widget.Editor$PinnedPopupWindow.show(Editor.java:2104)
at android.widget.Editor$SuggestionsPopupWindow.show(Editor.java:2349)
at android.widget.Editor.showSuggestions(Editor.java:1647)
at android.widget.Editor$1.run(Editor.java:1546)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
答案 1 :(得分:4)
原因:
我将错误原因追溯到某些手机(Moto Droid Razr和其他一些Moto手机)和一些Android Rom(如某些CM7和CM7.1 ROMS)上的拼写自动纠正行为。如果文本包含拼写错误的单词,并且文本光标悬停在文本中或文本附近,则Android操作系统将尝试自动调出键盘并尝试提供正确拼写的建议。
在大多数设备上,自动更正建议框仅显示为键盘上方的一个线段。然而,在一些自定义ROM(CM7是我看起来很多的东西)和一些设备(Droid Razr)上,还有一个额外的下拉选择框出现:
请参阅此image自动更正弹出窗口的内容(抱歉没有足够的代码插入图片)
我非常怀疑自动更正下拉列表也是作为弹出窗口实现的,并且它正在尝试使用当前弹出窗口(包含带有错误拼写字的EditText的弹出窗口)作为根视图,并且试图从根视图中获取windowToken。
由于弹出窗口本身不是传统视图,我假设它无法将正确的windowToken提供给其他要求它们的视图,因此导致错误。
解决方案:
1)我能够解决这个问题的最简单方法是使用Dialog而不是Popup窗口。他们的API非常相似,在我的情况下使用Dialog很容易替换PopupWindow。
例如:
旧代码:
LayoutInflater inflater = (LayoutInflater) parentActivity.getLayoutInflater();
View mainView = parentActivity.findViewById(R.id.main_calendar_fragment);
updateEventPopupWindow = new PopupWindow(inflater.inflate(
R.layout.add_event_fragment, null, false), metrics.widthPixels, metrics.heightPixels, true);
updateEventPopupWindow.setBackgroundDrawable(new BitmapDrawable());
updateEventPopupWindow.showAtLocation(mainView, Gravity.CENTER, 0, 0);
新代码:
LayoutInflater inflater = (LayoutInflater) parentActivity.getLayoutInflater();
View mainView = parentActivity.findViewById(R.id.main_calendar_fragment);
updateEventDialog = new Dialog(parentActivity, android.R.style.Theme_NoTitleBar);
updateEventDialog.setContentView(inflater.inflate(R.layout.add_event_fragment, (ViewGroup) mainView, false));
updateEventDialog.show();
2)第二种方法更难,但如果PopupWindow到Dialog替换不可行,则可能是合适的,是用户Fragments代替PopupWindows。那里有许多好的片段tutorials,所以我不打算在这篇文章中讨论如何做到这一点。
3)作为最后的手段,就像上面提到的多个海报一样,您可以在PopupWindwow内的EditText字段上关闭文本自动更正,以解决此问题。然而,这导致了糟糕的用户体验,因为许多用户(以及像swype这样的键盘)依赖于自动更正,这样做可能会使用户远离您的应用程序。
希望这可以帮助那些面临这个问题的人。换了一天之后我把头撞到了键盘上,最后决定尝试使用Dialog方法,令我惊讶的是相当容易换掉。祝你好运
答案 2 :(得分:3)
我试图运行你的代码,但一切都适合我...这是我写的测试类:
public class TestActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.testBtn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
showPopup();
}
});
}
private void showPopup()
{
PopupWindow window = new PopupWindow(this);
window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
window.setTouchable(true);
window.setFocusable(true);
EditText text = new EditText(this);
text.setText("Touch it, it doesn't crash");
window.setContentView(text);
window.showAtLocation(text, Gravity.NO_GRAVITY, 30, 30);
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/testBtn"
android:text="Popup"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
也许你试过在onCreate()函数中运行弹出代码?如果我这样做,它会抛出与你相同的异常,但这是正常的,因为当调用onCreate()时,活动尚未完全初始化。
(我也尝试过Galaxy Tab,但没有输入swype)
答案 3 :(得分:2)
EditText text = new EditText(activity);
text.setText("Dont touch, this crash!");
这实际上是例外的原因..
当我们将EditText绑定到某些文本时,当虚拟键盘出现时,它会在单击时失效。
但是当我们不绑定EditText时,相同的代码工作正常
EditText text = new EditText(activity);
虽然我面临同样的错误,但到目前为止还无法解决....
只需将努力集中在问题创造者线上......
任何机构都能说明为什么itz会这样做以及如何解决这个问题。
Thankx
答案 4 :(得分:1)
当我的弹出窗口中的edittext已经存在一些文本并且文本不是字典单词(例如城市名称)时,我也遇到了同样的错误。当我点击文字和繁荣之间!我得到了例外。 我通过使edittext不显示自动正确的建议来解决它:
android:inputType="textNoSuggestions"
答案 5 :(得分:0)
被修改
尝试这样创建一个新类说Popupcls
public class PopUpFlag {
private PopupWindow pw;
public void initiatePopupWindow(Activity ctx) {
LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.popupprofile, (ViewGroup) ctx.findViewById(R.id.popup_element));
EditText ettext = (EditText) layout.findViewById(R.id.edit);
pw = new PopupWindow(layout, 300, 400, true);
pw.showAtLocation(layout, Gravity.BOTTOM, 0, 0);
}
现在在你的活动中如果弹出按钮需要弹出按钮点击这样写
popupbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
PopUpFlag puf=new PopUpFlag();
puf.initiatePopupWindow(YourActivityName.this);
}
});
我希望这会有所帮助
答案 6 :(得分:0)
当用户点击带下划线的单词为红色时,崩溃发生在放置在WindowManager中的EditText上。这样一个带下划线的单词意味着它不存在于字典中。在点击时,操作系统会尝试显示一个弹出,其中包含来自字典的最接近的匹配单词并且崩溃,因为由于不良的标记异常,这样的弹出窗口无法附加到窗口。
以下解决方案似乎只能以编程方式为我工作
//assume an EditText object with name myEditText
myEditText.setInputType(myEditText.getInputType() | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
在所有键盘上,InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS似乎没有按预期工作,而InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD的缺点是它还会禁用切换键盘中的语言和滑动手势以添加文本。