PopupWindow嵌套PopupWindow时报Unable to add window的处理
今天在帮同学实现一个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:
<?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;
privateView 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时就用我提供的这个就可以了,当然还有可能有更多的解决方案,如果有其他解决方案时,请分享一起学习,写此博文,只是希望对目前还没解决的人提供一点帮助。
×××
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。