iOS App中UITextField的PASTE菜单旋转后位置异常,如何使其显示在控件上方?
解决UITextField旋转后PASTE菜单位置异常的问题
这个问题的核心是系统默认的菜单定位逻辑在设备旋转或复杂视图层级下失效,导致PASTE菜单偏离文本框位置。以下是两种可靠的解决方法:
方法一:自定义UITextField子类,手动控制菜单位置
通过子类化UITextField,接管菜单的显示逻辑,强制将菜单锚定在文本框上方:
@interface CustomTextField : UITextField @end @implementation CustomTextField // 保留PASTE操作权限 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(paste:)) { return YES; } return [super canPerformAction:action withSender:sender]; } // 手动设置菜单显示位置 - (void)showCustomMenu { UIMenuController *menuController = [UIMenuController sharedMenuController]; // 将菜单的目标区域设为文本框自身的边界 [menuController setTargetRect:self.bounds inView:self]; [menuController setMenuVisible:YES animated:YES]; } // 监听长按事件,触发自定义菜单 - (void)awakeFromNib { [super awakeFromNib]; UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)]; [self addGestureRecognizer:longPress]; } - (void)onLongPress:(UILongPressGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateBegan) { [self becomeFirstResponder]; [self showCustomMenu]; } } @end
方法二:在控制器中监听旋转事件,实时修正菜单位置
如果不想子类化文本框,可以在所属控制器中监听设备旋转通知,在旋转完成后重新定位菜单:
- (void)viewDidLoad { [super viewDidLoad]; // 注册旋转通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onDeviceRotated:) name:UIDeviceOrientationDidChangeNotification object:nil]; } - (void)onDeviceRotated:(NSNotification *)notification { UIMenuController *menuController = [UIMenuController sharedMenuController]; // 若菜单可见且文本框处于编辑状态,重新定位 if (menuController.isMenuVisible && self.targetTextField.isFirstResponder) { [menuController setTargetRect:self.targetTextField.bounds inView:self.targetTextField]; } } // 记得移除通知监听 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
关键注意点
- 确保文本框已调用
becomeFirstResponder,UIMenuController需要当前存在第一响应者才能正常显示 - 如果文本框嵌套在UIScrollView或自定义容器中,必须手动指定菜单的目标视图为文本框本身,避免系统错误计算位置
内容的提问来源于stack exchange,提问作者Shital Bhikhadiya
相关产品推荐
相关产品推荐

