Исключение при фокусировке EditText в PopupWindow на устройстве - PullRequest
17 голосов
/ 28 января 2011

Я разрабатываю всплывающее окно для Android, и оно работает, я добавил EditText и Button для этого, при работе в ADV это работает правильно, при запуске на устройстве, когда я фокусируюсь на EditText, это бросает странный Исключение.

android.view.WindowManager$BadTokenException: Unable to add window - - token android.view.ViewRoot&48163b18 is not valid; is your active running?

Я не знаю, имеет ли это значение, но я работаю на Galaxy Tab с вводом Swype.

Теперь я читаю спецификации 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
[...]

Проблема только в том токене, но как мне передать ему токен активности?

Я также написал небольшой код для воспроизведения ошибки.

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 ]

6 голосов
/ 15 августа 2013

Спасибо, TheRedPill!У меня была та же проблема с EditText внутри PopupWindow, который ведет себя странно.Он работал на Samsung Galaxy S3, HTC One X, но зависал на Huawei MediaPad FHD 10. Как только я начал редактировать, приложение рухнуло.я.

Трассировка стека была:

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)
4 голосов
/ 07 мая 2014

Причина:

Я прослеживаю причину ошибки вплоть до автокоррекции правописания на некоторых телефонах (Moto Droid Razr и нескольких других Moto Phones) и некоторых Android Rom (например, CM7 и CM7.1 ROMS). Если в тексте содержится слово, написанное неправильно, и текстовый курсор находится в тексте или рядом с ним, ОС Android попытается автоматически вызвать клавиатуру и попытаться предложить правильное написание.

На большинстве устройств окно автокоррекции отображается только в виде одного отрезка над клавиатурой. Однако на некоторых пользовательских ПЗУ (с CM7, который, как мне кажется, часто случается) и на некоторых устройствах (Droid Razr) есть дополнительное раскрывающееся поле выбора:

Посмотрите на это изображение того, как выглядит автокоррекция всплывающего окна (извините, недостаточно репов для вставки изображения)

Я очень подозреваю, что выпадающий список автокоррекции также реализован в виде всплывающего окна, и он пытается использовать текущее всплывающее окно (то, которое содержит EditText со словом неправильного написания) в качестве корневого представления, и пытаясь получить windowToken из корневого представления.

Так как само всплывающее окно не является традиционным представлением, я предполагаю, что оно не может дать правильное окно, взятое другим представлениям, которые их запрашивают, что приводит к ошибке.

Решения:

1) Самый простой способ обойти эту проблему - использовать диалог вместо всплывающих окон. Их API действительно похожи, и в моих случаях довольно просто заменить PopupWindow с помощью Dialog.

Например:

Старый код:

    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 невозможна, это использование пользовательских фрагментов вместо PopupWindows. Есть много хороших фрагментов учебников , поэтому я не стану рассказывать, как это сделать, в этом посте.

3) В качестве последнего средства, как и несколько упомянутых выше плакатов, вы можете отключить автокоррекцию текста в полях EditText внутри PopupWindwow, чтобы обойти эту проблему. Однако это приводит к ужасному взаимодействию с пользователем, так как многие пользователи (и клавиатуры, такие как swype) полагаются на автокоррекцию, что, вероятно, приведет к удалению пользователя из вашего приложения.

Надеюсь, это поможет другим, кто сталкивается с этой проблемой. Я бился головой о клавиатуру более суток, прежде чем, наконец, решил попробовать подход «Диалог», который, к моему удивлению, было довольно легко заменить. Удачи тебе

3 голосов
/ 04 февраля 2011

Я пытался запустить ваш код, но у меня все работает нормально ... Вот тестовый класс, который я написал:

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)

2 голосов
/ 09 мая 2012
EditText text = new EditText(activity);
text.setText("Dont touch, this crash!");

это на самом деле является причиной исключения ..

когда мы привязываем EditText к некоторому тексту, он выпадает при щелчке при появлении виртуальной клавиатуры

Но тот же код отлично работает, когда мы не привязываем EditText

EditText text = new EditText(activity);

Хотя я сталкиваюсь с той же ошибкой и не могу разобраться до сих пор ....

Просто приложите усилия, чтобы сосредоточиться на линии создателя проблем ...

Может ли какой-либо орган подсказать, почему он ведет себя так и как решить эту проблему ...

Спасибо

1 голос
/ 04 марта 2013

Я также получил ту же ошибку, когда текст редактирования в моем всплывающем окне уже содержал некоторый текст, а текст не был словарным словом (например, название города). Когда я нажимаю между текстом и бум! Я получил исключение. Я решил это, заставив текст редактирования не показывать автоматически правильные предложения:

android:inputType="textNoSuggestions"
0 голосов
/ 10 ноября 2016

Сбой происходит при редактировании текста, помещенного в WindowManager, когда пользователь нажимает на слово, подчеркнутое красным цветом. Такое подчеркнутое слово означает, что оно не существует в словаре. При нажатии операционная система пытается отобразить всплывающее окно с самыми близкими совпадающими словами из словаря и вылетает, поскольку такое всплывающее окно не может быть прикреплено к окну из-за исключения неверного токена.

Мне показалось, что только следующее решение работает для меня программно

//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 имеет недостаток, заключающийся в том, что он также отключает переключение языка на клавиатуре и жест свайпинга для добавления текста.

0 голосов
/ 30 апреля 2011

1001 * Отредактировано *

попробуй вот так создай новый класс скажем 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);
            }
        });

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...