Problems creating a Popup Window in Android Activity

老子叫甜甜 提交于 2019-11-26 19:36:58

To avoid BadTokenException, you need to defer showing the popup until after all the lifecycle methods are called (-> activity window is displayed):

 findViewById(R.id.main_page_layout).post(new Runnable() {
   public void run() {
     pw.showAtLocation(findViewById(R.id.main_page_layout), Gravity.CENTER, 0, 0);
   }
});

Solution provided by Kordzik will not work if you launch 2 activities consecutively:

startActivity(ActivityWithPopup.class);
startActivity(ActivityThatShouldBeAboveTheActivivtyWithPopup.class);

If you add popup that way in a case like this, you will get the same crash because ActivityWithPopup won't be attached to Window in this case.

More universal solusion is onAttachedToWindow and onDetachedFromWindow.

And also there is no need for postDelayed(Runnable, 100). Because this 100 millis does not guaranties anything

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    Log.d(TAG, "onAttachedToWindow");

    showPopup();
}

@Override
public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    Log.d(TAG, "onDetachedFromWindow");

    popup.dismiss();
}
Todd Painton

The accepted answer did not work for me. I still received BadTokenException. So I just called the Runnable from a Handler with delay as such:

new Handler().postDelayed(new Runnable() {
    public void run() {
        showPopup();
    }
}, 100);

use class Context eg. MainActivity.this instead of getApplicationContext()

There are two scenarios when this exception could occur. One is mentioned by kordzik. Other scenario is mentioned here: http://blackriver.to/2012/08/android-annoying-exception-unable-to-add-window-is-your-activity-running/

Make sure you handle both of them

saber

the solution is to set the spinner mode to dialog as below:

android:spinnerMode="dialog"

or

Spinner(Context context, int mode)
tnxs RamallahDroid

See This.

Depending on the use case, for types of pop-up to display a message, setting the pop-up type to TYPE_TOAST using setWindowLayoutType() avoids the issue, as this type of pop-up is not dependent on the underlying activity.

Edit: One of the side effects: no interaction in the popup window for API <= 18, as the touchable / focusable events would be removed by the system. ( http://www.jianshu.com/p/634cd056b90c )

I end up with using TYPE_PHONE (as the app happens to have the permission SYSTEM_ALERT_WINDOW, otherwise this won't work too).

You can check the rootview if it has the token. You can get the parent layout defined from your activity xml, mRootView

if (mRootView != null && mRootView.getWindowToken() != null) {
    popupWindow.showAtLocation();
}

Check that findViewById returns something - you might be calling it too early, before the layout is built

Also you may want to post logcat output for the exceptions you're getting

You can also try to use this check:

  public void showPopupProgress (){
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            if (getWindow().getDecorView().getWindowVisibility() == View.GONE) {
                showPopupProgress();
                return;
            }
            popup.showAtLocation(.....);
        }
    });
}

If you show a PopupWindow in another PopupWindow, do not use the view in first POP, use the origin parent view.

pop.showAtLocation(parentView, ... );

I had the same problem (BadTokenException) with AlertDialog on dialog.show(). I was making an AlertDialog by following some example. In my case the reason of that problem was a string dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST)

Everything became working after I removed it.

You can specify the y-offset to account for the status bar from the pw.showAtLocation method...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!