如何在 Nougat 的 multi-window 模式下定位吐司?

How to position a toast in Nougat's multi-window mode?

在使用 Nougat 的新 multi-window 模式时,我注意到如果我自己的应用程序在纵向模式下位于顶部 window,则 Toast 将显示在另一个应用程序之上。

这……一点都不好。所以我尝试将我的 Toast 跟随 this answer 定位到 "How to change position of Toast in Android?"

toast.setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);

不幸的是,Gravity 似乎被解释为 "gravity for the screen" 而不是 "gravity for my window"。

如何让 Toast 显示在 window 底部附近的某处并水平居中?

使用带有参数的 setGravity 方法:xOffset、yOffset。

Toast toast= Toast.makeText(getApplicationContext(),"Message Toast", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();

我怀疑这是有意为之的行为。根据 Material Design Guidelines Toasts 的说法,除了没有任何直接的方法可以实现您的愿望之外,Toast 主要用于传达系统消息,并且应该出现在屏幕底部。

我的猜测是,任何系统消息都应该与整个设备有关,不一定是特定于应用程序的,因此这种一致的行为是有道理的。也就是说,我可以理解为什么这种行为是不可取的,因为 Toast 最终占据了其中一个应用程序屏幕的近 25% ......但是,无论 Toast 的位置如何,它都会真正吞噬该屏幕遗产,无论是在您的申请中还是在下面的申请中。

如果您真的想实施解决方法,这里是垂直偏移 Toast 的实施方案。稍作改动应该可以实现横向模式,但它更加精致。

View root = findViewById(R.id.root_main);

int[] xy = new int[2];
root.getLocationOnScreen(xy);

DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(displayMetrics);
int devHeight = displayMetrics.heightPixels;

int viewHeight = root.getHeight();

Toast toast = Toast.makeText(getApplicationContext(), "hello", Toast.LENGTH_LONG);
int yOffset = Math.abs(xy[1] - devHeight + viewHeight) + toast.getYOffset();
toast.setGravity(Gravity.BOTTOM, 0, yOffset);
toast.show();