【问题标题】:Positioning Unity Admob Banner at the Bottom on a Device with a Display Cutout将 Unity Admob 横幅定位在带有显示屏切口的设备底部
【发布时间】:2019-03-31 12:25:09
【问题描述】:

我正在尝试将我的广告横幅(通过 Unity 的官方 Admob 包生成)放置在屏幕的最底部,但它似乎不适用于带有缺口的设备。

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

这行代码在没有缺口的设备(例如 Pixel、Pixel XL、Pixel 2 和 2 XL)上完美地将横幅定位在最底部,但是当设备顶部有一个缺口时看起来像这样:

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

横幅和屏幕底部之间的空间正好是缺口的高度。我用多个缺口高度对其进行了测试。

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

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

但我找不到任何方法来获得切口高度。我尝试使用 Screen 和 Display 类属性,但没有任何方法可以帮助我获得屏幕的真实分辨率,包括缺口,所以我可以减去 safeArea 高度 - 并获得缺口的确切高度。

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

【问题讨论】:

  • 如果你只使用Screen.height - adHeight会发生什么?
  • @ruzihm 它位于底部,但横幅和底部之间的空间等于缺口的高度。
  • 只是好奇。如果你这样做 Debug.Log(Screen.height - Screen.safeArea.height); 会发生什么?此外,如果您尝试硬编码notchHeight 的值,它是否有效?想要确定这种方法是否有效。
  • @Ruzihm Screen.height - Screen.safeArea.height 等于 0,这很奇怪。当对notchHeight 的值进行硬编码时,一切正常(我在 Photoshop 中用截图测量了它)
  • 这绝对不寻常。我会仔细检查您拥有的任何可能环绕 Screen.height 的自定义代码,作为干扰事物的“便利”。

标签: c# android unity3d


【解决方案1】:

来自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 开始 safeArea 总是有 0 , x 和 y 为 0,而宽度和高度可用于检测与 Display.main.systemHeight 相比有一个缺口(尽管据我所知,Screen.height == safeArea.height 和 width 相同,所以 safeArea现在完全没用,因为它只传达您可以从Screen.height 和Screen.width 获得的信息),您实际上无法检测到缺口在哪里......这意味着在这个解决方法中,我假设缺口在屏幕顶部(一个安全的假设,但有些手机有两个凹口,一个在顶部,一个在底部,对于这些设备,我的解决方法将使广告部分被底部凹口覆盖......如果safeArea 有用的话值,我的解决方法可以解释这一点......无论如何,我离题了。)......

有了这个假设,我们可以使用稍微修改的公式:int yDP = DensityIndependentPixels(Screen.height - ScreenPixels(adSize.Height));

但令人沮丧的是,当我记录我期望的 y 位置值时……它仍然出现在同一个奇怪的偏移位置!我开始从 0 开始手动增加 y 位置,并确认在某个 y 坐标处,即使您增加该值,它出现的位置也会相同!然后我发现,如果你在 y 值上增加一点,它会莫名其妙地弹回到屏幕顶部,你可以继续增加 y 位置,让它回到屏幕下方,只不过这次没有不要卡在奇怪的偏移位置!经过大量实验后,我发现这个莫名其妙的额外环绕 y 偏移的公式是:(DensityIndependentPixels(Display.main.systemHeight) + adSize.Height) 并且当添加到 intendedDensityIndependentPixelPosition...您现在在预期的 y 位置有了横幅!

一旦您简化了数学运算,手动 y 位置是一种将横幅放置在缺口设备底部的功能性变通方法,非常简单:

int yDP = DensityIndependentPixels(Screen.height + Display.main.systemHeight);

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

请注意,您只需要在 Screen.height != Display.main.systemHeight... 时执行此操作,否则您使用的是无槽设备,应该使用 AdPosition.BOTTOM。

对于那些希望您的横幅出现在顶部的人来说,手动计算 y 位置更加简单。在槽口始终位于顶部的相同假设下,广告的 y 位置应设置为 DensityIndependentPixels(Display.main.systemHeight - Screen.height),不需要奇怪的莫名其妙的环绕偏移。请注意,鉴于我的应用中的横幅始终显示在底部,因此我尚未测试在顶部显示横幅。

确保广告居中的 x 位置手动公式与您期望的完全一样:int xDP = Mathf.RoundToInt(DensityIndependentPixels(Display.main.systemWidth - ScreenPixels(adSize.Width)) / 2f); 没有什么特别奇怪的地方。

最后一点,我注意到在我开始手动指定广告位置后,在BannerView 上调用Hide() 后,我无法调用Show()...它会进入一个奇怪的状态不可见但可点击;简单地解决这个问题Destroy() 并创建一个新的AdRequest 而不是调用Show()...我在 Google 支持论坛上看到一些声明说无论如何这是更好的做法。

我希望有一天我迷失在这个奇怪的问题上并找到这个解决方法可以帮助这里的人。

【讨论】:

    【解决方案2】:

    很遗憾,这是由于 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.在cutout区域启用绘画:创建一个新的java插件,在onCreate添加:

    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 广告上,y==0 是屏幕顶部,而在 iPhone X 上,y==0 将横幅呈现在缺口下方约 10 个单位处。 对于 iOS,我只需将“缺口大小”硬编码为 30,然后在缺口区域绘制我的应用。
    3. Android 分屏很痛苦 - 我还没有完全测试过,在这种情况下我的横幅在屏幕上飞来飞去。我只是决定稍后修复它。

    【讨论】:

    • 嗨!似乎 2018.3 并没有解决问题。另外,在“不安全区域”中绘图的新功能似乎并没有真正解决(或改变)任何事情。剩下的唯一选择是第一个 - 我怎样才能创建这样的插件?
    • 在线搜索“unity create java plugin” - 你会找到很多教程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多