隐藏UITextField的光标


137

我正在使用UITextField带有a UIPickerViewinputView,因此当用户点击文本字段时,将召唤一个选择器供他们从中选择一个选项。

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

我怎样才能简单地将光标隐藏在鼠标上UITextField呢?

Answers:


277

只需将UITextField子类化并重写caretRectForPosition

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

2
美丽!对我来说就像一个魅力。
Joe Strout

1
@Joseph Chiu很棒。但不适用于iOS 4.3。你能帮我吗?
Dinesh Raja

最清洁,最短的方法值得两次投票=)
Ilker Baltaci 2014年

1
请注意。在我的子类中,我添加了一个bool hideCaret,然后在此重写中,如果为true-> return CGRectZero,否则返回super的结果。
WCByrne 2014年

6
请注意,即使隐藏了光标并且使用了选择器视图,使用外部键盘的用户也可以更改文本字段的值。
2015年

156

从iOS 7开始,您现在可以tintColor = [UIColor clearColor]在textField上设置,插入号将消失。


1
目前此功能有效,但是我建议不要使用它,因为将来可能会更改。而是选择caretRectForPosition:替代解决方案。
lipka

@lipka是的,那可能是一个更好的方法。
jamone 2014年

2
现在足够好了。有时您只需要快速解决方案。
GoldenJoe

到目前为止,这是最简单的解决方案!
杰伊·Q.

1
这个答案应该被批准为iOS 7+
TRYP

95

您可以清除文本字段的tintColor

self.textField.tintColor = [UIColor clearColor];

斯威夫特3.0

self.textField.tintColor = .clear

在此处输入图片说明


最佳答案。
Nik Kov'8

2
如上所述,清除色泽不会阻止使用外部键盘(iPad Pro)的用户更改文本。
Michael Long

@MichaelLong这不是要阻止用户更改文本,这只是样式选择。
JRam13,

21

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

- (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/


15

退房财产 selectedTextRange的的协议 UITextInput,对此 UITextField符合。很少!那就是那里面向对象编程的一课。

隐藏插入符

要隐藏插入记号,请取消选中文本字段的选定文本范围。

textField.selectedTextRange = nil; // hides caret

取消隐藏插入符号

这有两种隐藏隐藏符号的方法。

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

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

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

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

    textField.selectedTextRange     = _textFieldSelectedTextRange;
    _textFieldLastSelectedTextRange = nil;

3
这个特定的解决方案不适用于我的实现。光标仍然闪烁。
Art Geigel 2013年

嗯,那么,也许您应该在bugreport.apple.com上提交错误,因为iOS文档说:“如果文本范围有长度,则表示当前选定的文本。如果长度为零,则表示插入号(插入点)。如果文本范围对象为nil,则表明没有当前选择。”
ma11hew28 2013年

4
我不在乎要提交报告。如果其他人使用您的“解决方案”并且认为它不起作用,我希望他们知道他们并不孤单。
Art Geigel

尽管有@ArtGeigel的评论,但这对我来说非常有效。但是,我更喜欢涉及覆盖的解决方案caretRectForPosition。更明确地说,它在做什么,并且您引用的文档并不清楚在没有“当前选择”时插入符号的行为。如果@ArtGeigel的说法不正确(至少据我所知不是这样),那么就不清楚那是一个错误。
Mark Amery 2013年

也没有为我工作。插入符号仍然在那里并且闪烁。
CW0007007 2013年

11

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

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

- (UIView *)inputView {
    return inputView_;
}

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

- (BOOL)canBecomeFirstResponder {
    return YES;
}

现在,按钮的UIResponder行为UITextField与相似,实现也非常简单。


5
这并不是一个很好的解决方案。在下面查看此答案:stackoverflow.com/a/13660503/1103584
DiscDev 2013年

2
为什么这不是一个很好的解决方案?它不仅可以达到预期的效果,还可以为以前没有的类提供功能。这也不是hack。我认为这真的很酷。那怎么了?
BreadicalMD

2
@BreadicalMD我可以看到的最大问题是,您不能UITextFieldDelegate与此一起使用a 来处理开始和结束编辑事件。相反,除非有一种方法可以处理我不知道的事件,否则您将需要重写它becomeFirstResponderresignFirstResponder在button子类中,并可能创建自己的委托协议,添加一个delegate属性,并从上述方法中调用委托方法。这不仅仅是caretRectForPositionUITextField子类中进行覆盖,还需要做更多的工作。
马克·阿默里

1
@BreadicalMD话虽如此,尽管从实际的角度来看,Joseph Chiu的回答是优越的,但我仍然同意你的看法,这很性感。我以前从没有仔细看过UIResponder类参考,也不知道这样的技巧是可能的。
Mark Amery 2013年

晚了聚会,但是我认为这是一个很好的解决方案,与使用a UITextField和隐藏光标相比,它感觉更合适,而且不那么hack ,这基本上是hack,因为我们随后将text字段用作标签,不使用的任何功能UITextField
罗珀特

7

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 4使用这些方法添加了UITextField的子类。谢谢!
J. Fdez '18年

3

将tintColor设置为Clear Color

textfield.tintColor = [UIColor clearColor];

您还可以通过界面构建​​器进行设置


2
您刚刚复制了2年前的答案。
阿什莉·米尔斯

1
对不起我的朋友,但我没有复制任何东西。
艾哈迈德·阿塔尔

4
有趣的是,“我的朋友”。您的答案看起来与15年5月1日以来@oldman的答案非常接近。你能告诉我你的与众不同吗?
阿什利·米尔斯

1
如上所述,清除色泽不会阻止使用外部键盘(iPad Pro)的用户更改文本。
Michael Long

专业用户可以做自己喜欢的事情。他们是专家:他们知道自己在做什么; ^)
Anton Tropashko

2

如果要隐藏光标,则可以轻松使用它!它对我有用。

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

3
据我所知,这是无证的。如果您将其提交到应用商店,使用此方法可能会使您的应用被拒绝调用私有API,尽管我不知道有任何提交使用此方法来以某种方式测试这种推测。很遗憾,因为能够不用子类就能解决此问题真是太好了,而这个答案可以实现这一点。
马克·阿默里

1

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

我认为我有正确的解决方案,但是如果可以改进,将是受欢迎的:)好吧,我制作了UITextField的子类,并重写了返回CGRect范围的方法

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

问题?该文本未显示,因为rect为零。但是我添加了一个UILabel作为控件的子视图,并覆盖了setText方法,因此,当我们像往常一样输入文本时,文本字段text为nil,并且是显示文本的标签

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

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

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

有了这个东西,事情按预期进行。您知道任何改善方法吗?


鉴于Joseph Chiu的替代方法非常相似,但更为简单,因此,此答案基本上毫无价值。我可以建议只删除它吗?
Mark Amery 2013年

1

要同时禁用游标和菜单,我将子类与以下两种方法结合使用:

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

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

    return NO;
}

0

我只是将其子类化UITextField,并重写layoutSubviews如下:

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

这是一个肮脏的技巧,将来可能会失败(此时光标将再次可见-您的应用不会崩溃),但是它可以正常工作。


-1

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

@interface UITextField (Cursorless)

@property (nonatomic, assign) BOOL cursorless;

@end

然后,使用swizzling caretRectForPosition:方法使用在之间切换CGRectZero及其默认值的方法进行滚动cursorless

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

只需将它们放入并获得此简单界面的好处

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


这么多级别的解决方案都不好!对于初学者:切勿覆盖类别中的方法。除非确实需要,否则请避免“方法混乱”(其他人对此问题提出了很好的解决方案)。这使您的代码变得更加复杂。
EsbenB 2014年

如果您实际上查看了代码,您会发现类别中没有覆盖任何方法,并且正确实现了方法混乱。我已经使用此实现多年,没有失败。
Awesome-o

另外,请解释一下添加约150行的隔离代码库以永久解决不断重复出现的问题有何复杂之处?这不仅不会使您的代码库复杂化,而且还提供了最简单的接口。一个布尔值来指示功能。
Awesome-o

看看有关方法混写这个优秀的讨论stackoverflow.com/questions/5339276/...上调试更是如此。方法混乱是一个了不起的功能,但是恕我直言,仅应在需要时使用。使用此处提供的建议之一可以轻松解决此问题,并将为其他程序员提供易于维护和阅读的代码。
EsbenB 2014年

我之前已经读过这篇文章,并且为了正确起见,我在实现过程中遵循了所有概述的准则。可以说,这是方法混乱胜出的可靠例子。这是一个孤立而又常见的情况,即基本库无法以简单的方式跨平台实现广泛需要的功能。建议的其他示例没有在语义上定义无光标文本字段,它们仅通过混淆光标的框架或其颜色来执行此操作。对于新程序员来说,此接口最容易阅读,并且完全可以实现预期的功能。
Awesome-o
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.