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?
Simply subclass UITextField and override caretRectForPosition
- (CGRect)caretRectForPosition:(UITextPosition *)position
{
return CGRectZero;
}
从 iOS 7 开始,您现在只需在 textField 上设置tintColor = [UIColor clearColor]
,插入符号就会消失。
You can just clear the textfield's tintColor
self.textField.tintColor = [UIColor clearColor];
Swift 3.0
self.textField.tintColor = .clear
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/
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.
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];
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;
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.
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
}
set the tintColor to Clear Color
textfield.tintColor = [UIColor clearColor];
and you can also set from the interface builder
If you want to hide cursor, you can easily use this! It worked for me..
[[textField valueForKey:@"textInputTraits"] setValue:[UIColor clearColor] forKey:@"insertionPointColor"]
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;
}
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?
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.
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.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.