PopupWindow嵌套PopupWindow时报Unabletoaddwindow的处理

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

企业建站必须是能够以充分展现企业形象为主要目的,是企业文化与产品对外扩展宣传的重要窗口,一个合格的网站不仅仅能为公司带来巨大的互联网上的收集和信息发布平台,成都创新互联公司面向各种领域:石凉亭成都网站设计营销型网站解决方案、网站设计等建站排名服务。


android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@4340e618 is not valid; is your activity running?

先贴代码:

volleytest_lay.xml,pop_first_lay.xml,pop_second_lay:

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="#ffffff"

    android:orientation="vertical" >

   

        android:id="@+id/popBtn"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

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

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时就用我提供的这个就可以了,当然还有可能有更多的解决方案,如果有其他解决方案时,请分享一起学习,写此博文,只是希望对目前还没解决的人提供一点帮助。

×××


文章题目:PopupWindow嵌套PopupWindow时报Unabletoaddwindow的处理
本文URL:http://azwzsj.com/article/poidid.html