2016-07-16 3 views
-2

Я хочу поставить два вида в том же положении, используя «автоматический макет визуального формата» в Swift, как мне это сделать элегантным способом?Как поместить два вида в ту же позицию, используя «автоматический макет визуального формата»?

Мне удалось использовать NSLayoutConstraint, но я надеюсь, что все еще могу найти элегантный способ с использованием визуального формата.

Мой код с использованием NSLayoutConstraint:

NSLayoutConstraint(item: greenView, attribute: .Left, relatedBy: .Equal, toItem: redView, attribute: .Left, multiplier: 1.0, constant: 0).active = true 
     NSLayoutConstraint(item: greenView, attribute: .Top, relatedBy: .Equal, toItem: redView, attribute: .Top, multiplier: 1.0, constant: 0).active = true 
     NSLayoutConstraint(item: greenView, attribute: .Right, relatedBy: .Equal, toItem: redView, attribute: .Right, multiplier: 1.0, constant: 0).active = true 
     NSLayoutConstraint(item: greenView, attribute: .Bottom, relatedBy: .Equal, toItem: redView, attribute: .Bottom, multiplier: 1.0, constant: 0).active = true 
+1

Читая документы? Это не сайт «сделай мою работу для меня». Возьмите удар, чтобы сделать это самостоятельно, и если вы не можете заставить его работать, разместите здесь свой код, и мы поможем вам его отладить. –

+1

@ DuncanC Я не думаю, что это неуместный вопрос. Я работаю над этим. Я все еще работаю над этим прямо сейчас. Я не видел ни одного подобного вопроса, размещенного на SO, поэтому я разместил его. И я подумал, что это простой, достаточно ясный вопрос, что мне не нужно публиковать мой неправильный код. Я буду искать больше и выложить позже. – allenlinli

ответ

2

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

Я хотел бы предложить вам использовать макет якоря, как это:

override func viewDidLoad() { 
    super.viewDidLoad() 

    let redView = UIView() 
    redView.backgroundColor = .redColor() 
    redView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(redView) 

    let greenView = UIView() 
    greenView.backgroundColor = .greenColor() 
    greenView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(greenView) 

    let redHoriz = NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[redView]-20-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redHoriz) 

    let redVert = NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[redView]-50-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redVert) 

    // Set greenView to occupy same space as the redView 
    greenView.leftAnchor.constraintEqualToAnchor(redView.leftAnchor).active = true 
    greenView.rightAnchor.constraintEqualToAnchor(redView.rightAnchor).active = true 
    greenView.topAnchor.constraintEqualToAnchor(redView.topAnchor).active = true 
    greenView.bottomAnchor.constraintEqualToAnchor(redView.bottomAnchor).active = true 
} 

Визуального формата Язык позволяет выровнять части просмотров. Например, вы можете выровнять вершины дна двух видов, передав [.AlignAllTop, .AlignAllBottom] как аргумент optionsconstraintsWithFormat. Но вы можете выровнять только значения, которые перпендикулярны направлению визуального формата . Итак, если вы указываете горизонтальный макет, то вы можете выровнять вершины и нижние видов. Если вы указываете вертикальный макет, вы можете выровнять слева и права.

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

И, наконец, скрытие синего и желтого видов оставляет вас с желаемой настройкой.

VFL example

let redView = UIView() 
    redView.backgroundColor = .redColor() 
    redView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(redView) 

    let greenView = UIView() 
    greenView.backgroundColor = .greenColor() 
    greenView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(greenView) 

    let blueView = UIView() 
    blueView.translatesAutoresizingMaskIntoConstraints = false 
    blueView.backgroundColor = .blueColor() 
    blueView.hidden = true 

    view.addSubview(blueView) 

    let yellowView = UIView() 
    yellowView.translatesAutoresizingMaskIntoConstraints = false 
    yellowView.backgroundColor = .yellowColor() 
    yellowView.hidden = true 

    view.addSubview(yellowView) 

    let redHoriz = NSLayoutConstraint.constraintsWithVisualFormat("H:|-80-[redView]-80-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redHoriz) 

    let redVert = NSLayoutConstraint.constraintsWithVisualFormat("V:|-80-[redView]-80-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redVert) 

    let blueHorizVert = NSLayoutConstraint.constraintsWithVisualFormat("H:[redView][blueView]|", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: ["redView": redView, "blueView": blueView]) 
    NSLayoutConstraint.activateConstraints(blueHorizVert) 

    let yellowHorizVert = NSLayoutConstraint.constraintsWithVisualFormat("V:[redView][yellowView]|", options: [.AlignAllLeft, .AlignAllRight], metrics: nil, views: ["redView": redView, "yellowView": yellowView]) 
    NSLayoutConstraint.activateConstraints(yellowHorizVert) 

    let greenTopBottom = NSLayoutConstraint.constraintsWithVisualFormat("H:[greenView][blueView]|", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: ["greenView": greenView, "blueView": blueView]) 
    NSLayoutConstraint.activateConstraints(greenTopBottom) 

    let greenLeftRight = NSLayoutConstraint.constraintsWithVisualFormat("V:[greenView][yellowView]|", options: [.AlignAllLeft, .AlignAllRight], metrics: nil, views: ["greenView": greenView, "yellowView": yellowView]) 
    NSLayoutConstraint.activateConstraints(greenLeftRight) 

Таким образом, вы можете сделать это с ЛВЖ, но это не так элегантно. Я бы посоветовал вам использовать якоря.

+0

Благодарим вас за предоставление ответа. Я не знал, как использовать alignAnchor. Мне удалось с NSLayoutConstraint. Но я надеюсь, что все еще найду элегантный способ, используя формат автоматической компоновки. – allenlinli

+0

Только только NSConstraint вручную. Я добавил свой код в вопрос. Помогите мне открыть этот вопрос, пожалуйста: p – allenlinli

+0

Я понял способ сделать это с помощью VFL, но он * не изящный *. – vacawama

5

Я бы эхо what vacawama said in his excellent answer об использовании компоновки якорей. Это, вероятно, так же ясно и элегантно, как и у родного API, но учтите, что для него требуется iOS 9 и более поздние версии.

Для организации кода, я хотел бы предложить вместо того, чтобы искать terser кода, организовать свой код в методы и/или расширения, например:

extension UIView { 

    func constraintsAligningAllEdges(toView view2: UIView) -> [NSLayoutConstraint] { 

     return [ topAnchor.constraintEqualToAnchor(view2.topAnchor), 
       bottomAnchor.constraintEqualToAnchor(view2.bottomAnchor), 
       leadingAnchor.constraintEqualToAnchor(view2.leadingAnchor), 
       trailingAnchor.constraintEqualToAnchor(view2.trailingAnchor) ] 
    } 
} 

Используя это будет выглядеть следующим образом :

NSLayoutConstraint.activateConstraints(greenView.constraintsAligningAllEdges(toView: redView)) 

... или, возможно, это расширение функции класса для NSLayoutConstraint.

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

let views = ["greenView" : greenView, "redView" : redView] 

NSLayoutConstraint.activateConstraints(
    NSLayoutConstraint.constraintsWithVisualFormat("H:[greenView]-([email protected])-[redView]", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: views) + 
    NSLayoutConstraint.constraintsWithVisualFormat("V:[greenView]-([email protected])-[redView]", options: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views) 
) 

Что я сделал здесь вместо введения дополнительных взглядов, я ввел два лишних ограничений, один между зеленой нижней & красным верхом, другой между зеленым trailing & верхний ведущий. Они оба имеют самый низкий приоритет 1, так как обычно у вас есть другие ограничения, определяющие размер/положение любого вида, они не должны причинять никакого вреда.

Это несколько более элегантный? Я не знаю, но лично я думаю, что привязки компоновки имеют больше смысла для меня, а сторонние структуры, такие как SnapKit, также являются прекрасными вариантами.

+0

Отлично. Отличный ответ. – vacawama

+1

Это дало мне еще одну идею. Вы можете использовать 'constraints.filter {$ 0.priority! = 1}', чтобы полностью удалить эти дополнительные ограничения, прежде чем активировать их. – vacawama

+0

Это потрясающие парни! Это будет '' ' NSLayoutConstraint.activateConstraints ( NSLayoutConstraint.constraintsWithVisualFormat ("H: [Greenview] - (0 @ 1) - [redView]", опции: [.AlignAllTop, .AlignAllBottom], метрики: nil, views: views) .filter {$ 0.priority! = 1} + NSLayoutConstraint.constraintsWithVisualFormat ("V: [greenView] - (0 @ 1) - [redView]", опции: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views) .filter {$ 0.priority! = 1} ) '' ' – allenlinli

 Смежные вопросы

  • Нет связанных вопросов^_^