NGUI HUD屏幕适配
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),围绕这两个数值存在多种可能的长宽比。
问题归类及解决方案
问题归类一
- 大窗口显示不全:部分高度为 640 的大窗口,长宽比达到 1.5,超过最小的 1.33,导致在 iPad 等小比例设备上无法完整显示。
- UI 元素叠加:在小比例设备上,左上角和右上角的 UI 在屏幕上方叠加在一起。
解决方案
- 尝试加大窗口的长宽比,以提高其适应性。
- 根据最小支持的长宽比值,适当加大 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; }
### 问题归类二
**背景图显示问题**:在以一张底图作为背景的场景(如启动界面、登录背景等)中,会出现显示不全或者有空白的情况。
#### 解决方法
1. 准备三张不同尺寸的图片,分别为 960x640(对应 iPhone4)、1136x640(对应 iPhone5)、1024x768(对应 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)); }
### 问题归类三
**遮罩覆盖不全**:部分遮罩不能覆盖住整个屏幕。
#### 解决方法
使用问题一的解决方法,通过 `GetPanelHeight()` 和 `GetPanelWidth()` 返回的值来设置遮罩的长宽值。
综上所述,通过上述针对不同问题的解决方案,可以有效解决 NGUI HUD 开发过程中的屏幕适配问题。