Подтвердить что ты не робот

Использование пользовательского шрифта в UITextField заставляет его слегка сдвигаться при доступе - есть ли исправление?

У меня есть пользовательский шрифт в UITextField, и я заметил, что когда он открывается (когда появляется клавиатура), текст сдвигается на очень небольшую величину - может быть, пиксель или два или три. (Разумеется, я не могу ее измерить, но мне это достаточно, чтобы заметить). И затем, когда клавиатура отклоняется, она снова возвращается обратно.

Я попытался очистить поле при редактировании (которое скрывает проблему начального сдвига вниз), но оно не решило проблему. Я также рассмотрел различные атрибуты в IB и попытался изменить несколько, но проблема все еще сохраняется. Я получаю те же результаты в симуляторе и на своем iPad2.

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

Я уверен, что это пользовательский шрифт, который вызывает проблему, - без него.

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

Любые советы оценены!

4b9b3361

Ответ 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.