将Unity Admob标语放置在具有显示切口的设备的底部

时间:2018-10-26 17:44:36

标签: c# android unity3d

我试图将广告横幅(通过Unity的官方Admob软件包生成)放置在屏幕的最底部,但是似乎无法在带有缺口的设备上很好地工作。

bv = new BannerView(adUnitId, adSize, AdPosition.Bottom);

此代码行将横幅广告完美地放置在无缺口设备(例如Pixel,Pixel XL,Pixel 2和2 XL)上的最底部,但是当设备顶部有缺口时,外观如下所示:< / p>

enter image description here

(演示照片取自this Github Issue。忽略可见的导航栏。)

横幅和屏幕底部之间的空间恰好是槽口的高度。我测试了多个缺口高度。

为了将横幅广告定位在最底部,我认为最好的解决方案是获取槽口的高度,然后使用以下代码行:

new BannerView(adUnitId, adSize, 0, (int)ConvertPixelsToDP(Screen.height - adHeight + notchHeight));

但是我找不到任何方法来获取抠图高度。我尝试使用ScreenDisplay类属性,但是没有一种方法可以帮助我获得屏幕的真实分辨率,包括凹口,因此我可以减去safeArea高度-并获得缺口。

有没有办法获得这种真实的屏幕分辨率?或任何其他可能的解决方案?

2 个答案:

答案 0 :(得分:2)

the main GitHub issue thread about this中,AdMob Unity插件开发人员表示“将优先考虑下一个版本的槽口兼容性”。早在10月,表明他们已经知道该错误,他们在1月22日发布消息说:“这项工作已被推迟,但将进入下一版本。尚无ETA,但应该很快。”那么谁知道这个问题何时会得到解决。

但是对于那些正在努力解决此问题的人:我找到了一种解决方法。就我而言,这是一种使广告显示在屏幕底部的解决方法,但我还将提到如何使广告正确显示在屏幕顶部。我仍然希望能尽快解决此问题,但是对于那些不想等待的人来说,这是一个选择...

我发现了这种解决方法,因为我首先从一个显而易见的解决方案开始:通过一个显而易见的公式手动计算y位置:int yDP = DensityIndependentPixels(Mathf.RoundToInt(Screen.safeArea.y + Screen.safeArea.height) - ScreenPixels(adSize.Height));这行得通,但从Unity 2018.3.5开始{{1} }始终为0,x和y始终为0,而​​宽度和高度可用来检测与safeArea相比是否有凹口(尽管据我所知,Display.main.systemHeightScreen.height == safeArea.height,因此width现在完全没有用,因为它仅传达您可以从safeAreaScreen.height获得的信息,因此您实际上无法检测到缺口在哪里...这意味着在此替代方法中,我假设该凹口位于屏幕顶部(一个安全的假设,但是某些电话具有两个凹口,一个位于顶部,一个位于底部,对于这些设备,我的替代方法将离开广告部分被底部陷印所覆盖...如果Screen.width获得有用的值,我的解决方法可以解决这个问题……无论如何,我离题了。)

基于此假设,我们可以使用经过稍微修改的公式:safeArea

但是令人沮丧的是,当我记录我期望的y位置值时...仍然显示在相同的奇怪偏移位置!我开始手动将y的位置从0开始增量增加,并确认在某个y坐标上,即使您增加该值,它出现的位置也将相同!然后我发现,如果您向y值添加更多的值,它将莫名其妙地弹出到屏幕顶部,并且您可以继续增加y位置以将其放回屏幕下方,但这次没有不会卡在奇怪的偏移位置!经过大量的实验,我发现这个无法解释的额外环绕y偏移的公式为:int yDP = DensityIndependentPixels(Screen.height - ScreenPixels(adSize.Height));,当添加到(DensityIndependentPixels(Display.main.systemHeight) + adSize.Height)时...现在,横幅在您期望的y位置!< / p>

简化数学运算后,手动y位置是一种非常实用的解决方案,可以将横幅广告放在带槽设备的底部,这非常简单:

intendedDensityIndependentPixelPosition

我已经使用Android 9中的所有模拟槽口对此进行了测试,并且可以正常工作(警告:双槽口仍然部分覆盖了广告,但是比覆盖应用程序UI的广告要好),但是请注意我尚未在实际的带槽设备上对此进行测试!

请注意,您仅在int yDP = DensityIndependentPixels(Screen.height + Display.main.systemHeight); 时才需要执行此操作...否则,您将在无缺口设备上使用Screen.height != Display.main.systemHeight

对于那些希望您的横幅显示在顶部的人,手动计算y位置更为简单。在相同的假设下,即凹口始终位于最上方,广告的y位置应设置为AdPosition.BOTTOM,而不必使用奇怪的莫名其妙的环绕偏移。请注意,鉴于我的应用中的横幅始终显示在底部,因此我没有测试过将横幅显示在顶部。

确保广告居中的x位置手动公式完全符合您的期望:DensityIndependentPixels(Display.main.systemHeight - Screen.height)那里没有什么特别奇怪的。

最后一点,我注意到在开始手动指定广告排名之后,在int xDP = Mathf.RoundToInt(DensityIndependentPixels(Display.main.systemWidth - ScreenPixels(adSize.Width)) / 2f);上调用Show()之后我无法调用Hide() ...它将进入一种不可见但可点击的怪异状态;只需BannerView即可解决此问题,并创建新的Destroy()而不是调用AdRequest ...我在Google支持论坛上看到了一些声明,说无论如何这都是更好的做法。

我希望我迷失在这一奇怪问题上的那一天,找到这种解决方法对这里的人有所帮助。

答案 1 :(得分:0)

不幸的是,这是由于admob无法正确计算Android上的最高级别而引起的。请注意,在iOS上,广告代码似乎承认了缺口的存在,并在其下方添加了额外的10个填充单位,这很奇怪。

我只是花了大约一天的时间来弄清楚横幅的相似问题。

有几种解决方法:

选项1.创建新的Java插件并添加下面的代码,或从C#中调用与此代码等效的代码:

public int getDisplayRealHeightPixels() {
    Point realSize = new Point();
    Display display = getWindowManager().getDefaultDisplay();
    if (Build.VERSION.SDK_INT >= 17) {
        display.getRealSize(realSize);
    }
    else {
        display.getSize(realSize);
    }
    return realSize.y;
}

然后使用getDisplayRealHeightPixels()来放置横幅。这就是我目前正在做的事情。

选项2。在绘画区域启用绘画:在onCreate上创建一个新的Java插件:

protected void onCreate(Bundle savedInstanceState) {
    ...
    // uncomment to allow painting in notch area;
    WindowManager.LayoutParams attributes = getWindow().getAttributes();
    attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
    getWindow().setAttributes(attributes);
    ...

一旦我调整应用程序以正确支持抠图,便会使用此选项。

选项3:等待Unity 2018.3正确支持缺口

根据https://unity3d.com/unity/beta/2018.3

“ Android:添加了对Android的陷波支持。”


陷阱:

  1. 以上修复都不完美(可能是选项3?但我还没有尝试过。)请确保在iOS(iPhone X)上进行测试,因为广告的行为与Android不同。
  2. 在Android Ads上,y == 0位于屏幕顶部,而在iPhone X上,y == 0则将横幅广告显示在槽口以下约10个单位。 对于iOS,我只是将“缺口大小”硬编码为30,然后在缺口区域中绘制我的应用。
  3. Android的分屏显示很痛苦-我尚未在此处进行完整的测试,在这种情况下,我的横幅在屏幕上飞来飞去。我只是决定稍后再修复。