Part of these game systems:
beginner Touch & Mobile

Mobile Safe Area Handler

Automatically adjusts UI RectTransform to respect device safe areas on notched phones and tablets. Supports runtime orientation changes and works across iOS and Android devices.

Unity 2022.3+ · 2.8 KB · MobileSafeArea.cs

How to Use

1

Create a full-screen RectTransform panel as a child of your Canvas

2

Attach the MobileSafeArea script to that panel

3

Place all your UI elements inside this safe area panel

4

Toggle applyTop/Bottom/Left/Right to control which edges are inset

5

Enable simulateInEditor to preview notch behavior in the Unity editor

Source Code

MobileSafeArea.cs
C#
using UnityEngine;

[RequireComponent(typeof(RectTransform))]
public class MobileSafeArea : MonoBehaviour
{
    [Header("Settings")]
    [SerializeField] private bool updateContinuously = true;
    [SerializeField] private bool applyTop = true;
    [SerializeField] private bool applyBottom = true;
    [SerializeField] private bool applyLeft = true;
    [SerializeField] private bool applyRight = true;

    [Header("Editor Simulation")]
    [SerializeField] private bool simulateInEditor;
    [SerializeField] private float simulatedNotchHeight = 80f;

    private RectTransform rectTransform;
    private Rect lastSafeArea;
    private Vector2Int lastScreenSize;
    private ScreenOrientation lastOrientation;

    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
        ApplySafeArea();
    }

    private void Update()
    {
        if (!updateContinuously) return;

        if (HasScreenChanged())
        {
            ApplySafeArea();
        }
    }

    private bool HasScreenChanged()
    {
        Rect safeArea = GetSafeArea();
        Vector2Int screenSize = new Vector2Int(Screen.width, Screen.height);
        ScreenOrientation orientation = Screen.orientation;

        if (safeArea != lastSafeArea || screenSize != lastScreenSize || orientation != lastOrientation)
        {
            lastSafeArea = safeArea;
            lastScreenSize = screenSize;
            lastOrientation = orientation;
            return true;
        }

        return false;
    }

    private void ApplySafeArea()
    {
        Rect safeArea = GetSafeArea();

        if (Screen.width <= 0 || Screen.height <= 0) return;

        Vector2 anchorMin = safeArea.position;
        Vector2 anchorMax = safeArea.position + safeArea.size;

        anchorMin.x /= Screen.width;
        anchorMin.y /= Screen.height;
        anchorMax.x /= Screen.width;
        anchorMax.y /= Screen.height;

        if (!applyLeft) anchorMin.x = 0f;
        if (!applyBottom) anchorMin.y = 0f;
        if (!applyRight) anchorMax.x = 1f;
        if (!applyTop) anchorMax.y = 1f;

        anchorMin.x = Mathf.Clamp01(anchorMin.x);
        anchorMin.y = Mathf.Clamp01(anchorMin.y);
        anchorMax.x = Mathf.Clamp01(anchorMax.x);
        anchorMax.y = Mathf.Clamp01(anchorMax.y);

        rectTransform.anchorMin = anchorMin;
        rectTransform.anchorMax = anchorMax;
        rectTransform.offsetMin = Vector2.zero;
        rectTransform.offsetMax = Vector2.zero;
    }

    private Rect GetSafeArea()
    {
#if UNITY_EDITOR
        if (simulateInEditor)
        {
            return new Rect(
                0f,
                0f,
                Screen.width,
                Screen.height - simulatedNotchHeight);
        }
#endif
        return Screen.safeArea;
    }

    public void ForceUpdate()
    {
        ApplySafeArea();
    }

    public Rect GetCurrentSafeArea()
    {
        return GetSafeArea();
    }

    public Vector2 GetSafeAreaRatio()
    {
        Rect safe = GetSafeArea();
        return new Vector2(
            safe.width / Screen.width,
            safe.height / Screen.height);
    }

    private void OnRectTransformDimensionsChange()
    {
        if (rectTransform != null)
            ApplySafeArea();
    }

    private void OnValidate()
    {
        if (rectTransform == null)
            rectTransform = GetComponent<RectTransform>();

        if (rectTransform != null)
            ApplySafeArea();
    }
}
Ready for more? Mobile Responsive UI Scaler Dynamically adjusts UI scaling based on device aspect ratio, DPI, and orientation.