在Android Activity中创建弹出窗口时出现问题

Amp*_*y91 52 android popupwindow

我正在尝试创建一个仅在应用程序第一次启动时出现的弹出窗口.我希望它显示一些文本并有一个按钮来关闭弹出窗口.但是,我在让PopupWindow工作时遇到了麻烦.我尝试了两种不同的方法:

首先我有一个XML文件,它声明了popup.xml的布局(在linearlayout中的textview),我在主Activity的OnCreate()中添加了这个:

PopupWindow pw = new PopupWindow(findViewById(R.id.popup), 100, 100, true);
    pw.showAtLocation(findViewById(R.id.main), Gravity.CENTER, 0, 0);
Run Code Online (Sandbox Code Playgroud)

其次,我使用此代码完全相同:

final LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    PopupWindow pw = new PopupWindow(inflater.inflate(R.layout.popup, (ViewGroup) findViewById(R.layout.main) ), 100, 100, true);
    pw.showAtLocation(findViewById(R.id.main_page_layout), Gravity.CENTER, 0, 0);
Run Code Online (Sandbox Code Playgroud)

第一个抛出NullPointerException,第二个抛出BadTokenException并说"无法添加窗口 - 令牌null无效"

世界上我做错了什么?我是非常新手所以请耐心等待.

kor*_*zik 177

为了避免BadTokenException,您需要在调用所有生命周期方法之后推迟显示弹出窗口( - >显示活动窗口):

 findViewById(R.id.main_page_layout).post(new Runnable() {
   public void run() {
     pw.showAtLocation(findViewById(R.id.main_page_layout), Gravity.CENTER, 0, 0);
   }
});
Run Code Online (Sandbox Code Playgroud)

  • 不,不会.它必须在所有生命周期方法完成后运行.在onCreate或onStart上运行上面的代码,它将在调用所有init生命周期方法并设置所有内容后在UI线程上执行pw.showAtLocation(这是post方法的目的 - 读取其javadoc以获取更多详细信息).这应该工作正常 (5认同)
  • 在onAttachedToWindow()方法中? (3认同)

Dan*_*okh 30

如果您连续启动2个活动,Kordzik提供的解决方案将无效:

startActivity(ActivityWithPopup.class);
startActivity(ActivityThatShouldBeAboveTheActivivtyWithPopup.class);
Run Code Online (Sandbox Code Playgroud)

如果你在这种情况下以这种方式添加弹出窗口,你将得到同样的崩溃,因为在这种情况下,ActivityWithPopup不会附加到Window.

更广泛的解决方法是onAttachedToWindowonDetachedFromWindow.

而且也不需要postDelayed(Runnable,100).因为这100毫克不保证任何东西

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    Log.d(TAG, "onAttachedToWindow");

    showPopup();
}

@Override
public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    Log.d(TAG, "onDetachedFromWindow");

    popup.dismiss();
}
Run Code Online (Sandbox Code Playgroud)


Tod*_*ton 17

我发现接受的答案对我不起作用.我仍然收到了错误的令牌错误..所以我只是从处理程序调用runnable延迟这样..

new Handler().postDelayed(new Runnable() {
    public void run() {
        showPopup();
    }
}, 100);
Run Code Online (Sandbox Code Playgroud)


bip*_*pin 10

使用类上下文例如.MainActivity.this而不是getApplicationContext()