NGUI使用UIPanel和UIAnchor来管理UI元素,对屏幕适配已经支持得相当不错。但是由于屏幕尺寸的千奇百怪,开发过程中或多或少会碰到一些屏幕适配的问题。
  微岛的HUD是基于iPhone 4的分辨率进行开发的,即限定了UIRoot上的UIPanel的Scaling Style为FixedSize, Manual Height为640。在做适配其他设备时还算比较顺利,主要碰到了一些小问题,在此谈谈。
  先来看看市场上移动设备的分辨率情况,下面是友盟2014年7月份数据。

 

 

 
从数据可以看出,市场主流设备的长宽比最小的在1.33(即4/3),最大的在1.78(即16/9),围绕着这两个数值,就有许多可能会发生。

问题归类一:
1、部分高度为640的大窗口的长宽比达到1.5,超过了最小的1.33,导致在iPad等小比例设备上无法显示完整;
2、小比例设备上,左上角和右上角的UI在屏幕上方叠加在一起;

解决方案:
1、先试试能否加大窗口长宽比,方便适应
2、根据最小支持的长宽比值,适当加大UIPanel的Manual Height,达到总体缩小Panel元素的目的;

[C#] 纯文本查看 复制代码
const int PANEL_HEIGHT_DEFAULT = 640;  
const float ADAPTE_ASPECTRATIO_MIN = 1.5f; //窗口支持的最小长宽比  
  
//UIPanel使用此值做为Manual Height  
public static int GetPanelHeight()  
{  
        int panelHeight = PANEL_HEIGHT_DEFAULT;  
        float aspectRation = Screen.width * 1.0f / Screen.height;  
        if (aspectRation < ADAPTE_ASPECTRATIO_MIN)  
        {  
            int minWidth = (int)(Screen.height * ADAPTE_ASPECTRATIO_MIN);  
            panelHeight = PANEL_HEIGHT_DEFAULT * minWidth / Screen.width;  
        }  
        return panelHeight;  
}  
  
public static int GetPanelWidth()  
{  
    return GetPanelHeight() * Screen.width / Screen.height;  
}  

 

问题归类二:
3、一张底图做背景的场景(如启动界面、登录背景等),会出现显示不全或者有空白的地方;

解决方法:
1、准备三张图,尺寸分别为960x640, 1136x640,1024x768,即分别为iPhone4, iPhone5, iPad 1的,放到Resources/Texture目录下,分别命名为splash_4to3@ldpi.png, splash_3to2@xhdpi.png和splash_16to9@xhdpi.png;
2、根据屏幕长宽比动态调节UIPanel和UI2DSprite的宽度和高度,代码如下;

 
[C#] 纯文本查看 复制代码
const float ADAPTE_ASPECTRATIO_4TO3 = 1.334f;   
const float ADAPTE_ASPECTRATIO_3TO2 = 1.5f;  
const float ADAPTE_ASPECTRATIO_16TO9 = 1.77f;  
  
public UI2DSprite splashSprite;  
  
    int width = Screen.width;  
    int height = Screen.height;  
    float aspectRation = Screen.width * 1.0f / Screen.height;  
    string splashTextureName = null;  
    if (aspectRation <= ADAPTE_ASPECTRATIO_4TO3)  
    {  
        splashTextureName = @"Textures/splash_4to3@ldpi";  
    }  
    else if (aspectRation <= ADAPTE_ASPECTRATIO_3TO2)  
    {  
        splashTextureName = @"Textures/splash_3to2@xhdpi";  
    }  
    else if (aspectRation <= ADAPTE_ASPECTRATIO_16TO9)  
    {  
        splashTextureName = @"Textures/splash_16to9@xhdpi";  
    }  
    else  
    {  
        splashTextureName = @"Textures/splash_16to9@xhdpi";  
    }  
    Sprite splashTexture = (Sprite)Resources.Load(splashTextureName, typeof(Sprite));  
    if(splashTexture != null)  
    {  
        int textureWidth = (int)splashTexture.textureRect.width;  
        int textureHeight = (int)splashTexture.textureRect.height;  
        splashSprite.sprite2D = splashTexture;  
  
        if(Screen.height < textureHeight)  
        {  
            textureWidth = textureWidth * Screen.height / textureHeight;  
            textureHeight = Screen.height;  
        }  
  
        if (aspectRation > ADAPTE_ASPECTRATIO_16TO9)  
        {  
            textureWidth = Screen.width;  
            textureHeight = textureWidth * 640 / 1136;  
        }  
        root.manualHeight = textureHeight;  
  
        splashSprite.width = textureWidth;  
        splashSprite.height = textureHeight;  
    }  
    else  
    {  
        Debug.LogWarning(string.Format("No Sprite At Resource Path {0} Found!", splashTextureName));  
    }


问题归类三:
4、部分遮罩不能覆盖住整个屏幕:


解决方法:

使用问题一的解决方法,用GetPanelHeight()和GetPanelWidth()返回的值 来设置遮罩的长宽值;