【Unity UGUI】UGUI适配

基本完成UGUI适配功能
  1 /*=================================================
  2 *FileName:      SafeAreaPanel.cs 
  3 *Author:        None 
  4 *UnityVersion:  2021.3.20f1 
  5 *Date:          2023-07-20 16:11 
  6 *Description:   UI适配组件
  7 *History:       
  8 *------------------------------------------------
  9 *2023年11月15日17:35:12
 10 *修复获取安全区尺寸的正确数据
 11 *重构适配数据的计算逻辑
 12 *重构全屏显示
 13 *新增RawImg自适应等比缩放(合并脚本)
 14 *重构后适配可根据具体上下左右安全区范围做显示
 15 =================================================*/
 16 using System;
 17 using UnityEngine;
 18 using UnityEngine.UI;
 19 
 20 public class SafeAreaPanel : MonoBehaviour
 21 {
 22     public enum SafeAreaType
 23     {
 24         自适应尺寸,
 25         全屏显示,
 26         /// <summary> 要求所有适配锚点x/y保持一致 </summary>
 27         RawImg自适应等比缩放,
 28     }
 29 
 30     RectTransform RT = null;
 31 
 32     private Vector2 m_OlPos;
 33 
 34     private RectTransform mParentCanvesRT;
 35 
 36     [Header("节点自适应")]
 37     public SafeAreaType m_SafeAreaType;
 38 
 39     [HideInInspector] public RawImage rawImage;
 40 
 41     ScreenOrientation m_LastScreenOrientation;
 42 
 43     bool invokeRefreshFrame = true;
 44 
 45     Vector2 lastCanvasSize;
 46     int lastScreenWidth;
 47     int lastScreenHeight;
 48 
 49     void OnEnable()
 50     {
 51         if (this == null || this.gameObject == null) return;
 52         if (mParentCanvesRT == null) mParentCanvesRT = GetComponentInParent<CanvasScaler>()?.GetComponent<RectTransform>();
 53         if (mParentCanvesRT == null) return;
 54         if (RT == null)
 55         {
 56             RT = GetComponent<RectTransform>();
 57             if (RT == null) return;
 58             m_OlPos = RT.anchoredPosition;
 59         }
 60         switch (m_SafeAreaType)
 61         {
 62             case SafeAreaType.自适应尺寸:
 63                 break;
 64             case SafeAreaType.全屏显示:
 65                 break;
 66             case SafeAreaType.RawImg自适应等比缩放:
 67                 if (rawImage == null) rawImage = GetComponent<RawImage>();
 68                 if (rawImage == null) return;
 69                 if (Application.isPlaying)
 70                 {
 71                     Debug.Assert(RT.anchorMax.x == RT.anchorMin.x && RT.anchorMax.x == RT.pivot.x, this);
 72                     Debug.Assert(RT.anchorMax.y == RT.anchorMin.y && RT.anchorMax.y == RT.pivot.y, this);
 73                 }
 74                 break;
 75             default:
 76                 break;
 77         }
 78         AutoSetSafeArea();
 79         Canvas.preWillRenderCanvases += Canvas_preWillRenderCanvases;
 80     }
 81 
 82     private void Canvas_preWillRenderCanvases()
 83     {
 84         if (!lastCanvasSize.Equals(mParentCanvesRT.sizeDelta))
 85         {
 86             lastCanvasSize = mParentCanvesRT.sizeDelta;
 87             invokeRefreshFrame = true;
 88         }
 89         /**
 90          * 渲染顺序为:
 91          *  1.当前帧:设备发生更改屏幕旋转事件,修改了Screen.orientation值
 92          *  2.下一帧:CanvasScaler在Canvas.preWillRenderCanvases 事件里修改Canvas适配sizeDelta
 93          *  preWillRenderCanvases    在即将开始 Canvas 渲染前调用的事件。
 94          *   
 95          *  所以在检测到屏幕旋转事件后,在下一次preWillRenderCanvases事件中进行适配计算
 96          */
 97         if (invokeRefreshFrame)
 98         {
 99             invokeRefreshFrame = false;
100             AutoSetSafeArea();
101         }
102         if (!Screen.orientation.Equals(m_LastScreenOrientation))
103         {
104             invokeRefreshFrame = true;
105             m_LastScreenOrientation = Screen.orientation;
106         }
107     }
108 
109     void OnDisable()
110     {
111         Canvas.preWillRenderCanvases -= Canvas_preWillRenderCanvases;
112     }
113     void AutoSetSafeArea()
114     {
115         float offsetTop = Screen.safeArea.yMin / Screen.currentResolution.height;
116         float offsetBottom = Screen.safeArea.yMax / Screen.currentResolution.height;
117         float offsetLeft = Screen.safeArea.xMin / Screen.currentResolution.width;
118         float offsetRight = Screen.safeArea.xMax / Screen.currentResolution.width;
119 
120 
121         switch (m_SafeAreaType)
122         {
123             case SafeAreaType.自适应尺寸:
124                 //安全区域偏移量
125                 RT.anchorMin = new Vector2(offsetLeft, offsetTop);
126                 RT.anchorMax = new Vector2(offsetRight, offsetBottom);
127                 break;
128             case SafeAreaType.全屏显示:
129                 //还原安全区偏移量
130                 RT.anchorMin = RT.anchorMax = new Vector2(0.5f, 0.5f);
131                 RT.sizeDelta = mParentCanvesRT.sizeDelta;
132 
133                 Vector2 SafeAreaPanelOffset;
134                 SafeAreaPanelOffset.x = ((Screen.currentResolution.width - Screen.safeArea.xMax) * 0.5f - Screen.safeArea.xMin * 0.5f) * mParentCanvesRT.sizeDelta.x / Screen.currentResolution.width;
135                 SafeAreaPanelOffset.y = ((Screen.currentResolution.height - Screen.safeArea.yMax) * 0.5f - Screen.safeArea.yMin * 0.5f) * mParentCanvesRT.sizeDelta.y / Screen.currentResolution.height;
136 
137                 RT.anchoredPosition = SafeAreaPanelOffset;
138                 break;
139             case SafeAreaType.RawImg自适应等比缩放:
140                 Vector2 textureSize, rawRtSize;
141                 textureSize = rawRtSize = rawImage.texture == null ? new Vector2(1667, 1024) : new Vector2(rawImage.texture.width, rawImage.texture.height);
142                 if (mParentCanvesRT.sizeDelta.x / mParentCanvesRT.sizeDelta.y < textureSize.x / textureSize.y)
143                 {
144                     rawRtSize.y = mParentCanvesRT.sizeDelta.y;
145                     rawRtSize.x = mParentCanvesRT.sizeDelta.y * textureSize.x / textureSize.y;
146                 }
147                 else
148                 {
149                     rawRtSize.x = mParentCanvesRT.sizeDelta.x;
150                     rawRtSize.y = mParentCanvesRT.sizeDelta.x * textureSize.y / textureSize.x;
151                 }
152 
153                 SafeAreaPanelOffset.x = ((Screen.currentResolution.width - Screen.safeArea.xMax) * RT.anchorMax.x - Screen.safeArea.xMin * (1 - RT.anchorMin.x)) * mParentCanvesRT.sizeDelta.x / Screen.currentResolution.width;
154                 SafeAreaPanelOffset.y = ((Screen.currentResolution.height - Screen.safeArea.yMax) * RT.anchorMax.y - Screen.safeArea.yMin * (1 - RT.anchorMax.y)) * mParentCanvesRT.sizeDelta.y / Screen.currentResolution.height;
155 
156                 RT.sizeDelta = rawRtSize;
157                 RT.anchoredPosition = m_OlPos + SafeAreaPanelOffset;
158                 break;
159             default:
160                 break;
161         }
162 
163     }
164 
165     //#if UNITY_EDITOR || EDITORMODE
166     //    //public bool ShowGUI;
167     //    //private void OnGUI()
168     //    //{
169     //    //    if (!ShowGUI)
170     //    //    {
171     //    //        return;
172     //    //    }
173     //    //    GUIStyle gUIStyle = new GUIStyle();
174     //    //    gUIStyle.normal.textColor = Color.blue;
175     //    //    gUIStyle.fontSize = 20;
176     //    //    GUILayout.Space(100);
177     //    //    GUILayout.Label($"offsetTop: {offsetTop}", gUIStyle);
178     //    //    GUILayout.Label($"offsetBottom: {offsetBottom}", gUIStyle);
179     //    //    GUILayout.Label($"offsetLeft: {offsetLeft}", gUIStyle);
180     //    //    GUILayout.Label($"offsetRight: {offsetRight}", gUIStyle);
181     //    //    GUILayout.Label($"Screen.safeArea.xMin: {Screen.safeArea.xMin}", gUIStyle);
182     //    //    GUILayout.Label($"Screen.safeArea.xMax: {Screen.safeArea.xMax}", gUIStyle);
183     //    //    GUILayout.Label($"Screen.safeArea.yMax: {Screen.safeArea.yMax}", gUIStyle);
184     //    //    GUILayout.Label($"Screen.safeArea.yMin: {Screen.safeArea.yMin}", gUIStyle);
185     //    //    GUILayout.Label($"Screen.currentResolution.width: {Screen.currentResolution.width}", gUIStyle);
186     //    //    GUILayout.Label($"Screen.currentResolution.height: {Screen.currentResolution.height}", gUIStyle);
187     //    //    GUILayout.Label($"SafeAreaPanelOffset: ({SafeAreaPanelOffset.x},{SafeAreaPanelOffset.y})", gUIStyle);
188     //    //    GUILayout.Label($"Screen.orientation: {Screen.orientation}", gUIStyle);
189     //    //    GUILayout.Label($"m_LastScreenOrientation: {m_LastScreenOrientation}", gUIStyle);
190 
191     //    //}
192     //#endif
193 
194 
195 }
View Code
*Screen.safeArea不支持Android8.0及以下的信息获取,如果需要单独添加设备适配配置

当然也可以跟我一下 忽略。。。
针对折叠屏的适配,暂时可以在Android层添加onConfigurationChanged监听
然后在Unity里面调用一下适配刷新即可

折叠屏的适配-这里同样可以

1 if (!lastCanvasSize.Equals(mParentCanvesRT.sizeDelta))
2         {
3             lastCanvasSize = mParentCanvesRT.sizeDelta;
4             invokeRefreshFrame = true;
5         }

 

posted @ 2023-11-15 18:00  lovewaits  阅读(129)  评论(0编辑  收藏  举报