将EditText聚焦在Device上运行的PopupWindow时出现异常

时间:2011-01-28 15:09:52

标签: java android android-edittext

我正在为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上运行一切正常,而在设备上崩溃并抛出我提到的错误。

我发现了一些新的东西,当我处于横向模式时,不会发生这种错误。

7 个答案:

答案 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的缺点是它还会禁用切换键盘中的语言和滑动手势以添加文本。