PopupWindow $ BadTokenException: Không thể thêm cửa sổ - mã thông báo null không hợp lệ


80

Tôi gặp lỗi sau khi hiển thị PopupWindow. Các lỗi được kích hoạt bởi dòng:

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

mapView là một MapView và không có gì là null. Hệ thống ngăn xếp:

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)

Đây là mã từ hoạt động của tôi (mở rộng 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);
}

Cảm ơn bạn đã chia sẻ suy nghĩ của bạn

Câu trả lời:


71

bạn đang hiển thị cửa sổ bật lên của mình quá sớm. Bạn có thể đăng một bài có thể chạy bị trì hoãn để hiển thị trong Onresume, Hãy thử

Chỉnh sửa: Bài đăng này dường như có cùng một vấn đề được giải đáp Sự cố khi tạo Cửa sổ bật lên trong Hoạt động của Android


Tôi khuyên bạn nên bắt ngoại lệ và tiếp tục đăng lại với độ trễ đáng kể (ít nhất là vài lần), vì không thể lường trước được độ trễ ban đầu.
Khắc nghiệt

93

Vấn đề tương tự đã xảy ra với tôi khi tôi cố gắng hiển thị menu bật lên trong hoạt động, tôi cũng gặp phải lỗi tương tự nhưng tôi gặp phải vấn đề n giải quyết bằng cách cung cấp ngữ cảnh

YourActivityName.this thay vì getApplicationContext()

Dialog dialog = new Dialog(getApplicationContext());

và vâng nó có hiệu quả với tôi có thể nó sẽ giúp ích cho người khác


Điều này đã giúp tôi tốt. Câu trả lời hay thanx
Tharusha

34

Sử dụng:

YourActivityName.this

Thay vì:

getApplicationContext();

1
Có, điều này hoạt động cho một: ProgressDialog mới (YourActivityName.this);
Lotfi

10

Có hai trường hợp khi ngoại lệ này có thể xảy ra. Một được đề cập bởi nandeesh. Kịch bản khác được đề cập ở đây: http://blackriver.to/2012/08/android-annoying-exception-unable-to-add-window-is-your-activity-running/

Đảm bảo rằng bạn xử lý cả hai


7
Lưu ý rằng các câu trả lời chỉ có liên kết không được khuyến khích, các tài liệu tham khảo có xu hướng cũ dần theo thời gian. Vui lòng xem xét thêm một bản tóm tắt độc lập ở đây, giữ liên kết làm tài liệu tham khảo.
kleopatra

@TheMan Nice ~ một mẹo nhỏ rất hữu ích! Cảm ơn bạn!
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);
    }
}

cách chính xác là popupwindow.show () tại onWindowFocusChanged ().


Điều này giải quyết vấn đề của câu hỏi ban đầu và là giải pháp tốt nhất / sạch nhất.
Dale

3

Bản thân cửa sổ bật lên không thể là một cửa sổ bật lên. Cha mẹ của cả hai đều phải giống nhau. Vì vậy, nếu bạn tạo một cửa sổ bật lên bên trong một cửa sổ bật lên, bạn phải lưu cửa sổ bật lên của phụ huynh và đặt nó thành cửa sổ phụ.

đây là một ví dụ


1

Cố gắng hiển thị cửa sổ bật lên như bên dưới

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

sử dụng phương pháp này trước khi hiển thị

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

Cố gắng sử dụng nó

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

Bạn cũng có thể đăng mã hoàn chỉnh để đảm bảo rằng anh ấy đang thay thế đúng thứ. Cảm ơn bạn.
kwoxer

0

Sau nhiều giờ tìm kiếm và thử nghiệm, tôi đã tìm thấy giải pháp sau (bằng cách triển khai các giải pháp SO khác nhau) ở đây nó không thành công trong bất kỳ trường hợp nào tôi gặp sự cố.

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

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

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

Trường hợp logcat cho biết sự cố đang xảy ra .. bắt đầu chạy. Trong trường hợp của tôi lúc nhận phát sóng.

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

-1

cố gắng hiển thị cửa sổ bật lên như thế này

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

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

}, 200L);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.