Я получил ViewController с кучей Labels, упорядоченных в 2 столбца (значения заголовка и описания). Все Labels являются дочерними элементами основного View. Я хочу, чтобы правый столбец с метками описания выровнялся по вертикали:

enter image description here

Моя первая попытка .

Я установил фиксированное ограничение ширины width = 180 для каждого Label левого столбца. Тогда каждый Label правого столбца имел ограничение для соответствующего Label слева от него. Это сработало и выглядело хорошо, но я получил предупреждение, от которого я хотел избавиться:

Фиксированные ограничения ширины могут вызывать отсечение

Моя вторая попытка .

Удалил все фиксированные ограничения ширины с левой стороны Labels, чтобы избавиться от предупреждения. Правая сторона больше не была выровнена. В viewDidLoad() я попытался установить все левые Labels ' размеры кадра на размер самого длинного Label (в моем случае «Некоторый длинный длинный текст»)

    shorterTitle.frame.size = longTitle.frame.size
    tinyTitle.frame.size = longTitle.frame.size

Это не оказало видимого влияния (левые ограничения правых меток не кажутся динамическими).

Моя третья попытка .

Я игнорировал разные размеры левой стороны Labels, но смотрел на те, что справа. Я проверяю положение x на правой стороне Label самой длинной левой стороны Label и устанавливаю эту позицию на все остальные правые стороны Labels:

    secondDes.frame.origin.x = firstDes.frame.origin.x
    thirdDes.frame.origin.x = firstDes.frame.origin.x

Это сработало нормально, но есть проблема:

Это не работает, если значение Labels пусто. В моем приложении они сначала пусты, а затем информация с правой стороны Labels загружается с веб-сервера.

Так что, если я сделаю это:

    secondDes.frame.origin.x = firstDes.frame.origin.x
    thirdDes.frame.origin.x = firstDes.frame.origin.x

    firstDes.text = "test1"
    secondDes.text = "test2"
    thirdDes.text = "test3"

Правая сторона не будет правильно выровнена.

Поэтому я изменил порядок, чтобы текст был задан первым, и поэтому Labels получают новый размер ширины в зависимости от их нового текста.

    firstDes.text = "test1"
    secondDes.text = "test2"
    thirdDes.text = "test3"

    secondDes.frame.origin.x = firstDes.frame.origin.x
    thirdDes.frame.origin.x = firstDes.frame.origin.x

Удивительно, но это тоже не работает. Причина в том, что текстовые атрибуты установлены, но к моменту выполнения последних двух строк размеры Labels еще не скорректированы. Поэтому мне пришлось бы немного подождать, пока не будут применены размеры, а затем снова вызвать две последние строки.

Если бы я сделал это, пользователь смог бы увидеть текстовый переход.

Надеюсь, у вас есть идея.

3
Rolf Wolf 3 Май 2019 в 14:57

3 ответа

Лучший ответ

Автопоставка должна быть лучшим подходом.
Относительно решения 1:
UDabel firstDes, secondDes и thirdDes выглядят как горизонтально отцентрированные. Если вы теперь установите ширину 160, у нее будут абсолютно перекрывающие / нарушающие ограничения.
IPhone 5s / LE будет иметь ширину 320. Если метка «Some long long text:» имеет ширину 180, он будет перекрывать метку «test1».

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

Если это ваш первый проект, я предлагаю вам взглянуть на некоторые учебники для Autolayout. (Рэй Вендерлих, например)

Изменить:
Предложение из комментариев. Используйте UIView в качестве контейнера. Поместите все UILabels туда и выровняйте их так, как вам нравится. UILabels "test2" и "test3" имеют LayoutContraints, который говорит им, что они имеют то же начало, что и "test1".
На рисунке 2 показаны ограничения, которые вы просматриваете в редакторе StoryBoard. Добавление их по коду менее тривиально, если вы не знакомы с Autolayout.

enter image description here enter image description here

1
Helge Becker 3 Май 2019 в 12:55

Как установить интерфейс из 1-го метода


  1. В вашем VC сначала возьмите Horizontal-StackView и дайте ему некоторые ограничения. Прямо сейчас я даю это

    • Leading, trailing - 10 (constant)
    • Вертикально от центра до вида Vc.
    • высота - 200 (постоянная) .. позже мы удалим это
  2. Сначала мы установим первый вид сверху, а затем повторим те же виды. Теперь добавим один вид в stackview. Скажи свое мнение1.

  3. Добавьте левую метку (labelLeft) в view1 и задайте для нее ограничение:

    • Ведущий, верхний, нижний - 5 (постоянный)
    • Ширина - 80 (постоянная) .. вы можете установить в соответствии с вашими потребностями
  4. Теперь установите среднюю метку (labelMid) для двоеточия (если вы не хотите этого, пропустите этот шаг) и задайте ограничение:

    • Ведущий к labelLeft - 5 (константа)
    • Сверху labelLeft
  5. Теперь установите правильную метку (labelRight) и задайте ограничения:

    • Ведущий к labelMid - 5 (константа)
    • Сверху labelLeft
    • Трейлинг - 5 (постоянный)
  6. Теперь установите количество строк каждой метки равным нулю (0) и удалите ограничение высоты стека. Установите текст в labelLeft и labelRight любой длины, какой вы хотели бы быть, и посмотрите на магию ниже.

Результаты .

Первый вывод (левая метка длиннее)

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

Второй выход (правая метка длиннее)

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

  1. Для нескольких представлений вы можете напрямую скопировать view1 и вставить его в stackView, как показано ниже.

enter image description here

Окончательный результат.

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

Фон фиолетового цвета является основным видом.

1
dahiya_boy 3 Май 2019 в 12:59

Если ваши данные статичны, вы должны использовать UIStackView. И если ваши данные являются динамическими, то UICollectionView является лучшим вариантом. В этом случае вы можете создать одну ячейку прототипа, содержащую вашу метку, а затем использовать dequeueReusableCell, чтобы использовать эту ячейку. Я надеюсь, что вы поняли, если у вас есть понимание UICollectionView.

0
Usama Azam 3 Май 2019 в 12:15