I'm using UITextField because I want to have a custom pop-up keyboard. However, I don't want the user to be able to change the insertion point or have access to the copy, paste menu.
I have found two useful stackoverflow questions, and attempted to implement them:
Disable Magnifying Glass in UITextField
(iPhone) How to handle touches on a UITextView?
I have removed the menu by subclassing the UITextField and implementing the method:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
return NO;
}
However, I have failed to stop the field from being selected when the user double taps it:
I have tried removing the gestureRecognizers which I believe to be responsible for the selection behaviour, but with no success. So what am I doing wrong?
@property (nonatomic, strong) MinimalTextField *inputText;
...
@synthesize inputText;
...
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear: animated];
NSLog(@"%ld gestureRecognizers initially ", (long)inputText.gestureRecognizers.count);
for (UIGestureRecognizer *gestureRecognizer in inputText.gestureRecognizers) {
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
UITapGestureRecognizer *tapGestureRecognizer = (UITapGestureRecognizer *)gestureRecognizer;
if ([tapGestureRecognizer numberOfTapsRequired] == 2) {
NSLog(@"found & removed: %@", tapGestureRecognizer);
[inputText removeGestureRecognizer:tapGestureRecognizer];
}
}
if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer;
NSLog(@"found & removed: %@", longPressGestureRecognizer);
[inputText removeGestureRecognizer:longPressGestureRecognizer];
}
}
NSLog(@"%ld gestureRecognizers remaining", (long)inputText.gestureRecognizers.count);
for (UIGestureRecognizer *gestureRecognizer in inputText.gestureRecognizers) {
NSLog(@"gestureRecognizer: %@", gestureRecognizer);
}
}
This code produces the following output, so I know it is working, but it fails to affect the double tap action.
7 gestureRecognizers initially
found & removed: <UITextTapRecognizer: 0x7ff6086571f0; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=oneFingerDoubleTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>; numberOfTapsRequired = 2>
found & removed: <UILongPressGestureRecognizer: 0x7ff608658180; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=twoFingerRangedSelectGesture:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>
found & removed: <UIVariableDelayLoupeGesture: 0x7ff608658a40; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=loupeGesture:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>
4 gestureRecognizers remaining
gestureRecognizer: <UITextTapRecognizer: 0x7ff608653960; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=oneFingerTripleTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>; numberOfTapsRequired = 3>
gestureRecognizer: <UITextTapRecognizer: 0x7ff6086576e0; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=twoFingerSingleTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>; numberOfTouchesRequired = 2>
gestureRecognizer: <UITapAndAHalfRecognizer: 0x7ff608657c70; state = Possible; view = <MinimalTextField 0x7ff608414b10>; target= <(action=tapAndAHalf:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>
gestureRecognizer: <UITextTapRecognizer: 0x7ff6086585f0; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=oneFingerTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>
I have even tried adding the following code to my subclass of UITextField:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
NSLog(@"Gesture should begin");
if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]])
NSLog(@"rotate");
if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]])
NSLog(@"pinch");
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
NSLog(@"tap");
NSLog(@"numberOfTouches: %ld", (long)gestureRecognizer.numberOfTouches);
}
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
NSLog(@"pan");
if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
NSLog(@"long");
if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]])
NSLog(@"swipe");
return YES;
}
However, there is no property gestureRecognizer.numberOfTaps available, so how can I tell how often it has been tapped.
Use the enabled: property of the TextField widget by setting it to false : TextField( enabled: false, ... ) This field won't respond to onTap events - it is similar to a disabled field in HTML.
Set the Boolean variable to false, which enables editing in the text field. When someone taps the Done button, isEditing becomes false. Set the Boolean variable to true, which disables editing in the text field.
I have found this useful article that solved the problem for me: https://www.transpire.com/insights/blog/disabling-caret-text-entry-uitextfields/
You need to add the following overrides to your UITextField
subclass (they basically disable the UIMenuController
and hide the selection and caret rects):
- (CGRect)caretRectForPosition:(UITextPosition*) position {
return CGRectNull;
}
- (NSArray *)selectionRectsForRange:(UITextRange *)range {
return nil;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
return NO;
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
false
}
override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
[]
}
override func caretRect(for position: UITextPosition) -> CGRect {
.null
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With