[分享干货晒技术]NGUI HUD屏幕适配

发表于2015-07-29
评论0 1.5k浏览
  NGUI使用UIPanel和UIAnchor来管理UI元素,对屏幕适配已经支持得相当不错。但是由于屏幕尺寸的千奇百怪,开发过程中或多或少会碰到一些屏幕适配的问题。

  微岛的HUD是基于iPhone 4的分辨率进行开发的,即限定了UIRoot上的UIPanel的Scaling Style为FixedSize, Manual Height为640。在做适配其他设备时还算比较顺利,主要碰到了一些小问题,在此谈谈。

  先来看看市场上移动设备的分辨率情况,下面是友盟2014年7月份数据。
Android设备分辨率
分辨率长宽比长宽比市场占有率
1280*72016/91.7820.50%
960*54016/91.789.70%
1920*108016/91.787.80%
854*480~7/41.7512.60%
800*4805/31.6727.50%
1184*720~5/31.671.40%
1280*8008/51.61.20%
480*3203/21.59.90%
800*6004/31.330.70%

iOS设备分辨率
分辨率长宽比长宽比市场占有率
1136*640~7/41.7541.9%
960*6403/21.537.7%
480*3203/21.50.2%
2048*15364/31.3312.0%
1024*7684/31.338.2%

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

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

解决方案:
1、先试试能否加大窗口长宽比,方便适应
2、根据最小支持的长宽比值,适当加大UIPanel的Manual Height,达到总体缩小Panel元素的目的;
  1. const int PANEL_HEIGHT_DEFAULT = 640;  
  2. const float ADAPTE_ASPECTRATIO_MIN = 1.5f; //窗口支持的最小长宽比  
  3.   
  4. //UIPanel使用此值做为Manual Height  
  5. public static int GetPanelHeight()  
  6. {  
  7.         int panelHeight = PANEL_HEIGHT_DEFAULT;  
  8.         float aspectRation = Screen.width * 1.0f / Screen.height;  
  9.         if (aspectRation < ADAPTE_ASPECTRATIO_MIN)  
  10.         {  
  11.             int minWidth = (int)(Screen.height * ADAPTE_ASPECTRATIO_MIN);  
  12.             panelHeight = PANEL_HEIGHT_DEFAULT * minWidth / Screen.width;  
  13.         }  
  14.         return panelHeight;  
  15. }  
  16.   
  17. public static int GetPanelWidth()  
  18. {  
  19.     return GetPanelHeight() * Screen.width / Screen.height;  
  20. }  

问题归类二:
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的宽度和高度,代码如下;
  1. const float ADAPTE_ASPECTRATIO_4TO3 = 1.334f;   
  2. const float ADAPTE_ASPECTRATIO_3TO2 = 1.5f;  
  3. const float ADAPTE_ASPECTRATIO_16TO9 = 1.77f;  
  4.   
  5. public UI2DSprite splashSprite;  
  6.   
  7.     int width = Screen.width;  
  8.     int height = Screen.height;  
  9.     float aspectRation = Screen.width * 1.0f / Screen.height;  
  10.     string splashTextureName = null;  
  11.     if (aspectRation <= ADAPTE_ASPECTRATIO_4TO3)  
  12.     {  
  13.         splashTextureName = @"Textures/splash_4to3@ldpi";  
  14.     }  
  15.     else if (aspectRation <= ADAPTE_ASPECTRATIO_3TO2)  
  16.     {  
  17.         splashTextureName = @"Textures/splash_3to2@xhdpi";  
  18.     }  
  19.     else if (aspectRation <= ADAPTE_ASPECTRATIO_16TO9)  
  20.     {  
  21.         splashTextureName = @"Textures/splash_16to9@xhdpi";  
  22.     }  
  23.     else  
  24.     {  
  25.         splashTextureName = @"Textures/splash_16to9@xhdpi";  
  26.     }  
  27.     Sprite splashTexture = (Sprite)Resources.Load(splashTextureName, typeof(Sprite));  
  28.     if(splashTexture != null)  
  29.     {  
  30.         int textureWidth = (int)splashTexture.textureRect.width;  
  31.         int textureHeight = (int)splashTexture.textureRect.height;  
  32.         splashSprite.sprite2D = splashTexture;  
  33.   
  34.         if(Screen.height < textureHeight)  
  35.         {  
  36.             textureWidth = textureWidth * Screen.height / textureHeight;  
  37.             textureHeight = Screen.height;  
  38.         }  
  39.   
  40.         if (aspectRation > ADAPTE_ASPECTRATIO_16TO9)  
  41.         {  
  42.             textureWidth = Screen.width;  
  43.             textureHeight = textureWidth * 640 / 1136;  
  44.         }  
  45.         root.manualHeight = textureHeight;  
  46.   
  47.         splashSprite.width = textureWidth;  
  48.         splashSprite.height = textureHeight;  
  49.     }  
  50.     else  
  51.     {  
  52.         Debug.LogWarning(string.Format("No Sprite At Resource Path {0} Found!", splashTextureName));  
  53.     }  

问题归类三:
4、部分遮罩不能覆盖住整个屏幕:
解决方法:使用问题一的解决方法,用GetPanelHeight()和GetPanelWidth()返回的值 来设置遮罩的长宽值;

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引