在 UITextField 中使用自定义字体会导致其在访问时稍微移动 - 有修复吗?

发布于 2024-11-15 23:28:13 字数 438 浏览 4 评论 0原文

我在 UITextField 中有一个自定义字体,我注意到当它被访问时(当键盘出现时),文本会向下移动非常很小的量——可能是一个像素或两个或三个像素。 (当然,我无法测量它,但这足以让我注意到。)然后当键盘关闭时,它会再次向上移动。

我尝试清除编辑字段(这隐藏了初始下移的问题),但它并没有解决问题。我还查看了 IB 中的各种属性,并尝试更改一些属性,但问题仍然存在。我在模拟器和 iPad2 上得到了相同的结果。

(该字段完全远离键盘,因此并不是整个视图移开 - 它只是特定文本字段的内容。)

我确信是自定义字体导致了问题 - 它没有没有它就不会发生。

知道如何解决这个问题吗?我在想我可能需要以编程方式创建文本字段,而不是在 IB 中——我知道我可能应该在在这里提出问题之前尝试一下,但如果不这样做的话,我不愿意遇到所有这些麻烦解决问题。

任何建议表示赞赏!

I have a custom font in a UITextField, and I've noticed that when it's accessed (when the keyboard appears), the text shifts down by a very small amount -- maybe a pixel or two or three. (I've no way to measure it, of course, but it's enough for me to notice.) And then when the keyboard is dismissed, it shifts back up again.

I've tried clearing the field on editing (which hides the problem of the initial shift down), but it hasn't solved the problem. I've also looked over the various attributes in IB, and tried changing a few, but still the problem persists. I get the same results in the simulator and on my iPad2.

(The field is well clear of the keyboard, so it's not the entire view moving out of the way -- it's just the contents of that specific text field.)

I'm sure it's the custom font that's causing the problem -- it doesn't occur without it.

Any idea how to address this? I was thinking I might need to create the text field programmatically, instead of in IB -- and I know I probably ought to try that before asking the question here, but I'm loathe to go to all that trouble if it won't solve the problem.

Any advice appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

鸢与 2024-11-22 23:28:13

我也有这个问题。

要修复此问题,请子类化 UITextField 并实现以下方法,以在不编辑和编辑时调整文本的位置。

- (CGRect)textRectForBounds:(CGRect)bounds {

    return CGRectInset( bounds , 8 , 8 );
}

- (CGRect)editingRectForBounds:(CGRect)bounds {

    return CGRectInset( bounds , 8 , 5 );
}

I had this issue as well.

To fix, subclass UITextField and implement the following methods to adjust the positioning of text when not editing and editing.

- (CGRect)textRectForBounds:(CGRect)bounds {

    return CGRectInset( bounds , 8 , 8 );
}

- (CGRect)editingRectForBounds:(CGRect)bounds {

    return CGRectInset( bounds , 8 , 5 );
}
大海や 2024-11-22 23:28:13

我的解决方案与 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 点是正确的垂直调整,有助于占位符、“静态”和“编辑”文本全部保持在同一垂直线上。

My solution is along the same lines a McDJ's, but with a slightly different twist. Subclass UITextField and override only these:

- (CGRect)placeholderRectForBounds:(CGRect)bounds {
  return CGRectOffset( [self editingRectForBounds:bounds], 0, 2 );
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
  return CGRectOffset( [super editingRectForBounds:bounds], 0, -2 );
}

With the custom font I'm using, 2 points is the correct vertical adjustment, helping placeholder, "static", and "editing" text all stay on the same vertical line.

计㈡愣 2024-11-22 23:28:13

不幸的是,没有一个答案对我有用。

@blackjacx 答案有效,但只是有时:(

我开始调试,这是我发现的:

1 - 真正的问题似乎是 UITextField 类型的私有子视图 UIFieldEditorContentView< /code>

UITextField view hieararchy

下面可以看到它的子视图的 y 不一样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 以添加将任何设置为负数的子视图的 y 手动设置为 0 的功能因为 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)
}

Unfortunately none of the answers worked for me.

@blackjacx answer worked but only sometimes :(

I started out debugging and here is what I've discovered:

1 - The real problem seems to be with a private subview of UITextField of type UIFieldEditorContentView

UITextField view hieararchy

Below you can see that the y of it subview is not the same of the UITextField itself:

Y is not set to 0

After realizing it I came out with the following workaround:

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)
            }
        }
    }
}

You will need to subclass UITextField and override layoutSubviews to add the ability to manually set to 0 the y of any subview that is set to a negative value. As this problem doesn't occur with iOS 9 our below I added a check to do the workaround only when it is on iOS 10.

The result you can see below:

Working properly

2 - This workaround doesn't work if the user choose to select a subrange of the text (selectAll works fine)

Since the selection of the text is not a must have for my app I rather disable it. In order to do that you can use the following code (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)
}
如日中天 2024-11-22 23:28:13

适用于所有字体大小,并且不会导致与 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 );
}

Works for all font sizes and does not cause de-alignment with clearButton.

Subclass UITextField and override these as follows:

- (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 );
}
櫻之舞 2024-11-22 23:28:13

出于一个奇怪的原因,我并没有真正理解我已经通过将automaticAdjustsScrollViewInsets设置为NO(或Interface Builder中的等效值)解决了这个问题。这是 iOS 8.1 的情况。

For a strange reason I didn't really understood I've solved this by setting automaticallyAdjustsScrollViewInsets to NO (or equivalent in Interface Builder). This with iOS 8.1.

a√萤火虫的光℡ 2024-11-22 23:28:13

我在使用自定义字体时遇到了这个问题,并通过在键盘事件触发时将标签向另一个方向移动来解决它。我通过重写 drawRect: 方法移动了按钮中标签的中心

- (void)drawRect:(CGRect)rect
{
    self.titleLabel.center = CGPointMake(self.titleLabel.center.x, self.titleLabel.center.y+3);
}

I had this issue with a custom font and solved it by shifting the label in the other direction when the keyboard events would fire. I moved the center of the label in the button by overriding the drawRect: method

- (void)drawRect:(CGRect)rect
{
    self.titleLabel.center = CGPointMake(self.titleLabel.center.x, self.titleLabel.center.y+3);
}
东走西顾 2024-11-22 23:28:13

这是标准 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))
}

这应该可以解决问题!

This is expected behaviour in a standard UITextField. You can however solve this by subclassing UITextField and by adjusting the bounds for the text itself.

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))
}

This should do the trick!

这个俗人 2024-11-22 23:28:13

将文本字段边框样式设置为 IB 中除“none”之外的任何值,然后在 ViewController 的 viewDidLoad 集中:(

yourTextField.borderStyle = .none

基于此答案 作者:Box Jeon)

Set your textfields Border Style to any value except "none" in IB, then, in your ViewController's viewDidLoad set:

yourTextField.borderStyle = .none

(Based on this answer by Box Jeon)

赠我空喜 2024-11-22 23:28:13

Swift 3

不要忘记 UITextField 的辅助视图。如果您想要一个有效的实现,您需要考虑 *rect(forBounds: ...) 函数的 super 。并且请确保仅替换有缺陷的 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 的“plus”设备上对其进行了测试。

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,权重:UIFontWeightLight)

Swift 3

Do not forget the accessory views of the UITextField. You'll need to account for super of the *rect(forBounds: ...) functions if you want a working implementation. And be also sure to only displace the rects for the buggy iOS 10 and not for 9 or 8! The following code should do the trick:

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
    }
}

EDIT

I slightly edited my code from above to the following and it works better for me. I testet it on iPhone 6, 6s, 7, 7s as well as the 'plus' devices with iOS 9.3 and 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)
    }
}

I think it also depends on the font you use. I use UIFont.systemFont(ofSize: 17.0, weight: UIFontWeightLight)

海未深 2024-11-22 23:28:13

您应该先设置 Font 属性,然后再设置 Text 属性。

You should set Font property earlier than Text property.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文