前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS 键盘和UIMenuController的并存问题

iOS 键盘和UIMenuController的并存问题

作者头像
且行且珍惜_iOS
发布2020-03-20 12:10:18
1.7K0
发布2020-03-20 12:10:18
举报
问题描述

当UITextView 处于编辑状态时,即键盘存在时,UITextView是第一响应者,而当需要弹出UIMenuController时,第一响应者需要变更为处理UIMenuController菜单事件的对象,此时UITextView就不是第一响应者,键盘就会隐藏,造成键盘和UIMenuController不能同时出现。问题示意图如下:

键盘和UIMenuController不能同时出现效果预览

解决方案

史上最详细的iOS之事件的传递和响应机制-原理篇 iOS响应链全家桶

此方案是通过改变响应链来解决的,如果对响应链不了解的先去补一下这方面的知识。

在保证UITextView第一响应者的前提下,我们可以覆盖改变UITextView的nextResponder,让nextResponder指向UIMenuController菜单事件的执行者;同时也要注意,在UIMenuController隐藏后,要取消nextResponder指向,不改变原有的响应链。

代码语言:javascript
复制
@interface SLTextView : UITextView
//覆盖下一个响应者
@property (nonatomic, weak) UIResponder *overrideNextResponder; 
@end
@implementation SLTextView

- (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
代码语言:javascript
复制
//长按显示菜单 UIMenuController
- (void)longPressShowMenuView:(UILongPressGestureRecognizer *)longPress {
    //编辑过程中,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];
}

键盘和UIMenuController并存问题解决

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
  • 解决方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档