Откуда этот вертикальный интервал в UILabelView?

Я создаю представление iOS, которое отображает различные статические текстовые элементы. XIB выглядит следующим образом:

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

Он использует четыре метки для заголовка, метки времени, тела и нижнего колонтитула. Каждое представление привязывается к родственному представлению над ним по вертикали и привязывается слева/справа от родительского представления. Все метки имеют фиксированную высоту, за исключением тела, которое имеет высоту >= и количество строк, установленное на 0, с «переносом слов» в качестве стиля переноса строк. Родительским представлением является UIScrollView.

На айфоне вроде нормально:

iPhone начало прокруткиКонец прокрутки iPhone

Однако на iPad это выглядит так:

iPad начало прокруткиiPad конец прокрутки

Хм? Откуда берется все это дополнительное вертикальное пространство в этикетке тела? Xib и его контроллер представления идентичны между iPhone и iPad (на данный момент нет специального кода для iPad). Я обнаружил, что вертикальное пространство напрямую связано с количеством переносов строк, отображаемых меткой. Если строки не переносятся, нет дополнительного вертикального пространства. Если переносятся только несколько строк, появляется небольшое дополнительное пространство по вертикали. Если почти каждая строка переносится, что ж, вот как это выглядит.

Прежде всего, есть идеи, почему UILabel ведет себя таким образом?

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

Я уже пробовал несколько вещей. Если я вызову [bodyLabel sizeToFit] внутри -viewDidLayoutSubViews, тогда он исправит метку, но не исправит макет любого из одноуровневых представлений (например, метка нижнего колонтитула застревает в нижней части экрана, а не поднимается прямо под ним). тело). Любые попытки заставить все представление переразметить своих дочерних элементов после вызова sizeToFit игнорируются. Я также попытался определить размер UILabel, вычислив высоту на основе шрифта, что приводит к тому же поведению, что и -sizeToFit (хотя и с большим количеством кода).

Вместо этого замена Body UILabel на UITextView не дает мне странных проблем с вертикальным интервалом, но мне нужно вычислить высоту UITextView вручную (с использованием вычислений шрифта) и что-то об изменении размера UITextView в родительском UIScrollView делает так, чтобы UIScrollView просто отказывается прокручиваться (как будто он не знает, что его содержимое слишком велико для его границ).

Так что на данный момент я застрял. Было бы полезно даже просто объяснить, почему UILabel ведет себя таким образом на макете iPad.


person Brandon    schedule 03.09.2013    source источник
comment
Вы используете Autolayout или Springs and Struts?   -  person CoderPug    schedule 04.09.2013
comment
Я использую Autolayout. Я могу опубликовать ограничения, если хотите. Я попытался объяснить соответствующие ограничения в первом абзаце.   -  person Brandon    schedule 04.09.2013
comment
Посмотрите на меня, что проблемы заключаются в ограничениях, если использование [bodyLabel sizeToFit] провоцирует то, что нижний колонтитул застревает внизу, вам нужно проверить свои ограничения, вероятно, есть одни, чтобы поместить нижний колонтитул внизу, и другие, которые заставляют вашу метку Body растягиваться по вертикали .   -  person CoderPug    schedule 04.09.2013
comment
В настоящее время похоже, что IB чрезмерно ограничивает нижний колонтитул. У меня есть ограничение слева и справа для родительского представления, ограничение сверху между меткой тела и меткой нижнего колонтитула и ограничение фиксированной высоты. Этого должно быть достаточно для нижнего колонтитула, верно? Слева, справа, сверху, по высоте. Однако IB настаивает на наличии нижнего ограничения между нижним колонтитулом и родительским представлением. На данный момент для него установлено значение «Авто» вместо фиксированного значения, но дело в том, что мне не должно нужно это ограничение. Однако он остается неустранимым. Есть идеи?   -  person Brandon    schedule 04.09.2013
comment
Я думаю, что есть еще проблема с пробелами. Если я заменю текст lorum ipsum, скажем, серией отдельных предложений, которые не переносятся, проблема пробелов исчезнет. Похоже, что UILabel добавляет пробел прямо пропорционально тому, как часто он переносит текстовую строку. Без переноса текста, без лишнего пробела (даже если текст по-прежнему состоит из сотен строк). На это поведение не влияет изменение поведения переноса строки.   -  person Brandon    schedule 04.09.2013
comment
нижнее ограничение между нижним колонтитулом и родительским представлением Я думаю, что проблема заключается в ограничениях, попробуйте присвоить этому второстепенный приоритет, также, если у вас установлено отношение «Равно», измените его на « Вместо этого больше или равно». надеюсь, это поможет   -  person CoderPug    schedule 04.09.2013
comment
К сожалению, любое изменение этого ограничения вынуждает IB также повторно добавлять исходное статическое ограничение. Итак, теперь у меня есть два нижних ограничения нижнего колонтитула, одно из которых я не могу изменить. IB считает, что этот ярлык по какой-то причине недостаточно ограничен, но я не могу понять, почему. Я указываю верх, лево, право и высоту! Нет ничего невыясненного! Очевидно, что autolayout считает иначе, но я не могу понять, как это обойти.   -  person Brandon    schedule 05.09.2013


Ответы (2)


Основная проблема заключается в том, что метод автоматического изменения размера текста внутри вашей метки не работает, потому что в iPad ваша метка не имеет заданной ширины с самого начала, она рассчитывается во время выполнения, и это источник этого беспорядка. На айфоне, т.к. ваша метка имеет заданную ширину (на ИБ) проблем нет.

Есть два пути решения проблемы:

  1. Две раскадровки: одна для iPhone и одна для iPad

    Это сделает так, что ваша метка будет знать свою ширину с самого начала, и она будет работать так же, как на iPhone. введите здесь описание изображения

  2. Наличие только одной раскадровки для iPhone и iPad

    Вы можете обойти эту проблему, рассчитав размер, который лучше всего соответствует его тексту, и с этим результатом добавьте ограничение по высоте с помощью кода в метку. Для расчета желаемого размера вы можете рассчитать ширину по этой формуле: Current View's width - (Leading space + Trailing Space). Вот мой код

CGSize desiredSize = [_bodyLabel sizeThatFits:CGSizeMake(self.view.frame.size.width-40, 10)];
NSString *visualContraint = [NSString stringWithFormat:@"V:[_bodyLabel(%.0f)]",desiredSize.height];
[_bodyLabel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualContraint
                                                                   options:NSLayoutFormatDirectionLeadingToTrailing
                                                                   metrics:nil
                                                                     views:NSDictionaryOfVariableBindings(_bodyLabel)]];

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

objective-c

person CoderPug    schedule 05.09.2013

На случай, если кто-то еще столкнется с той же проблемой, используя авторазметку... Я, возможно, смог решить ту же проблему, создав ограничение, как предлагает Коче, но я понял, что у меня есть preferredMaxLayoutWidth, который слишком мал для ulabel. Как только я установил точную preferredMaxLayoutWidth (фактическая ширина этикетки), расстояние сверху и снизу исчезло.

person ccwasden    schedule 03.04.2014
comment
Это правильный/предпочтительный ответ ИМХО. Он не требует обходного кода (чем меньше кода пользовательского интерфейса, тем лучше при выборе маршрута Auto-Layout + IB). Это исправило мою проблему. - person Form; 10.11.2015