← Назад к вопросам

Как сделать так, чтобы три View делили экран ровно на три части?

1.0 Junior🔥 112 комментариев
#SwiftUI#UIKit и верстка

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Распределение экрана на три равные части между UIView

Существует несколько подходов к равномерному распределению трех UIView по высоте или ширине экрана (или родительского контейнера). Основные методы реализуются через:

  • Auto Layout (современный, рекомендуемый способ)
  • Frame-based layout (математический расчет)
  • UIStackView (самый простой вариант для равномерного распределения)

1. Использование UIStackView (наиболее простой метод)

UIStackView автоматически управляет распределением своих subviews согласно заданным параметрам.

import UIKit

class ThreeEqualPartsViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Создаем три view с разными цветами для визуализации
        let redView = UIView()
        redView.backgroundColor = .red
        
        let greenView = UIView()
        greenView.backgroundColor = .green
        
        let blueView = UIView()
        blueView.backgroundColor = .blue
        
        // Создаем вертикальный stack view
        let stackView = UIStackView(arrangedSubviews: [redView, greenView, blueView])
        stackView.axis = .vertical // Распределение по вертикали
        stackView.distribution = .fillEqually // Ключевой параметр: равное заполнение
        stackView.alignment = .fill
        stackView.spacing = 0 // Убираем промежутки между view
        
        // Добавляем stack view на главный view и устанавливаем constraints
        view.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: view.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            stackView.leftAnchor.constraint(equalTo: view.leftAnchor),
            stackView.rightAnchor.constraint(equalTo: view.rightAnchor)
        ])
    }
}

Примечание: Для горизонтального распределения измените axis на .horizontal. Этот метод гарантирует точное равенство частей независимо от размеров экрана.

2. Использование Auto Layout с Constraints (без UIStackView)

Можно создать равные части путем установки прямых constraints между views.

import UIKit

class ThreeEqualPartsConstraintViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let view1 = UIView()
        view1.backgroundColor = .red
        let view2 = UIView()
        view2.backgroundColor = .green
        let view3 = UIView()
        view3.backgroundColor = .blue
        
        view.addSubview(view1)
        view.addSubview(view2)
        view.addSubview(view3)
        
        // Отключаем авто конвертацию масок в constraints
        [view1, view2, view3].forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
        
        // Вертикальное распределение: фиксируем верх и низ, связываем соседние view
        NSLayoutConstraint.activate([
            // Первое view: сверху к родителю, высота равна второму view
            view1.topAnchor.constraint(equalTo: view.topAnchor),
            view1.leftAnchor.constraint(equalTo: view.leftAnchor),
            view1.rightAnchor.constraint(equalTo: view.rightAnchor),
            view1.heightAnchor.constraint(equalTo: view2.heightAnchor),
            
            // Второе view: сверху к первому view, высота равна третьему view
            view2.topAnchor.constraint(equalTo: view1.bottomAnchor),
            view2.leftAnchor.constraint(equalTo: view.leftAnchor),
            view2.rightAnchor.constraint(equalTo: view.rightAnchor),
            view2.heightAnchor.constraint(equalTo: view3.heightAnchor),
            
            // Третье view: сверху к второму view, низ к родителю
            view3.topAnchor.constraint(equalTo: view2.bottomAnchor),
            view3.leftAnchor.constraint(equalTo: view.leftAnchor),
            view3.rightAnchor.constraint(equalTo: view.rightAnchor),
            view3.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }
}

Ключевой момент: Мы связали высоты view1.heightAnchor == view2.heightAnchor и view2.heightAnchor == view3.heightAnchor, что создает транзитивное равенство всех трех высот. Последнее view также прикреплено к bottomAnchor родителя, что фиксирует общую высоту.

3. Frame-based layout (для ручного расчета)

Это исторический подход, который менее гибкий, но может использоваться в специфических контекстах (например, в drawRect).

import UIKit

class ThreeEqualPartsFrameViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let totalHeight = view.bounds.height
        let partHeight = totalHeight / 3
        
        let view1 = UIView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: partHeight))
        view1.backgroundColor = .red
        
        let view2 = UIView(frame: CGRect(x: 0, y: partHeight, width: view.bounds.width, height: partHeight))
        view2.backgroundColor = .green
        
        let view3 = UIView(frame: CGRect(x: 0, y: partHeight * 2, width: view.bounds.width, height: partHeight))
        view3.backgroundColor = .blue
        
        view.addSubview(view1)
        view.addSubview(view2)
        view.addSubview(view3)
    }
    
    // Важно: пересчитать frames при изменении размеров (например, ротация)
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        
        let totalHeight = view.bounds.height
        let partHeight = totalHeight / 3
        
        view.subviews[0].frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: partHeight)
        view.subviews[1].frame = CGRect(x: 0, y: partHeight, width: view.bounds.width, height: partHeight)
        view.subviews[2].frame = CGRect(x: 0, y: partHeight * 2, width: view.bounds.width, height: partHeight)
    }
}

Критические рекомендации

  • UIStackView — предпочтительный метод для современных приложений: минимальный код, автоматическая адаптация, поддержка Dynamic Type и изменений ориентации.
  • При использовании Auto Layout напрямую важно убедиться, что все translatesAutoresizingMaskIntoConstraints установлены в false.
  • Для сложных сценариев (например, разные пропорции в портретной и landscape ориентации) можно комбинировать подходы или использовать UILayoutGuide как промежуточные анкеры.
  • Всегда учитывайте safe area insets на устройствах с "челкой": вместо view.topAnchor используйте view.safeAreaLayoutGuide.topAnchor.

Выбор метода зависит от контекста: для статических интерфейсов подойдет UIStackView, для динамических изменений — прямые constraints, для кастомной анимации или рисования — frame-based расчет с обновлением в viewWillLayoutSubviews.

Как сделать так, чтобы три View делили экран ровно на три части? | PrepBro