隐藏 UITextField 的光标

发布于 2024-09-18 21:18:10 字数 431 浏览 8 评论 0原文

我使用 UITextFieldUIPickerView 作为其 inputView,这样当用户点击文本字段时,就会调用一个选择器来让他们从中选择一个选项。

几乎一切正常,但我有一个问题:当文本字段处于活动状态时,光标仍然在文本字段中闪烁,这是丑陋且不合适的,因为用户不会在该字段中键入内容,并且不会出现键盘。我知道我可以通过在文本字段上将 editing 设置为 NO 并跟踪其上的触摸来解决这个问题,或者将其替换为自定义样式的按钮,然后调用通过代码选择器。但是,我想使用 UITextFieldDelegate 方法来处理文本字段上的所有事件,而诸如用按钮替换文本字段之类的黑客行为不允许这种方法。

如何简单地将光标隐藏在 UITextField 上?

I am using a UITextField with a UIPickerView for its inputView, so that when the user taps the text field, a picker is summoned for them to select an option from.

Nearly everything works, but I have one problem: the cursor still flashes in the text field when it is active, which is ugly and inappropriate, since the user is not expected to type into the field and is not presented with a keyboard. I know I could hackily solve this by setting editing to NO on the text field and tracking touches on it, or by replacing it with a custom-styled button, and summoning the picker via code. However, I want to use the UITextFieldDelegate methods for all the event handling on the text field and hacks such as replacing the text field with a button do not permit this approach.

How can I simply hide the cursor on the UITextField instead?

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

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

发布评论

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

评论(15

春花秋月 2024-09-25 21:18:46

您可以通过关联对象将 BOOLcursorless 属性添加到类别中的 UITextField

@interface UITextField (Cursorless)

@property (nonatomic, assign) BOOL cursorless;

@end

然后使用方法调配来调配 caretRectForPosition: 和使用 cursorlessCGRectZero 及其默认值之间切换的方法。

这通过插入类别产生了一个简单的界面。以下文件对此进行了演示。

的好处

只需将它们放入即可享受这个简单界面UITextField 类别 :
https://github.com/rexmas/RexDK/blob /master/RexDK/UI/UITextField%2BRXCursorless.h
https://github.com/rexmas/RexDK/blob /master/RexDK/UI/UITextField%2BRXCursorless.m

方法调整:
https://github.com/rexmas/RexDK/blob /master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.h
https://github.com/rexmas/RexDK/blob /master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.m

You can add a BOOL cursorless property to UITextField in a category via associated objects.

@interface UITextField (Cursorless)

@property (nonatomic, assign) BOOL cursorless;

@end

Then use method swizzling to swizzle caretRectForPosition: with a method that toggles between CGRectZero and its default value using cursorless.

This leads to a simple interface via a drop-in category. This is demonstrated in the following files.

Simply drop them in and get the benefit of this simple interface

UITextField category:
https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless.h
https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless.m

Method Swizzling:
https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.h
https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.m

蓝咒 2024-09-25 21:18:44

就我而言,覆盖插入符号矩形是不够的。在 iOS 15 上,插入符号并未有效出现,但选择手柄却出现了。

解决方法是:在 UITextView 子类上覆盖 var canBecomeFirstResponder: Bool { return false } 。

In my case, overriding the caret rect wasn't enough. On iOS 15, the caret didn't appear, effectively, but the selection handles did.

Solved it with: override var canBecomeFirstResponder: Bool { return false } on the UITextView subclass.

带刺的爱情 2024-09-25 21:18:43

如果您喜欢更干净=更少的代码,请使用界面构建器:

Clear color

(属性检查器,查看部分。)

If you like cleaner = less code, use the interface builder:

Clear color

(Attributes inspector, view section.)

So尛奶瓶 2024-09-25 21:18:41

我只是子类化UITextField,并重写layoutSubviews,如下所示:

- (void)layoutSubviews
{
    [super layoutSubviews];
    for (UIView *v in self.subviews)
    {
        if ([[[v class] description] rangeOfString:@"UITextSelectionView"].location != NSNotFound)
        {
            v.hidden = YES;
        }
    }
}

这是一个肮脏的黑客行为,并且将来可能会失败(此时光标将再次可见 - 您的应用程序获胜)不会崩溃),但它有效。

I simply subclass UITextField, and override layoutSubviews as follows:

- (void)layoutSubviews
{
    [super layoutSubviews];
    for (UIView *v in self.subviews)
    {
        if ([[[v class] description] rangeOfString:@"UITextSelectionView"].location != NSNotFound)
        {
            v.hidden = YES;
        }
    }
}

It's a dirty hack, and may fail in the future (at which point the cursor will be visible again - your app won't crash), but it works.

谁对谁错谁最难过 2024-09-25 21:18:38

为了禁用光标和菜单,我使用带有以下两种方法的子类:

- (CGRect)caretRectForPosition:(UITextPosition *)position {
    return CGRectZero;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    [UIMenuController sharedMenuController].menuVisible = NO;
    self.selectedTextRange = nil;

    return NO;
}

To both disable cursor and menu I use subclass with these 2 methods:

- (CGRect)caretRectForPosition:(UITextPosition *)position {
    return CGRectZero;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    [UIMenuController sharedMenuController].menuVisible = NO;
    self.selectedTextRange = nil;

    return NO;
}
倦话 2024-09-25 21:18:37

OP提供的答案,从问题正文中复制,以帮助清理不断增长的未回答问题。

我认为我有正确的解决方案,但如果可以改进,将受到欢迎:)好吧,我创建了 UITextField 的子类,并重写了返回边界 CGRect 的方法 问题

-(CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectZero;
}

是什么?文本不显示,因为矩形为零。但是我添加了一个 UILabel 作为控件的子视图并重写了 setText 方法,因此,当我们像往常一样输入文本时,文本字段文本为零,并且是显示文本的标签

- (void)setText:(NSString *)aText {
    [super setText:nil];

    if (aText == nil) {
        textLabel_.text = nil;
    }

    if (![aText isEqualToString:@""]) {
        textLabel_.text = aText;
    }
}

有了这个,事情就按预期工作了。你知道有什么方法可以改善吗?

Answer provided by the OP, copied from the question body to help clean up the ever growing tail of unanswered questions.

I think I have the correct solution but If it can be improved will be welcome :) Well, I made a subclass of UITextField and overriden the method that returns the CGRect for the bounds

-(CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectZero;
}

The problem? The text doesn't show because the rect is zero. But I added an UILabel as a subview of the control and overridden the setText method so, as we enter a text as usual, the text field text is nil and is the label which shows the text

- (void)setText:(NSString *)aText {
    [super setText:nil];

    if (aText == nil) {
        textLabel_.text = nil;
    }

    if (![aText isEqualToString:@""]) {
        textLabel_.text = aText;
    }
}

With this the thing works as expected. Have you know any way to improve it?

电影里的梦 2024-09-25 21:18:35

如果你想隐藏光标,你可以轻松使用这个!它对我有用..

[[textField valueForKey:@"textInputTraits"] setValue:[UIColor clearColor] forKey:@"insertionPointColor"]

If you want to hide cursor, you can easily use this! It worked for me..

[[textField valueForKey:@"textInputTraits"] setValue:[UIColor clearColor] forKey:@"insertionPointColor"]
浪漫人生路 2024-09-25 21:18:33

将tintColor设置为Clear Color

textfield.tintColor = [UIColor clearColor];

,您也可以从界面生成器中设置

set the tintColor to Clear Color

textfield.tintColor = [UIColor clearColor];

and you can also set from the interface builder

风吹过旳痕迹 2024-09-25 21:18:32

OP提供的答案,从问题正文中复制来帮助清理不断增长的未回答问题。

我找到了另一个解决方案:子类UIButton并重写这些方法

- (UIView *)inputView {
    return inputView_;
}

- (void)setInputView:(UIView *)anInputView {
    if (inputView_ != anInputView) {
        [inputView_ release];
        inputView_ = [anInputView retain];
    }
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

现在按钮作为 UIResponder 具有与 UITextField 类似的行为,并且实现非常简单。

Answer provided by the OP, copied from the question body to help clean up the ever growing tail of unanswered questions.

I found another solution: subclass UIButton and override these methods

- (UIView *)inputView {
    return inputView_;
}

- (void)setInputView:(UIView *)anInputView {
    if (inputView_ != anInputView) {
        [inputView_ release];
        inputView_ = [anInputView retain];
    }
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

Now the button, as a UIResponder, have a similar behavior than UITextField and an implementation pretty straightforward.

回梦 2024-09-25 21:18:30

Net 帖子的 Swift 5 版本

  override func caretRect(for position: UITextPosition) -> CGRect {
    return .zero
  }
  
  override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
    return []
  }
  
  override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return false
  }

Swift 5 version of Net's post

  override func caretRect(for position: UITextPosition) -> CGRect {
    return .zero
  }
  
  override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
    return []
  }
  
  override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return false
  }
不醒的梦 2024-09-25 21:18:28

查看属性协议的 selectedTextRange UITextInput UITextField 符合。很少!这就是面向对象编程的一课。

隐藏插入符号

要隐藏插入符号,请将文本字段的选定文本范围清零。

textField.selectedTextRange = nil; // hides caret

取消隐藏插入符号

以下是取消隐藏插入符号的两种方法。

  1. 将文本字段的选定文本范围设置为文档末尾。

    UITextPosition *end = textField.endOfDocument;
    textField.selectedTextRange = [textField textRangeFromPosition:end
                                                        到位置:结束];
    
  2. 要将插入符号保持在同一位置,首先,将文本字段的选定文本范围存储到实例变量中。

    _textFieldSelectedTextRange = textField.selectedTextRange;
    textField.selectedTextRange = nil; // 隐藏插入符号
    

    然后,当您想要取消隐藏插入符号时,只需将文本字段的选定文本范围设置回原来的值即可:

    textField.selectedTextRange = _textFieldSelectedTextRange;
    _textFieldLastSelectedTextRange = nil;
    

Check out the property selectedTextRange of the protocol UITextInput, to which the class UITextField conforms. Few! That's a lesson in object-oriented programing right there.

Hide Caret

To hide the caret, nil out the text field's selected text range.

textField.selectedTextRange = nil; // hides caret

Unhide Caret

Here are two ways to unhide the caret.

  1. Set the text field's selected text range to the end of the document.

    UITextPosition *end = textField.endOfDocument;
    textField.selectedTextRange = [textField textRangeFromPosition:end
                                                        toPosition:end];
    
  2. To keep the caret in the same spot, first, store the text field's selected text range to an instance variable.

    _textFieldSelectedTextRange = textField.selectedTextRange;
    textField.selectedTextRange = nil; // hides caret
    

    Then, when you want to unhide the caret, simply set the text field's selected text range back to what it was originally:

    textField.selectedTextRange     = _textFieldSelectedTextRange;
    _textFieldLastSelectedTextRange = nil;
    
久光 2024-09-25 21:18:26

您可能还想阻止用户选择、复制或粘贴任何文本,以便唯一的文本输入来自选择器视图。

- (CGRect) caretRectForPosition:(UITextPosition*) position
{
    return CGRectZero;
}

- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
    return nil;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(copy:) || action == @selector(selectAll:) || action == @selector(paste:))
    {
        returnNO;
    }

    return [super canPerformAction:action withSender:sender];
}

http://b2cloud.com.au/教程/禁用插入符号和文本输入在 uitextfields/

You might also want to stop the user from selecting, copying or pasting any text so that the only text input comes from the picker view.

- (CGRect) caretRectForPosition:(UITextPosition*) position
{
    return CGRectZero;
}

- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
    return nil;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(copy:) || action == @selector(selectAll:) || action == @selector(paste:))
    {
        returnNO;
    }

    return [super canPerformAction:action withSender:sender];
}

http://b2cloud.com.au/tutorial/disabling-the-caret-and-text-entry-in-uitextfields/

走走停停 2024-09-25 21:18:24

您只需清除文本字段的tintColor

self.textField.tintColor = [UIColor clearColor];

Swift 3.0

self.textField.tintColor = .clear

在此处输入图像描述

You can just clear the textfield's tintColor

self.textField.tintColor = [UIColor clearColor];

Swift 3.0

self.textField.tintColor = .clear

enter image description here

蔚蓝源自深海 2024-09-25 21:18:22

从 iOS 7 开始,您现在只需在文本字段上设置 tintColor = [UIColor clearColor] ,插入符号就会消失。

As of iOS 7 you can now just set the tintColor = [UIColor clearColor] on the textField and the caret will disappear.

策马西风 2024-09-25 21:18:21

只需子类化 UITextField 并覆盖 caretRectForPosition

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    return CGRectZero;
}

Simply subclass UITextField and override caretRectForPosition

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