描述以UITextView
为例
当UITextView
处于编辑状态时,即键盘存在时,UITextView
是第一响应者,而当需要弹出UIMenuController
时,第一响应者需要变更为处理UIMenuController
菜单事件的对象,此时UITextView就不是第一响应者,键盘就会隐藏,造成键盘和UIMenuController
不能同时出现.
解决方案
通过改变响应链来解决:
参考
iOS事件响应机制
iOS响应链全家桶
在保证UITextVie
第一响应者的前提下,我们可以覆盖改变UITextView
的nextResponder
,让nextResponder
指向UIMenuController
菜单事件的执行者,同时也要注意,在UIMenuController
隐藏后,要取消nextResponder
指向,不改变原有的响应链.
代码实现
自定义MYTextView
@interface MYTextView : UITextView
//覆盖下一个响应者
@property (nonatomic, weak) UIResponder *overrideNextResponder;
@end
@implementation MYTextView
- (UIResponder *)nextResponder {
if(_overrideNextResponder == nil){
return [super nextResponder];
} else {
return _overrideNextResponder;
}
}
//UIMenuController 菜单可以执行操作
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (_overrideNextResponder != nil) {
return NO;
}
return [super canPerformAction:action withSender:sender];
}
@end
长按显示UIMenuController
的VC
这里以长按VC
中的self.titleLabel
为例:
//长按显示菜单 UIMenuController
- (void)longPressShowMenuView:(UILongPressGestureRecognizer *)longPress {
//避免长按多次执行
if (longPress.state != UIGestureRecognizerStateBegan) {
return;
}
//编辑过程中,self.textView是第一响应者
if(self.textView.isFirstResponder){
//如果textView是第一响应者,则对titleLabel进行响应链透传,覆盖self.textView的下一个响应者
self.textView.overrideNextResponder = self.titleLabel;
//添加菜单隐藏的监听,当菜单隐藏时,要重置self.textView.overrideNextResponder = nil
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuViewDidHide:) name:UIMenuControllerDidHideMenuNotification object:nil];
}else {
//如果当前无第一响应者,就成为第一响应者
[self.titleLabel becomeFirstResponder];
}
UIMenuController *menuController = [UIMenuController sharedMenuController];
UIMenuItem *saveItems = [[UIMenuItem alloc] initWithTitle:@"保存" action:@selector(save:)];
UIMenuItem *noteItem = [[UIMenuItem alloc] initWithTitle:@"笔记" action:@selector(note:)];
menuController.menuItems = @[noteItem, saveItems];
if (@available(iOS 13.0, *)) {
[menuController showMenuFromView:self.view rect:self.titleLabel.frame];
} else {
[menuController setTargetRect:self.titleLabel.frame inView:self.view];
[menuController setMenuVisible:YES animated:YES];
}
}
//隐藏菜单UIMenuController的通知
- (void)menuViewDidHide:(NSNotification*)notification {
//重置,不影响原有的响应链
self.textView.overrideNextResponder = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerDidHideMenuNotification object:nil];
}
FEATURED TAGS
iOS
OC
C
Xcode
MIMEType
屏幕旋转
Mac
工具
SQLite3
重命名
证书+内购
像素
pch
支付协议税务
APP转让
审核
银行卡格式化
git
描述文件
命令行
沙盒日志
i386
x86_64
控制台log
xcode10&iOS12
正则
textfield
输入限制
Pod
真机支持
封面尺寸
SDWebImage
Ruby
RVM
渐变色
jekyll
水印
富文本
标签
M3U8
动、静态库
异步上传
Url编码解码
AlertController
保活
pod报错
特定UI横竖屏
Launch版本号
ijkplayer
适配
手势
截图
网络和信号
礼物缓存
手绘礼物
UIPickerView
文件权限
键盘和菜单
耗时卡顿
国际化
Paypal
AWSS3
npm、Node
控制台
warning
扩展
防盗链
动画
分析
CallKit
侧滑
重置根控制器
播放器
裁剪
日志
bugly
uniapp
Swift
文字翻转
跨域
WebClip
网络请求
地图导航
ZSH
SPM
Vapor
导航
验证码
杀进程
Ubuntu
Android
JWT
vue
html-js
style-class
ssh
PHP
jks
css
Runtime
tree
uniCloud
圆角
总结