У меня есть UITextView
в моем приложении iOS, которое отображает большое количество текста.
Затем я разбил этот текст на страницы с помощью параметра смещения поля UITextView
.
Моя проблема в том, что отступы UITextView
запутывают мои расчеты, так как они кажутся разными в зависимости от размера шрифта и используемого шрифта.
Поэтому я задаю вопрос: возможно ли удалить отступы, окружающие содержимое UITextView
?
С нетерпением ждем ваших ответов!
ios
iphone
cocoa-touch
uikit
uitextview
sniurkst
источник
источник
Ответы:
Обновленный на 2019 год
Это одна из самых глупых ошибок в iOS.
Класс, данный здесь,
UITextViewFixed
обычно является наиболее разумным решением в целом.Вот класс:
Не забудьте отключить scrollEnabled в Инспекторе!
Решение работает правильно в раскадровке
Решение работает правильно во время выполнения
Вот и все, вы сделали.
В общем, это должно быть все, что вам нужно в большинстве случаев .
Даже если вы изменяете высоту текстового представления на лету ,
UITextViewFixed
обычно делает все, что вам нужно.(Типичным примером изменения высоты на лету является изменение ее по типу пользователя.)
Вот сломанный UITextView от Apple ...
Вот
UITextViewFixed
:Обратите внимание, что, конечно, вы должны
отключите scrollEnabled в Инспекторе!
Не забудьте отключить scrollEnabled! :)
Некоторые дальнейшие проблемы
(1) В некоторых необычных случаях - например, в некоторых случаях таблиц с гибкими, динамически изменяющимися высотами ячеек - Apple делает странную вещь: они добавляют дополнительное пространство внизу . Нет, правда! Это должно быть одной из самых ярких вещей в iOS.
Вот «быстрое решение», которое можно добавить к вышесказанному, что обычно помогает с этим безумием.
(2) Иногда, чтобы исправить еще одну тонкую ошибку Apple, вы должны добавить это:
(3) Возможно, мы должны добавить:
только после того, как
.lineFragmentPadding = 0
вUITextViewFixed
.Однако ... верьте или нет ... это просто не работает в текущей iOS! (Проверено в 2019.) Возможно, потребуется добавить эту строку в будущем.
Тот факт, что
UITextView
это не работает в iOS, является одной из самых странных вещей во всех мобильных вычислениях. Десятилетие этого вопроса, и он до сих пор не решен!Наконец, вот несколько похожий совет для текстового поля : https://stackoverflow.com/a/43099816/294884
Совершенно случайный совет: как добавить «...» в конец
Часто вы используете UITextView "как UILabel". Таким образом, вы хотите усечь текст с помощью многоточия "..."
Если это так, добавьте третью строку кода в «настройку»:
Полезный совет, если вы хотите нулевую высоту, когда нет текста вообще
Часто вы используете текстовое представление только для отображения текста. Таким образом, пользователь не может ничего редактировать. Вы используете строки "0", чтобы обозначить, что текстовое представление автоматически изменит высоту в зависимости от того, сколько строк текста.
Это здорово, но если текста нет вообще, то, к сожалению, вы получите ту же высоту, как если бы была одна строка текста !! Текстовое представление никогда не «уходит».
Если вы хотите, чтобы он "ушел", просто добавьте это
(Я сделал это «1», поэтому ясно, что происходит, «0» - это хорошо.)
А как насчет UILabel?
Просто отображая текст, UILabel имеет много преимуществ по сравнению с UITextView. UILabel не страдает от проблем, описанных на этой странице QA. Действительно, причина, по которой мы все обычно «сдаемся» и просто используем UITextView, заключается в том, что с UILabel трудно работать. В частности, до смешного трудно просто добавить отступы в UILabel. На самом деле, здесь подробно обсуждается, как «наконец» правильно добавить заполнение в UILabel: https://stackoverflow.com/a/58876988/294884 В некоторых случаях, если вы делаете сложный макет с динамическими ячейками высоты, иногда лучше сделать это нелегко с UILabel.
источник
self.textView.isScrollEnabled = false
внутри,viewDidLayoutSubviews()
и это тоже сработало. Apple просто нравится заставлять нас прыгать через обручи :)translatesAutoresizingMaskIntoConstraints
. Только с этим ответом я не смог удалить все поля (какой-то странный нижний отступ, чтобы не уходить) в иерархии представления, используя автоматическое расположение. Он также имеет дело с вычислением размеров представленийsystemLayoutSizeFitting
, которые ранее возвращали неверный размер из-за ошибкиUITextView
Для iOS 7.0 я обнаружил, что трюк contentInset больше не работает. Это код, который я использовал, чтобы избавиться от полей / отступов в iOS 7.
Это приводит левый край текста к левому краю контейнера:
Это приводит к тому, что верх текста выравнивается по верху контейнера.
Обе строки необходимы для полного удаления полей / отступов.
источник
self.descriptionTextView.textContainerInset = UIEdgeInsetsZero;
lineFragmentPadding
в 0 это магия, которую я искал. Я понятия не имею, почему Apple так сложно выровнять контент UITextView с другими элементами управления.lineFragmentPadding
не предназначен для изменения полей. Из документов Заполнение фрагмента строки не предназначено для выражения текстовых полей. Вместо этого вы должны использовать вставки в текстовом представлении, настроить атрибуты полей абзаца или изменить положение текстового представления в его суперпредставлении.Этот обходной путь был написан в 2009 году, когда была выпущена IOS 3.0. Это больше не применяется.
Я столкнулся с точно такой же проблемой, в конце концов мне пришлось закончить с помощью
где nameField является
UITextView
. Я использовал шрифт Helvetica 16 пунктов. Это единственное нестандартное решение для конкретного размера поля, которое я рисовал. Это делает левое смещение заподлицо с левой стороной, а верхнее смещение там, где я хочу, для поля, в котором оно нарисовано.Кроме того, это, кажется, относится только к тому,
UITextViews
где вы используете aligment по умолчанию, т.е.Например
UIEdgeInsetsMake
, выровняйте по правому краю, и кажется, что оно никак не влияет на правый край.По крайней мере, использование свойства .contentInset позволяет размещать поля с «правильными» позициями и учитывать отклонения, не компенсируя ваши
UITextViews
.источник
Опираясь на некоторые хорошие ответы, которые уже даны, мы предлагаем решение на основе исключительно Storyboard / Interface Builder, которое работает в iOS 7.0+.
Установите пользовательские атрибуты времени выполнения UITextView для следующих ключей:
источник
На iOS 5
UIEdgeInsetsMake(-8,-8,-8,-8);
вроде бы отлично работает.источник
Я бы определенно избегал любых ответов, связанных с жестко заданными значениями, поскольку фактические поля могут изменяться в зависимости от настроек размера шрифта пользователя и т. Д.
Вот ответ @ user1687195, написанный без изменения
textContainer.lineFragmentPadding
(поскольку в документе указано, что это не является предполагаемым использованием).Это прекрасно работает для iOS 7 и более поздних версий.
Это фактически тот же результат, только немного чище, поскольку он не использует свойство lineFragmentPadding.
источник
self.textView.textContainer.lineFragmentPadding = 0;
lineFragmentPadding
не предназначен для контроля наценок. Вот почему вы должны использоватьtextContainerInset
.Решение Storyboard или Interface Builder с использованием пользовательских атрибутов времени выполнения :
Скриншоты из iOS 7.1 и iOS 6.1 с
contentInset = {{-10, -5}, {0, 0}}
.источник
Все эти ответы касаются заглавного вопроса, но я хотел предложить некоторые решения проблем, представленных в основной части вопроса ОП.
Размер текстового содержимого
Быстрый способ рассчитать размер текста внутри
UITextView
- это использоватьNSLayoutManager
:Это дает общий прокручиваемый контент, который может быть больше, чем
UITextView
фрейм. Я обнаружил, что это гораздо точнее, чемtextView.contentSize
вычисление того, сколько места занимает текст. Например, дано пустоеUITextView
:Высота линии
UIFont
имеет свойство, которое позволяет быстро получить высоту строки для данного шрифта. Таким образом, вы можете быстро найти высоту строки текста в вашемUITextView
:Расчет видимого размера текста
Определение объема фактически видимого текста важно для обработки эффекта «подкачки».
UITextView
имеет свойство с именем,textContainerInset
которое на самом деле является границей между фактическимUITextView.frame
и самим текстом. Для расчета реальной высоты видимой рамки вы можете выполнить следующие расчеты:Определение размера подкачки
Наконец, теперь, когда у вас есть видимый размер текста и содержание, вы можете быстро определить, какими должны быть ваши смещения, вычитая
textHeight
изtextSize
:Используя все эти методы, я не трогал свои вкладыши и мог перейти к каретке или куда угодно в тексте, который я хочу.
источник
Вы можете использовать
textContainerInset
свойствоUITextView
:textView.textContainerInset = UIEdgeInsetsMake (10, 10, 10, 10);
(верхний левый нижний правый)
источник
textContainerInset
свойства не работает для меня, когда я хочу изменить его на новое значение - см. Stackoverflow.com/questions/19422578/… .Для iOS 10 следующая строка работает для удаления верхнего и нижнего отступов.
источник
UIEdgeInset.zero
работает с использованием симулятора XCode 8.3 и iOS 10.3Последний Свифт:
источник
Вот обновленная версия очень полезного ответа Фэтти. Он добавляет 2 важные строки, которые помогли мне заставить работать макет на iOS 10 и 11 (и, вероятно, на более низких):
Важные строки - это два
translatesAutoresizingMaskIntoConstraints = <true/false>
утверждения!Это удивительно удаляет все поля при всех моих обстоятельствах!
Хотя
textView
респондент не первый, может случиться так, что есть какой-то странный нижний предел, который не может быть решен с помощьюsizeThatFits
метода, который упомянут в принятом ответе.При нажатии на textView внезапно исчезло странное нижнее поле, и все выглядело так, как должно, но только после того, как textView получил
firstResponder
.Итак, я прочитал здесь о SO, что включение и отключение
translatesAutoresizingMaskIntoConstraints
действительно помогает при ручной настройке фрейма / границ между вызовами.К счастью, это работает не только с настройкой кадра, но и с двумя линиями,
setup()
расположенными между двумяtranslatesAutoresizingMaskIntoConstraints
вызовами!Это, например, очень полезно при расчете фрейма вида с использованием
systemLayoutSizeFitting
aUIView
. Возвращает правильный размер (чего раньше не было)!Как упоминалось в оригинальном ответе:
не забудьте отключить scrollEnabled в Инспекторе!
Это решение работает правильно как в раскадровке, так и во время выполнения.
Вот и все, теперь вы действительно сделали!
источник
Для swift 4, Xcode 9
Используйте следующую функцию, чтобы изменить поле / отступ текста в UITextView.
так что в этом случае
источник
Делая решение для врезки, у меня все еще была прокладка справа и снизу. Также выравнивание текста вызывало проблемы. Единственный надежный способ, который я нашел, - это поместить текстовое представление в другое представление, обрезанное до границ.
источник
Вот небольшое простое расширение, которое удалит поля Apple по умолчанию из каждого текстового представления в вашем приложении.
Примечание. Интерфейсный конструктор по-прежнему будет отображать старое поле, но ваше приложение будет работать так, как ожидается.
источник
Для меня (iOS 11 и Xcode 9.4.1) волшебным образом было настроить свойство textView.font для
UIFont.preferred(forTextStyle:UIFontTextStyle)
стиля, а также первый ответ, упомянутый @Fattie. Но ответ @Fattie не сработал, пока я не установил свойство textView.font, иначе UITextView продолжает работать беспорядочно.источник
Если кто-то ищет последнюю версию Swift, то приведенный ниже код работает нормально с Xcode 10.2 и Swift 4.2
источник
Я нашел еще один подход: получить представление с текстом из подпредставлений UITextView и настроить его в методе layoutSubview подкласса:
источник
Прокрутка textView также влияет на положение текста и делает его не центрированным по вертикали. Мне удалось отцентрировать текст в представлении, отключив прокрутку и установив верхнюю вставку в 0:
По какой-то причине я еще не понял, курсор все еще не центрирован до начала набора, но текст центрируется сразу же, как я начинаю печатать.
источник
Если вы хотите установить строку HTML и избежать нижнего заполнения, убедитесь, что вы не используете теги блока, т.е. div, p.
В моем случае это было причиной. Вы можете легко проверить это, заменив вхождения тегов блока, например, тегом span.
источник
Для SwiftUI
Если вы делаете свой собственный TextView, используя
UIViewRepresentable
и хотите управлять заполнением, в своейmakeUIView
функции просто выполните:uiTextView.textContainerInset = UIEdgeInsets(top: 10, left: 18, bottom: 0, right: 18)
или что хочешь.
источник
источник