在Android活动中创建弹出窗口的问题

56

我正在尝试创建一个弹出窗口,在应用程序启动时只出现一次。我想要显示一些文本,并有一个按钮关闭该弹窗。然而,我无法让PopupWindow正常工作。我尝试了两种不同的方法:

首先,我有一个名为popup.xml的XML文件,声明了弹出窗口的布局(一个线性布局内的文本视图),并在我的主Activity的OnCreate()中添加了它:

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

然后我用完全相同的代码进行了这个操作:

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);

第一个抛出NullPointerException异常,第二个抛出BadTokenException异常,并显示“无法添加窗口--令牌为null无效”。

我到底做错了什么?我非常新手,请多包涵。

14个回答

0

我也遇到了同样的问题(BadTokenException),在dialog.show()时出现AlertDialog。我是按照一些示例制作AlertDialog的。在我的情况下,这个问题的原因是一个字符串 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST)

在我删除它之后,一切都正常工作了。


0
如果你在另一个PopupWindow中显示PopupWindow,请不要使用第一个POP中的视图,而应该使用原始父视图。
pop.showAtLocation(parentView, ... );

0
也许是时候考虑一种更新的解决方案了。这种方法每50毫秒检查5次弹出窗口的父视图是否有一个令牌。我在我的自定义弹出窗口中使用它。
private fun tryToShowTooltip(tooltipLayout: View) {
    Flowable.fromCallable { parentView.windowToken != null }
            .map { hasWindowToken ->
                if (hasWindowToken) {
                    return@map hasWindowToken
                }
                throw RetryException()
            }
            .retryWhen { errors: Flowable<Throwable> ->
                errors.zipWith(
                        Flowable.range(1, RETRY_COUNT),
                        BiFunction<Throwable, Int, Int> { error: Throwable, retryCount: Int ->
                            if (retryCount >= RETRY_COUNT) {
                                throw error
                            } else {
                                retryCount
                            }
                        })
                        .flatMap { retryCount: Int ->
                            Flowable.timer(retryCount * MIN_TIME_OUT_MS, TimeUnit.MILLISECONDS)
                        }
            }
            .onErrorReturn {
                false
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ hasWindowToken ->
                if (hasWindowToken && !isShowing) {
                    showAtLocation(tooltipLayout, Gravity.NO_GRAVITY, 100, 100)
                }
            }, { t: Throwable? ->
                //error logging
            })
}

使用

companion object {

    private const val RETRY_COUNT = 5
    private const val MIN_TIME_OUT_MS = 50L
}

class RetryException : Throwable()

-3

您可以通过pw.showAtLocation方法指定y偏移量以考虑状态栏...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接