Подтвердить что ты не робот

Исключение при фокусировке EditText в PopupWindow, запущенном на устройстве

Я разрабатываю окно PopUp для Android, и он работает, я добавил EditText и кнопку на том, что при работе в 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
[...]

Проблема только в этом токене, но как я могу передать токен 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 все работает нормально, а на устройстве этот сбой и выбросить ошибку, о которой я упоминал.

Я обнаруживаю что-то новое, когда я в ландшафтном режиме, таких ошибок не возникает.

4b9b3361

Ответ 1

Спасибо, TheRedPill! У меня была такая же проблема с EditText внутри PopupWindow, ведущей себя грубо. Он работал на Samsung Galaxy S3, HTC One X, но разбился на Huawei 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 [email protected] 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)

Ответ 2

Причина:

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

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

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

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

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

Решения:

1) Самый простой способ решить эту проблему - использовать Dialog вместо всплывающих окон. Их 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. Существует много хороших фрагментов tutorials, поэтому я не буду обсуждать, как это сделать в этом сообщении.

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

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

Ответ 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, но без ввода swype)

Ответ 4

EditText text = new EditText(activity);
text.setText("Dont touch, this crash!");

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

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

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

EditText text = new EditText(activity);

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

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

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

Thankx

Ответ 5

Edited

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

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

android:inputType="textNoSuggestions"

Ответ 7

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

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

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