Как создать процент от общей ширины с помощью автоматического раскладки?

114

Мне нужно создать три динамических столбца, каждый с фиксированным процентом от общей ширины. Не трети, а разные значения. Например, на следующем рисунке показаны три столбца: первый - шириной 42%, второй - шириной 25%, а третий - шириной 33%.

Для 600 пикселей на контроллере представления это будет 252, 150 и 198 пикселей соответственно.

Однако для любых последующих размеров дисплея (например, iPhone 4 в альбомной ориентации (ширина 960) или iPad 2, портретная (ширина 768)), я хотел бы, чтобы относительные проценты были одинаковыми (не указанная выше ширина в пикселях).

Есть ли способ сделать это с помощью раскадровки (т.е. без кода)? Я могу легко сделать это в коде, но моя цель - поместить как можно больше этой логики отображения в раскадровку.

введите описание изображения здесь

Джеффри Бертьям
источник

Ответы:

205

Если, как вы говорите, вы знаете, как это сделать в коде, значит, вы уже знаете, как это сделать в раскадровке. Это точно такие же ограничения, но вы создаете их визуально, а не в коде.

  1. Выберите представление и его супервизор.

  2. Выберите Editor -> Pin -> Widths Equally, чтобы ограничить ширину равной ширине супервизора (на самом деле здесь лучше всего работает всплывающее диалоговое окно с булавкой внизу холста).

  3. Отредактируйте ограничение и установите множитель на желаемую дробь, например 0,42. То же самое и с другими взглядами.

матовый
источник
9
Убедитесь, что представление, которое вы ограничиваете, появляется в «первом элементе» ограничения Equal Widths Constraint, а не в ширине супервизора, в противном случае вы делаете ширину вашего подпредставления кратной ширине супервизора. При перетаскивании элемента управления из подпредставления в супервизор для применения ограничения равной ширины они всегда меняются местами, что мне кажется нелогичным.
memmons
Ах, под «делать это в коде» я имел в виду нечто большее, вроде «вручную, без ограничений или автоматического размещения».
Джеффри Бертьям,
Хороший ответ. Я удивлен, что IB не предоставляет способ сделать это без редактирования ограничения.
wcochran
Я попытался применить это в своем UITableViewCell, и все было серым. Мне пришлось встроить все мои представления в новое представление и выбрать «Ширина равно» в моем ярлыке для этого нового представления. Надеюсь, поможет.
nano
6
Новое в Xcode7: если вы хотите одинаково выровнять представления, используйте новое «представление стека».
Биджан
15

Когда Apple представила UIStackView, работа стала намного проще.

Метод 1: Использование пера / раскадровки:

Вам нужно просто добавить три представления в конструкторе интерфейса и встроить их в стек

Xcode ► Редактор ► Вставить ► StackView

введите описание изображения здесь

Выберите stackView и задайте ограничение с ведущей, конечной, верхней и равной высотой с помощью safeArea

Щелкните область инспектора атрибутов и установите StackView по горизонтали и распределению для пропорционального заполнения

[ введите описание изображения здесь3

Задайте ограничение трех видов с ведущими, замыкающими, верхними, нижними и соответствующими сторонами. введите описание изображения здесь

Метод 2: программно:

import UIKit
class StackViewProgramatically: UIViewController {
    var propotionalStackView: UIStackView!
    ///Initially defining three views
    let redView: UIView = {
        let view = UIView()//taking 42 % initially
        view.frame = CGRect(x: 0, y: 0, width: 42 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .red
        return view
    }()

    let greenView: UIView = {
        let view = UIView()//taking 42* initially
        view.frame = CGRect(x: 42 * UIScreen.main.bounds.width/100, y: 0, width: 25 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .green
        return view
    }()
    let blueView: UIView = {
        let view = UIView()//taking 33*initially
        view.frame = CGRect(x: 67 * UIScreen.main.bounds.width/100, y: 0, width: 33 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .blue
        return view
    }()

    ///Changing UIView frame to supports landscape mode.
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        DispatchQueue.main.async {
            self.redView.frame = CGRect(x: 0, y: 0, width: 42 * self.widthPercent, height: self.screenHeight)
            self.greenView.frame = CGRect(x: 42 * self.widthPercent, y: 0, width: 25 * self.widthPercent, height: self.screenHeight)
            self.blueView.frame = CGRect(x: 67 * self.widthPercent, y: 0, width: 33 * self.widthPercent, height: self.screenHeight)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        //Adding subViews to the stackView
        propotionalStackView = UIStackView()
        propotionalStackView.addSubview(redView)
        propotionalStackView.addSubview(greenView)
        propotionalStackView.addSubview(blueView)
        propotionalStackView.spacing = 0
        ///setting up stackView
        propotionalStackView.axis = .horizontal
        propotionalStackView.distribution = .fillProportionally
        propotionalStackView.alignment = .fill
        view.addSubview(propotionalStackView)
    }
}
//MARK: UIscreen helper extension
extension NSObject {

    var widthPercent: CGFloat {
        return UIScreen.main.bounds.width/100
    }

    var screenHeight: CGFloat {
        return UIScreen.main.bounds.height
    }
}

Вывод:

Работает с пейзажем и портретом

введите описание изображения здесь введите описание изображения здесь

Демо-проект - https://github.com/janeshsutharios/UIStackView-with-constraints

https://developer.apple.com/videos/play/wwdc2015/218/

разъем
источник
4

Я думаю, что это можно объяснить более подробно, чтобы его было легче применить к любому количеству представлений, требующих фиксированного процентного расположения в супервизоре.

Крайний левый вид

  • Привязан к SuperView.Leading
  • Определяет свой фиксированный процент как множитель на SuperView.Height

Промежуточные просмотры

  • Определяет свой фиксированный процент как множитель на SuperView.Height
  • Прикрепляет его leftсправа от соседа

Самый правый вид

  • Не определяет фиксированный процент (это остаток доступного представления)
  • Прикрепляет его leftсправа от соседа
  • Прикрепляет его rightкSuperView.Trailing

Все просмотры

  • Определите их нефиксированную высоту путем привязки к Top Layout Guide.Topи Top Layout Guide.bottom. В ответе выше отмечено, что это также можно сделать, установив равную высоту для соседнего вида.
JuJoDi
источник