PopupWindow $ BadTokenException:无法添加窗口-令牌null无效


80

显示PopupWindow时出现以下错误。错误是由以下行触发的:

checkInPopup.showAtLocation((ViewGroup) mapView.getParent(), Gravity.CENTER_HORIZONTAL, 0, 0);

mapView是一个MapView,没有任何内容为null。堆栈跟踪:

01-08 18:00:09.402: E/AndroidRuntime(27768): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.ViewRootImpl.setView(ViewRootImpl.java:513)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:301)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.view.Window$LocalWindowManager.addView(Window.java:537)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.widget.PopupWindow.invokePopup(PopupWindow.java:988)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.widget.PopupWindow.showAtLocation(PopupWindow.java:845)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.widget.PopupWindow.showAtLocation(PopupWindow.java:809)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at com.geoloc.ActivityCheckIn.onCreate(ActivityCheckIn.java:50)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.app.Activity.performCreate(Activity.java:4465)
01-08 18:00:09.402: E/AndroidRuntime(27768):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)

这是我的活动中的代码(扩展了MapActivity)

    protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.checkin);
    mapView = (MapView) findViewById(R.id.mapview);

    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    checkInPopup = new PopupWindow(inflater.inflate(CHECK_IN_POPUP_LAYOUT, null, false));
    checkInPopup.setOutsideTouchable(true);
    checkInPopup.setHeight(100);
    checkInPopup.setWidth(200);
    checkInPopup.showAtLocation((ViewGroup) mapView.getParent(), Gravity.CENTER_HORIZONTAL, 0, 0);
}

感谢您分享您的想法

Answers:


71

您显示弹出窗口为时过早。您可以在Onresume中发布showatlocation的延迟运行项,尝试一下

编辑: 这篇文章似乎有相同的问题,回答了在Android活动中创建弹出窗口的问题


我建议捕获异常,并以相当大的延迟(至少几次)继续重新发布,因为最初的延迟是无法预期的。
严苛

92

当我尝试在活动中显示弹出菜单时,我也遇到了同样的问题,但我也遇到了同样的问题,但是我遇到了问题n通过提供上下文来解决

YourActivityName.this 而不是getApplicationContext()

Dialog dialog = new Dialog(getApplicationContext());

是的,它为我工作可能会帮助别人


这对我很有帮助。一个好的答案thanx
Tharusha '18


10

在两种情况下可能会发生此异常。nandeesh提到了一个。这里提到了其他场景:http : //blackriver.to/2012/08/android-annoying-exception-unable-to-add-window-is-your-activity-running/

确保您都处理


7
请注意,不鼓励仅链接的答案,随着时间的流逝,引用往往会过时。请考虑在此处添加独立的摘要,并保留该链接作为参考。
kleopatra 2013年

@TheMan Nice〜如此小巧而强大的提示!谢谢!
cmcromance

5
  @Override
protected void onCreate(Bundle savedInstanceState) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.popup_window_layout, new LinearLayout(mContext), true);
    popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    popupWindow.setContentView(view);
}

   @Override
public void onWindowFocusChanged(boolean hasFocus) {
    if (hasFocus) {
        popupWindow.showAtLocation(parentView, Gravity.BOTTOM, 0, 0);
    }
}

正确的方法是onWindowFocusChanged()的popupwindow.show()。


这解决了原始问题,是最好/最干净的解决方案。
Dale

3

弹出窗口的父项本身不能成为弹出窗口。他们的父母必须相同。因此,如果在弹出窗口内创建弹出窗口,则必须保存父窗口的弹出窗口并使其成为父窗口。

这是一个例子


1

尝试显示如下所示的流行音乐

findViewById(R.id.main_layout).post(new Runnable() {
        public void run() {
            mPopupWindow.showAtLocation(findViewById(R.id.main_layout), Gravity.CENTER, 0, 0);
            Button close = (Button) customView.findViewById(R.id.btn_ok);
            close.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mPopupWindow.dismiss();
                    doOtherStuff();
                }
            });
        }
    });

1

演出前使用此方法

public static ViewGroup getActivityFirstLayout(Context ctx)
{
    return (ViewGroup)((ViewGroup) ActivityMaster.getActivity(ctx).findViewById(android.R.id.content)).getChildAt(0);
}

private boolean activityIsOk(Activity activity)
{
    boolean s1 = !(activity == null || activity.isFinishing());

    if(s1)
    {
        View v = LayoutMaster.getActivityFirstLayout(activity);
        return v.isShown() && ViewCompat.isLaidOut(v);
    }

    return false;
}

0

尝试使用它

LayoutInflater inflater = (LayoutInflater).getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View view = inflate.from(YourActivity.this).inflate(R.layout.yourLayout, null);

您是否还可以张贴完整的代码,以确保他要替换正确的东西。谢谢。
kwoxer

0

经过数小时的搜索和测试,我发现以下解决方案(通过实施不同的SO解决方案)在任何情况下都没有失败,甚至崩溃了。

     Runnable runnable = new Runnable() {
            @Override
            public void run() {

          //displayPopup,progress dialog or what ever action. example

                ProgressDialogBox.setProgressBar(Constants.LOADING,youractivityName.this);
            }};

logcat指示崩溃正在发生的地方。在我的情况下,在接收广播时开始运行。

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(!isFinishing()) {
                    new Handler().postAtTime(runnable,2000);
                }
            }
        });

-1

尝试显示这样的弹出窗口

new Handler().postDelayed(new Runnable(){

    public void run() {
       popupWindow.showAtLocation(context.getWindow().getDecorView(), Gravity.CENTER,0,0);
    }

}, 200L);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.