Получите одинаковый пользовательский интерфейс для всех экранов iPhone, используя масштабирование NSLayoutConstraint
17 апреля 2022 г.Часто пользовательский интерфейс iOS-приложений предназначен только для экранов одного размера. Например, iPhone X (375x812) или iPhone 13 (390x844), а затем разработчики iOS делают дизайны для экранов других размеров.
С большими экранами все просто. А вот разместить дизайн iPhone X на экране iPhone SE 2016 (1-го поколения) сложнее, некоторые элементы и отступы приходится уменьшать вручную.
Пример дизайна экрана для iPhone 13:
🥲 Как это выглядит на разных экранах:
🙂 Результат с масштабированием пользовательского интерфейса:
Как масштабировать — простая реализация
Мы проходим через иерархию UIView и масштабируем (почти) все ограничения.
```цельc
расширение UIView {
func callRecursively(level: Int = 0, _ body: (_ subview: UIView, _ level: Int) -> Void) {
тело (я, уровень)
subviews.forEach { $0.callRecursively(уровень: уровень + 1, тело)}
функция масштаба () {
// 390 — это ширина экрана iPhone 13
вар масштабный фактор = мин (UIScreen.main.bounds.width / 390, 1)
callRecursively { (подвид, уровень) в
// чтобы избежать масштабирования системных ограничений
уровень охраны != 0 иначе { возврат }
для ограничения в subview.constraints {
если ограничение.константа!= 0 {
ограничение.константа = CGFloat(ограничение.константа) * коэффициент масштабирования
```цельc
класс ViewController: UIViewController {
переопределить функцию viewDidLoad() {
super.viewDidLoad()
// достаточно одной строки
вид.масштаб()
А теперь давайте немного усложним задачу для нерастянутых экранов
```цельc
func scale(kFor5: CGFloat? = nil, kFor8: CGFloat? = nil) {
// 390 — это ширина экрана iPhone 13
// 375 для iPhone Х
// и 320 для iPhone SE 2016 (1-го поколения)
вар масштабный фактор = мин (UIScreen.main.bounds.width / 390, 1)
если пусть kFor5 = kFor5,
UIScreen.main.bounds.width <= 320 {
масштабный коэффициент = масштабный коэффициент * kFor5
} иначе, если пусть kFor8 = kFor8,
UIScreen.main.bounds.width <= 375,
UIScreen.main.bounds.height <= 667 {
масштабный коэффициент = масштабный коэффициент * kFor8
callRecursively { (подвид, уровень) в
// чтобы избежать масштабирования системных ограничений
уровень охраны != 0 иначе { возврат }
если пусть label = subview как? UILabel {
label.scaleFont(масштабныйКоэффициент)
} else if let button = subview as? UIButton {
button.scaleFont(масштабныйфактор)
для ограничения в subview.constraints {
если ограничение.константа!= 0 {
ограничение.константа = CGFloat(ограничение.константа) * коэффициент масштабирования
```цельc
расширение UILabel {
func scaleFont(_ k: CGFloat) {
пусть fontSize = font.pointSize
шрифт = font.withSize (размер шрифта * k)
```цельc
расширение UIButton {
func scaleFont(_ k: CGFloat) {
пусть fontSize: Double = Double (titleLabel?.font.pointSize ?? 0.0)
titleLabel?.font = titleLabel?.font.withSize(fontSize * k)
```цельc
класс ViewController: UIViewController {
переопределить функцию viewDidLoad() {
super.viewDidLoad()
// вы можете поиграть с этими факторами для достижения наилучших результатов
view.scale(kFor5: 0,75, kFor8: 0,85)
Спасибо за чтение!
Это все. Пожалуйста, напишите, если у вас есть какие-либо комментарии, я почти уверен, что это можно улучшить дальше. Также, пожалуйста, дайте мне знать, если вы решили подобную проблему.
Оригинал