Swift package that handles the annoying task of positioning UI elements around the iPhone's notch and Dynamic Island
Compatible with iOS 13.0 and later
NotchMyProblem is a lightweight Swift package that makes it easy to position buttons and other UI elements around the notch or Dynamic Island on modern iPhones. It automatically detects the device's top cutout and provides tools to create beautiful, adaptive layouts without the hassle of manual positioning.
- Go to File > Add Packages...
- Enter the repository URL:
https://github.com/Aeastr/NotchMyProblem
- Click "Add Package"
Alternatively, add it to your Package.swift
dependencies:
NotchMyProblem automatically detects the device type and adjusts the UI accordingly, ensuring your buttons are perfectly positioned regardless of the device model.
The simplest way to use NotchMyProblem is with the included TopologyButtonsView
:
import SwiftUI
import NotchMyProblem
struct MyView: View {
var body: some View {
ZStack {
// Your main content here
// Buttons positioned around the notch/island
TopologyButtonsView(
leadingButton: {
Button(action: { print("Left button tapped") }) {
Image(systemName: "gear")
}
},
trailingButton: {
Button(action: { print("Right button tapped") }) {
Text("Save")
}
}
)
}
}
}
This will automatically:
- Position buttons on either side of the notch/Dynamic Island on compatible devices
- Fall back to standard left/right positioning on devices without a notch
- Adjust the spacing based on the specific device model
Some devices report incorrect notch dimensions through the API. Overrides correct the reported values to match actual device dimensions, ensuring consistent UI across all devices.
NotchMyProblem provides several ways to customize how the notch/island area is handled:
// In your App's initialization
NotchMyProblem.globalOverrides = [
.series(prefix: "iPhone13", scale: 0.95, heightFactor: 1.0, radius: 27),
DeviceOverride(modelIdentifier: "iPhone14,3", scale: 0.8, heightFactor: 0.7)
]
// For specific use cases
NotchMyProblem.shared.overrides = [
DeviceOverride(modelIdentifier: "iPhone14,3", scale: 0.8, heightFactor: 0.7)
]
TopologyButtonsView(
leadingButton: { /* ... */ },
trailingButton: { /* ... */ }
)
.notchOverride(.series(prefix: "iPhone14", scale: 0.6, heightFactor: 0.6))
Overrides are applied in the following order (highest priority first):
- View-specific overrides (via
.notchOverride()
modifier) - Instance-specific exact model matches
- Instance-specific series matches
- Global exact model matches
- Global series matches
// For a specific device model
let override = DeviceOverride(
modelIdentifier: "iPhone14,3", // Exact model
scale: 0.8, // Width scale (0.8 = 80% of original width)
heightFactor: 0.7, // Height scale (0.7 = 70% of original height)
radius: 24 // Corner radius (for visualization)
)
// For all devices in a series
let seriesOverride = DeviceOverride.series(
prefix: "iPhone14", // All iPhone 14 models
scale: 0.75, // Width scale
heightFactor: 0.75, // Height scale
radius: 24 // Corner radius
)
If you need direct access to the notch/island dimensions:
// Get the raw exclusion rect (unmodified)
let rawRect = NotchMyProblem.exclusionRect
// Get the adjusted rect with any applicable overrides
let adjustedRect = NotchMyProblem.shared.adjustedExclusionRect
// Get a custom-adjusted rect with specific overrides
let customRect = NotchMyProblem.shared.adjustedExclusionRect(using: myOverrides)
NotchMyProblem uses a safe approach to access the device's notch/Dynamic Island information:
- It retrieves the exclusion area using Objective-C runtime features
- It safely checks for the existence of methods before calling them
- It applies device-specific adjustments based on the model identifier
- It provides fallbacks if the information cannot be retrieved
The package is designed to be robust against API changes and includes comprehensive logging to help diagnose any issues.
- Requires iOS 13.0 or later
- Supports all notched iPhones (X, XS, XR, 11, 12, 13 series)
- Supports Dynamic Island devices (iPhone 14 Pro and newer)
- Safely falls back on devices without notches
NotchMyProblem includes built-in logging that works across iOS versions:
- Uses
Logger
on iOS 14+ - Falls back to
os_log
on iOS 13 - Provides helpful debug information
To see logs, filter Console app output with subsystem: com.notchmyproblem
This project is released under the MIT License. See LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request. Before you begin, take a moment to review the Contributing Guide for details on issue reporting, coding standards, and the PR process.
If you like this project, please consider giving it a βοΈ
- This package uses private API information in a safe, non-invasive way, however use at your own risk considering app store rules
- Check out TopNotch which helped inspire this solution and provided valuable insights into working with the notch/Dynamic Island
Built with ππ±ποΈ by Aether