Mar*_*los 17 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?
Run Code Online (Sandbox Code Playgroud)
我不知道它是否重要,但我正在运行带有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
[...]
Run Code Online (Sandbox Code Playgroud)
问题只在于该令牌,但我如何将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);
Run Code Online (Sandbox Code Playgroud)
在AVD上运行一切正常,而在设备上崩溃并抛出我提到的错误.
我发现了一些新东西,当我处于横向模式时,不会发生这种错误.
谢谢你,TheRedPill!我在PopupWindow内部的EditText表现出同样的问题.它适用于三星Galaxy S3,HTC One X但在华为MediaPad FHD 10上崩溃了.一旦我开始编辑该应用程序就崩溃了.
你的解决方案
editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
Run Code Online (Sandbox Code Playgroud)
为我解决了这个问题.
堆栈跟踪是:
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)
Run Code Online (Sandbox Code Playgroud)
原因:
我将错误的原因追溯到某些手机(Moto Droid Razr 和少数其他 Moto 手机)和一些 android Rom(如某些 CM7 和 CM7.1 ROM)上的拼写自动更正行为。如果文本包含拼写错误的单词,并且文本光标悬停在文本中或文本附近,Android 操作系统将尝试自动调出键盘并尝试提供有关正确拼写的建议。
在大多数设备上,自动更正建议框仅显示为键盘上方的一条线段。但是,在某些自定义 ROM(CM7 是我似乎经常遇到的一种)和某些设备(Droid Razr)上,会出现一个额外的下拉选择框:
看到这个图片什么的自动更正弹出的样子(抱歉没有足够的代表,以插入图片)
我非常怀疑自动更正下拉列表也是作为弹出窗口实现的,它试图使用当前弹出窗口(包含带有拼写错误的 EditText 的那个)作为根视图,并试图获取根视图中的 windowToken。
由于弹出窗口本身不是传统视图,我假设它无法将正确的 windowToken 提供给其他请求它们的视图,因此导致错误。
解决方案:
1) 我能够解决这个问题的最简单方法是使用对话框而不是弹出窗口。他们的 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);
Run Code Online (Sandbox Code Playgroud)
新代码:
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();
Run Code Online (Sandbox Code Playgroud)
2)第二种方法更难,但如果 PopupWindow 到 Dialog 替换不可行,则可能是合适的,是用户 Fragments 代替 PopupWindows。那里有很多很好的片段教程,所以我不会在这篇文章中费心去讨论如何做到这一点。
3) 作为最后的手段,就像上面提到的多张海报一样,您可以在 PopupWindwow 内的 EditText 字段上关闭文本自动更正以避开这个问题。然而,这会导致糟糕的用户体验,因为许多用户(以及 swype 等键盘)依赖于自动更正,这样做可能会使用户远离您的应用程序。
希望这可以帮助其他面临此问题的人。我把头撞在键盘上超过一天,最后决定尝试 Dialog 方法,令我惊讶的是,它很容易换掉。祝你好运
我尝试运行您的代码,但一切对我来说都运行良好...这是我编写的测试类:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
主要.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>
Run Code Online (Sandbox Code Playgroud)
也许您尝试在 onCreate() 函数中运行弹出代码?如果我这样做,它会抛出与您相同的异常,但这是正常的,因为调用 onCreate() 时活动尚未完全初始化。
(我也尝试过 Galaxy Tab,但没有 swype 输入)
| 归档时间: |
|
| 查看次数: |
6006 次 |
| 最近记录: |