您好,登錄后才能下訂單哦!
今天在幫同學實現一個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; 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時就用我提供的這個就可以了,當然還有可能有更多的解決方案,如果有其他解決方案時,請分享一起學習,寫此博文,只是希望對目前還沒解決的人提供一點幫助。
×××
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。