Reputation: 303
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:
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.
Upvotes: 12
Views: 9152
Reputation: 904
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
}
Upvotes: 12