Anu*_*bra 6 iphone uimenucontroller iphone-softkeyboard
我目前有一个用于聊天的应用程序.我使用UItextField作为输入框和气泡来显示消息,有些东西就像系统短信.我想在消息气泡(标签)上启用复制粘贴.问题是,当我想显示UIMenuController时,我需要复制的标签需要成为第一响应者.如果当前显示键盘,当标签成为第一响应者时,文本字段将失去焦点,因此键盘将自动隐藏.这导致UI滚动并感觉不好.无论如何,即使我需要显示菜单,我仍然可以保持键盘显示?


Nik*_*ook 11
对于那些仍然在这里寻找答案的人是代码(主要想法属于neon1,请参阅链接问题).
这个想法如下:如果响应者不知道如何处理给定的动作,它会将其传播给链中的下一个响应者.到目前为止,我们有两名第一响应者候选人:
他们每个人都有独立的响应者链(事实上,不,他们确实有共同的祖先,因此他们的链有一些共同点,但我们不能使用它):
UITextField <- UIView <- ... <- UIWindow <- UIApplication
UITableViewCell <- UIView <- ... <- UIWindow <- UIApplication
Run Code Online (Sandbox Code Playgroud)
所以我们希望有以下的转发链:
UITextField <- UITableViewCell <- ..... <- UIWindow <- UIApplication
Run Code Online (Sandbox Code Playgroud)
我们需要子类UITextField(代码取自这里):
CustomResponderTextView.h
@interface CustomResponderTextView : UITextView
@property (nonatomic, weak) UIResponder *overrideNextResponder;
@end
Run Code Online (Sandbox Code Playgroud)
CustomResponderTextView.m
@implementation CustomResponderTextView
@synthesize overrideNextResponder;
- (UIResponder *)nextResponder {
if (overrideNextResponder != nil)
return overrideNextResponder;
else
return [super nextResponder];
}
@end
Run Code Online (Sandbox Code Playgroud)
这段代码非常简单:如果我们没有设置任何自定义的下一个响应者,它会返回真实的响应者,否则返回我们的自定义响应者.
现在我们可以在代码中设置新的响应者(我的示例添加自定义操作):
CustomCell.m
@implementation CustomCell
- (BOOL) canBecomeFirstResponder {
return YES;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
return (action == @selector(copyMessage:) || action == @selector(deleteMessage:));
}
@end
- (void) copyMessage:(id)sender {
// copy logic here
}
- (void) deleteMessage:(id)sender {
// delete logic here
}
Run Code Online (Sandbox Code Playgroud)
调节器
- (void) viewDidLoad {
...
UIMenuItem *copyItem = [[UIMenuItem alloc] initWithTitle:@"Custom copy" action:@selector(copyMessage:)];
UIMenuItem *deleteItem = [[UIMenuItem alloc] initWithTitle:@"Custom delete" action:@selector(deleteMessage:)];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setMenuItems:@[copyItem, deleteItem]];
...
}
- (void) longCellTap {
// cell is UITableViewCell, that has received tap
if ([self.textField isFirstResponder]) {
self.messageTextView.overrideNextResponder = cell;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuDidHide:) name:UIMenuControllerDidHideMenuNotification object:nil];
} else {
[cell becomeFirstResponder];
}
}
- (void)menuDidHide:(NSNotification*)notification {
self.messageTextView.overrideNextResponder = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerDidHideMenuNotification object:nil];
}
Run Code Online (Sandbox Code Playgroud)
最后一步是使第一响应者(在本例中的文本字段)传播完成copyMessage:和deleteMessage:行动,下一个响应者(在本例中的细胞).正如我们所知,iO发送canPerformAction:withSender:知道,如果给予响应者可以处理该动作.
我们需要修改CustomResponderTextView.m并添加以下功能:
CustomResponderTextView.m
...
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (overrideNextResponder != nil)
return NO;
else
return [super canPerformAction:action withSender:sender];
}
...
Run Code Online (Sandbox Code Playgroud)
如果我们设置了我们的自定义下一个响应者,我们会向它发送所有操作(如果你需要在textField上执行某些操作,你可以修改这个部分),否则我们会问我们的超类型是否可以处理它.
您可以尝试对 uitextfield 进行子类化并覆盖第一个响应程序。如果 uitextfield 是第一个响应者,请检查长按手势处理程序并覆盖下一个响应者。
| 归档时间: |
|
| 查看次数: |
3117 次 |
| 最近记录: |