PopupWindow嵌套PopupWindow时报Unable to add window的处理

今天在帮同学实现一个PopupWindow嵌套PopupWindow时报了异常,导致第二个POP不能显示:

android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running?

先贴代码:

volleytest_lay.xml,pop_first_lay.xml,pop_second_lay:


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ffffff"

android:orientation="vertical" >

<Button

android:id="@+id/popBtn"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="弹出POP菜单" />

</LinearLayout>

PopupWindowActivity.java :


public class PopupWindowActivity extends Activity {

private Button popBtn = null, mButton;

private Context mContext;

private PopupWindow mSecondPOPWindow, mFirstPOPWindow = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.volleytest_lay);

mContext = this;

popBtn = (Button) findViewById(R.id.popBtn);

initPopFirst();

initListener();

}

private void initListener() {

// TODO Auto-generated method stub

popBtn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

if (mFirstPOPWindow.isShowing()) {

// 隐藏窗口,如果设置了点击窗口外小时即不需要此方式隐藏

mFirstPOPWindow.dismiss();

} else {

// 显示窗口

mFirstPOPWindow.showAsDropDown(v);

}

}

});

}

/**

* 初始化第一个POP

*/

private void initPopFirst() {

View firstView = getLayoutInflater().inflate(R.layout.pop_first_lay,

null);

mFirstPOPWindow = new PopupWindow(firstView, LayoutParams.MATCH_PARENT,

LayoutParams.MATCH_PARENT, true);

mFirstPOPWindow.setTouchable(true);

mFirstPOPWindow.setOutsideTouchable(true);

mFirstPOPWindow.setFocusable(true);

mFirstPOPWindow.setBackgroundDrawable(new BitmapDrawable());

initPopSecond();

Button btn = (Button) firstView.findViewById(R.id.popFirstBtn);

btn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

try {

if (mSecondPOPWindow.isShowing()) {

// 隐藏窗口,如果设置了点击窗口外小时即不需要此方式隐藏

mSecondPOPWindow.dismiss();

} else {

// 显示窗口

mSecondPOPWindow.showAsDropDown(v, 500, 500);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

/*//测试AlertDialog

new AlertDialog.Builder(mContext)

.setTitle("确认")

.setMessage("确定吗?")

.setPositiveButton("是", null)

.setNegativeButton("否", null)

.show();*/

}

});

}

/**

* 初始化第二个POP

*/

private void initPopSecond() {

View popSecView = PopupWindowActivity.this.getLayoutInflater().inflate(

R.layout.pop_second_lay, null);

mSecondPOPWindow = new PopupWindow(popSecView,

LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true);

mSecondPOPWindow.setTouchable(true);

mSecondPOPWindow.setOutsideTouchable(true);

mSecondPOPWindow.setFocusable(true);

mSecondPOPWindow.setBackgroundDrawable(new BitmapDrawable());

Button popSecondBtn = (Button) popSecView

.findViewById(R.id.popSecondBtn);

popSecondBtn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

Toast.makeText(PopupWindowActivity.this, "第二个POP", 100).show();

}

});

}

}

此时是报异常的,经过不断的排查和网上搜查,问题依然没有解决。比如这里http://stackoverflow.com/questions/8782250/popupwindow-badtokenexception-unable-to-add-window-token-null-is-not-valid 只是提出讨论并么有实际解决出来。

异常的原因是因为第一个PopupWindow已经显示后,他就控制了整个Window的焦点,此时第一个POP则成为了父Window,而PopupWindow是不能以子window的形式展现的,他们必须都要以父Window显示,所以第二个POP无法添加上去。

修改后:


public class PopupWindowActivity extends Activity {

private Button popBtn = null, mButton;

private Context mContext;

private PopupWindow mSecondPOPWindow, mFirstPOPWindow = null;

private View parientView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.volleytest_lay);

mContext = this;

popBtn = (Button) findViewById(R.id.popBtn);

initPopFirst();

initListener();

}

private void initListener() {

// TODO Auto-generated method stub

popBtn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

if (mFirstPOPWindow.isShowing()) {

// 隐藏窗口,如果设置了点击窗口外小时即不需要此方式隐藏

mFirstPOPWindow.dismiss();

} else {

// 显示窗口

mFirstPOPWindow.showAsDropDown(v);

}

// 给第二个POP显示时用,解决了嵌套时出现的Unable to add window的问题

parientView = v;

}

});

}

/**

* 初始化第一个POP

*/

private void initPopFirst() {

View firstView = getLayoutInflater().inflate(R.layout.pop_first_lay,

null);

mFirstPOPWindow = new PopupWindow(firstView, LayoutParams.MATCH_PARENT,

LayoutParams.MATCH_PARENT, true);

mFirstPOPWindow.setTouchable(true);

mFirstPOPWindow.setOutsideTouchable(true);

mFirstPOPWindow.setFocusable(true);

mFirstPOPWindow.setBackgroundDrawable(new BitmapDrawable());

initPopSecond();

Button btn = (Button) firstView.findViewById(R.id.popFirstBtn);

btn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

try {

if (mSecondPOPWindow.isShowing()) {

// 隐藏窗口,如果设置了点击窗口外小时即不需要此方式隐藏

mSecondPOPWindow.dismiss();

} else {

// 显示窗口

mSecondPOPWindow.showAsDropDown(parientView, 500, 500);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

/*//测试AlertDialog

new AlertDialog.Builder(mContext)

.setTitle("确认")

.setMessage("确定吗?")

.setPositiveButton("是", null)

.setNegativeButton("否", null)

.show();*/

}

});

}

/**

* 初始化第二个POP

*/

private void initPopSecond() {

View popSecView = PopupWindowActivity.this.getLayoutInflater().inflate(

R.layout.pop_second_lay, null);

mSecondPOPWindow = new PopupWindow(popSecView,

LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true);

mSecondPOPWindow.setTouchable(true);

mSecondPOPWindow.setOutsideTouchable(true);

mSecondPOPWindow.setFocusable(true);

mSecondPOPWindow.setBackgroundDrawable(new BitmapDrawable());

Button popSecondBtn = (Button) popSecView

.findViewById(R.id.popSecondBtn);

popSecondBtn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

Toast.makeText(PopupWindowActivity.this, "第二个POP", 100).show();

}

});

}

}

解决方式请看红色标出的部分,而且解决的方式相当简单(此方案得益于一个同学),有时候我们把问题想得太复杂了,反而会使我们陷入一定的僵局,换一种思路去看待问题,必然会柳暗花明。

其实这个问题可以换一种方式解决,那就是第二个POP用AlertDialog显示也是可以,看代码中我注释点的几句就会明白,只是你非要用POP时就用我提供的这个就可以了,当然还有可能有更多的解决方案,如果有其他解决方案时,请分享一起学习,写此博文,只是希望对目前还没解决的人提供一点帮助。

源码下载

时间: 2024-10-13 17:26:20

PopupWindow嵌套PopupWindow时报Unable to add window的处理的相关文章

bug_android.view.WindowManager$BadTokenException: Unable to add window -- token

========5 java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:653) at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:349) at android.view.Wi

bug_ _ android.view.WindowManager$BadTokenException: Unable to add window -- token

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:546)at android.view.WindowManagerImpl.addView(WindowManagerImp

Unable to add window -- token [email&#160;protected] is not valid错误分析记录

打开APP时,出现闪退的情况,查看android studio报错信息,主要为: Unable to add window -- token [email protected] is not valid 原因分析:由于进入APP时会显示一个进度对话框,对话框的初始化必须依赖Activity,但如果对话框的初始化放在Activity的onCreate方法中,那么就会报错. 因为根据Activity的生命周期,onCreate方法执行时,Activity并未创建完毕,对话框所依赖的Activity还

WindowManager$BadTokenException: Unable to add window permission denied for this window type

10-11 11:47:27.472: E/AndroidRuntime(12804): java.lang.RuntimeException: Unable to start activity ComponentInfo{cn.zhl.classguiding/cn.zhl.classguiding.XueanPdfActivity}: android.view.WindowManager$BadTokenException: Unable to add window [email prote

Android Studio:Unable to add window [email&#160;protected] -- permission denied for this window 第一行代码

学习<第一行代码>的时候,出现的错误. java.lang.RuntimeException: Unable to start receiver com.example.sevenun.littledemo.receiver.ForceOfflineReceiver: android.view.WindowManager$BadTokenException: Unable to add window [email protected] -- permission denied for this

Context 对应的Unable to add window 错误记录

近日在使用 AlertDialog时发现一个错误:Unable to add window -- token null is not for an application,从前面观察是无法添加一个新的窗口到这个context,后来想了想前面是用的getApplicationContext()传递过来的context, 看来不能往context中加window吧,就改成了activity.this,代表一个具体的activity了,这样就OK了,记录下以后应该能解决这种添加新窗口传递context

Unable to add window -- token null is not for an application

代码中出现如下错误: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 分析: 问题在于new AlertDialog.Builder(Context),虽然这里的参数是AlertDialog.Builder(Context context) 但我们不能使用getApplicationContext()获得的Context,而必须使用

debug debug Unable to add window android.view.View--permission denied for this window type

1 AlertDialog builder=new AlertDialog.Builder(context).setTitle("注意:") 2 .setIcon(R.drawable.dailog_icon) 3 .setMessage("MS0"+ReceiveNumber+"请求建立语音连接,是否同意?") 4 .setPositiveButton("同意", new DialogInterface.OnClickLis

Android报错:WindowManager$BadTokenException: Unable to add window -- window has already been added

很久之前测试通过的代码,现在手机升级了Android7.0后一运行就崩溃,报出这样的错误,具体错误如下: Process: com.example.sho.android_anti_theft, PID: 26807 android.view.WindowManager$BadTokenException: Unable to add window -- window [email protected] has already been added at android.view.ViewRoo