Привет. Пока не забыл что и как делал, поделюсь хаком:)
В адмобе есть баннер 320х50 dp. Нам нужно отобразить его вверху экрана, а под ним кнопку. Если баннера нет, то сдвигаем кнопку вверх.
Вроде все просто, так? Знаем, осталось перевести по формуле в пиксели:
var pixelsHeight = 50 * Screen.dpi / 160f;
Но хер там! Есть еще кое что, о чем не написано(или я плохо искал). Если запустить этот код на смартфоне 480 х 800 с dpi 160, то ничего работать не будет:) Потому что теперь баннер стал 480x75dp. На планшетах всегда берется баннер 320х50 dp. Потратив на танцы с бубном не один час времени, делюсь решением проблемы:
Где то в и-нетах ходит вот такой классик:
using System;
using UnityEngine;
using System.Collections;
public static class DisplayUtils
{
private const float DEFAULT_DPI = 160.0f;
private const float MIN_TABLET_INCHES = 6.8f;
public static int DpToPixel(this int dp)
{
// Convert the dps to pixels
return (int)(dp * GetScale() + 0.5f);
}
public static int DpToPixel(this float dp)
{
// Convert the dps to pixels
return (int)(dp * GetScale() + 0.5f);
}
public static int PixelToDp(this int px)
{
// Convert the pxs to dps
return (int)(px / GetScale() - 0.5f);
}
public static int PixelToDp(this float px)
{
// Convert the pxs to dps
return (int)(px / GetScale() - 0.5f);
}
private static float GetDPI()
{
return Screen.dpi == 0 ? DEFAULT_DPI : Screen.dpi;
}
private static float GetScale()
{
return GetDPI() / DEFAULT_DPI;
}
public static bool DeviceIsTablet()
{
float inches = (float)Math.Sqrt(Math.Pow(Screen.width / GetDPI(), 2) + Math.Pow(Screen.height / GetDPI(), 2));
return inches > MIN_TABLET_INCHES;
}
}
Наша логика:
private float GetHeight(float pixelsScaler)
{
float w = Mathf.Min(Screen.height, Screen.width);//screen width
float halfBannerSize = new Vector2(160,25);// --> 320x50 / 2
float scaledHeight = Mathf.Floor(w / halfBannerSize.x) * halfBannerSize .y; //узнаем во сколько раз заскейлился баннер по горизонтали, т.к. скейлиться он кратно 160.
//tablet
if (DisplayUtils.DeviceIsTablet())
return pixelsScaler * (halfBannerSize .y * 2f).DpToPixel();
//phone
return pixelsScaler * scaledHeight;
}
pixelsScaler — это множитель. Я использовал ngui и у меня была жестко задана высота в 1136 пикселей. Так что я передавал в функцию значение:
float h = Mathf.Max(Screen.height, Screen.width);
float adj = 1136f / h;//1136 - UI высота
var height = GetHeight(adj);//это уже UI координаты
Странно то, как скейлится баннер и что приходится делить пиксели на dp(когда считаем scaledHeight). Может кто-то нашел вариант лучше? или хотя бы объяснит почему так оно работает?)