Использование пользовательского шрифта в UITextField заставляет его слегка сдвигаться при доступе - есть ли исправление?
У меня есть пользовательский шрифт в UITextField, и я заметил, что когда он открывается (когда появляется клавиатура), текст сдвигается на очень небольшую величину - может быть, пиксель или два или три. (Разумеется, я не могу ее измерить, но мне это достаточно, чтобы заметить). И затем, когда клавиатура отклоняется, она снова возвращается обратно.
Я попытался очистить поле при редактировании (которое скрывает проблему начального сдвига вниз), но оно не решило проблему. Я также рассмотрел различные атрибуты в IB и попытался изменить несколько, но проблема все еще сохраняется. Я получаю те же результаты в симуляторе и на своем iPad2.
(Поле хорошо видно из клавиатуры, поэтому не весь вид перемещается в сторону - это просто содержимое этого конкретного текстового поля.)
Я уверен, что это пользовательский шрифт, который вызывает проблему, - без него.
Любая идея, как решить эту проблему? Я думал, что мне может понадобиться создать текстовое поле программно, а не в IB - и я знаю, что, вероятно, мне следовало бы попробовать это, прежде чем задавать этот вопрос здесь, но я не могу пойти на все эти проблемы, если это не будет решить проблему.
Любые советы оценены!
Ответы
Ответ 1
У меня была и эта проблема.
Чтобы исправить, подкласс UITextField
и реализовать следующие методы для настройки позиционирования текста при редактировании и редактировании.
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectInset( bounds , 8 , 8 );
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectInset( bounds , 8 , 5 );
}
Ответ 2
Мое решение - это те же линии, что и McDJ, но с немного отличающимся твистом. Подкласс UITextField и переопределить только следующие:
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
return CGRectOffset( [self editingRectForBounds:bounds], 0, 2 );
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectOffset( [super editingRectForBounds:bounds], 0, -2 );
}
С помощью пользовательского шрифта, который я использую, 2 точки - это правильная вертикальная настройка, помогающая заполнителю, "статический" и "редактирующий" текст остаются на одной вертикальной линии.
Ответ 3
К сожалению, ни один из ответов не работал у меня.
Ответ на @blackjacx работал, но только иногда: (
Я начал отлаживать, и вот что я обнаружил:
1 - Реальная проблема, похоже, связана с закрытым подзаголовком UITextField типа UIFieldEditorContentView
![UITextField view hieararchy]()
Ниже вы можете видеть, что y
этого subview не совпадает с самим UITextField
:
![Y не установлен в 0]()
Поняв это, я вышел со следующим обходным путем:
override func layoutSubviews() {
super.layoutSubviews()
fixMisplacedEditorContentView()
}
func fixMisplacedEditorContentView() {
if #available(iOS 10, *) {
for view in subviews {
if view.bounds.origin.y < 0 {
view.bounds.origin = CGPoint(x: view.bounds.origin.x, y: 0)
}
}
}
}
Вам нужно будет подклассом UITextField
и переопределить layoutSubviews
, чтобы добавить возможность вручную установить 0
y
любого подзаголовка, установленного на отрицательное значение. Поскольку эта проблема не возникает с iOS 9 ниже, я добавил проверку, чтобы сделать обходной путь только тогда, когда он находится на iOS 10.
Результат, который вы можете увидеть ниже:
![Работаем правильно]()
2 - Это обходное решение не работает, если пользователь выбирает подменю текста (selectAll отлично работает)
Поскольку выбор текста не является обязательным для моего приложения, я скорее отключу его. Для этого вы можете использовать следующий код (Swift 3):
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if #available(iOS 10, *) {
if action == #selector(UIResponderStandardEditActions.select(_:)) {
return false
}
}
return super.canPerformAction(action, withSender: sender)
}
Ответ 4
Работает для всех размеров шрифтов и не вызывает выравнивания с clearButton
.
Подкласс UITextField
и переопределить их следующим образом:
- (CGRect)placeholderRectForBounds:(CGRect)bounds
{
return CGRectOffset( bounds, 0, 4 );
}
- (CGRect)editingRectForBounds:(CGRect)bounds
{
return CGRectOffset( bounds, 0, 2);
}
- (CGRect)textRectForBounds:(CGRect)bounds
{
return CGRectOffset( bounds , 0 , 4 );
}
Ответ 5
По странной причине я действительно не понял, что решил это, установив autoAdjustsScrollViewInsets в NO (или эквивалент в Interface Builder). Это с iOS 8.1.
Ответ 6
У меня была эта проблема с пользовательским шрифтом и была решена, сдвинув ярлык в другом направлении, когда будут происходить события клавиатуры. Я переместил центр метки в кнопку, переопределив метод drawRect:
- (void)drawRect:(CGRect)rect
{
self.titleLabel.center = CGPointMake(self.titleLabel.center.x, self.titleLabel.center.y+3);
}
Ответ 7
Это ожидаемое поведение в стандартном UITextField. Однако вы можете решить это путем подкласса UITextField и путем настройки границ для самого текста.
Swift 3
override func textRect(forBounds bounds: CGRect) -> CGRect {
return(bounds.insetBy(dx: 0, dy: 0))
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return(bounds.insetBy(dx: 0, dy: -0.5))
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return(bounds.insetBy(dx: 0, dy: 0))
}
Это должно сделать трюк!
Ответ 8
Установите ваши текстовые поля Border Style на любое значение, кроме "none" в IB, а затем в вашем ViewController viewDidLoad установите:
yourTextField.borderStyle = .none
(Основано на этом ответе от Box Jeon)
Ответ 9
Swift 3
Не забывайте accessory views
UITextField. Вам нужно будет указать super
функций * rect (forBounds:...), если вы хотите выполнить рабочую реализацию. И будьте также уверены, что только вытесните прямоугольники для багги iOS 10
, а не для 9 или 8! Следующий код должен сделать трюк:
public class CustomTextField: UITextField {
public override func textRect(forBounds bounds: CGRect) -> CGRect {
let superValue = super.textRect(forBounds: bounds)
if #available(iOS 10, *) {
return superValue.insetBy(dx: 0, dy: 0)
}
return superValue
}
public override func editingRect(forBounds bounds: CGRect) -> CGRect {
let superValue = super.editingRect(forBounds: bounds)
if #available(iOS 10, *) {
return superValue.insetBy(dx: 0, dy: -0.5)
}
return superValue
}
public override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
let superValue = super.placeholderRect(forBounds: bounds)
if #available(iOS 10, *) {
if isEditing {
return superValue.insetBy(dx: 0, dy: 0.5)
}
return superValue.insetBy(dx: 0, dy: 0.0)
}
return superValue
}
}
ИЗМЕНИТЬ
Я немного изменил свой код сверху до следующего, и он работает лучше для меня. Я тестирую его на iPhone 6, 6s, 7, 7s, а также на устройствах "плюс" с iOS 9.3 и 10.3.
public class CustomTextField: UITextField {
public override func textRect(forBounds bounds: CGRect) -> CGRect {
let superValue = super.textRect(forBounds: bounds)
if #available(iOS 10, *) {
return superValue.insetBy(dx: 0, dy: -0.3)
}
return superValue.insetBy(dx: 0, dy: -0.2)
}
public override func editingRect(forBounds bounds: CGRect) -> CGRect {
return self.textRect(forBounds: bounds)
}
}
Я думаю, что это также зависит от используемого вами шрифта. Я использую UIFont.systemFont(ofSize: 17.0, weight: UIFontWeightLight)
Ответ 10
Вы должны установить свойство шрифта раньше, чем свойство Text.