我正在寻找一种将键盘从右侧滑入视图的方法,就像编辑注释时在“联系人”应用程序中发生的情况一样。
我的问题是,当我在 viewWillAppear 中调用 [someTextViewBecomeFirstResponder] 时,键盘立即弹出,没有动画。当我在viewDidAppear中调用它时,视图首先从右侧滑入(UINavigationController进行滑动),然后键盘从底部滑入。
能否让键盘和视图一起从右侧滑入?
在 iOS 7 中,可以在
becomeFirstResponder
中的 _textView
上调用 viewDidLayoutSubviews
。
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[_textView becomeFirstResponder];
}
注意:在
viewWillLayoutSubviews
中执行也可以。
阅读文档中关于 becomeFirstResponder 的讨论。
您可以调用此方法使响应者对象(例如视图)成为第一响应者。但是,只有当该视图是视图层次结构的一部分时,才应该在该视图上调用它。如果视图的
属性包含window
对象,则它已安装在视图层次结构中;如果它返回UIWindow
,则视图与任何层次结构分离。nil
当使用导航控制器将自定义视图控制器推送到屏幕上时,在调用
self.view.window
或 nil
时,viewDidLoad
仍然是 viewWillAppear:
。因此,在相同的方法中,_textView.window
也是nil
,因为_textView
是self.view
的子视图,即它们都在同一个窗口中。无论您如何呈现自定义视图控制器,self.view.window
(因此_textView.window
)也是nil
中的initWithNibName:bundle:
。 self.view.window
是在调用 viewDidAppear:
时设置的,但是已经太晚了,因为到那时,导航控制器已经完成了将视图推到屏幕上的动画。
self.view.window
也可以在调用 viewWillLayoutSubviews
或 viewDidLayoutSubviews
时设置,并且在导航控制器的推送动画开始之前调用这些方法。因此,这就是为什么当您使用这些方法中的任何一种时它都会起作用。
不幸的是,
viewWillLayoutSubviews
和viewDidLayoutSubviews
被调用的次数远不止在最初的导航控制器推送上。但是, navigationController:willShowViewController:
和 willMoveToParentViewController:
被调用得太早(在 viewDidLoad
之后但在 self.view.window
设置之前),而 navigationController:didShowViewController:
和 didMoveToParentViewController:
被调用得太晚(在推送动画之后)。
我能想到的唯一其他方法是以某种方式观察
window
的 _textView
属性,以便在它发生变化时收到通知,但我不知道该怎么做,因为 window
是 readonly
.
您需要做的就是告诉相关文本视图成为您推送到导航堆栈的视图控制器的
viewDidLoad
方法中的第一响应者:
override func viewDidLoad() {
super.viewDidLoad()
someTextView.becomeFirstResponder()
}
这适用于 iOS 8。键盘会随着视图从右侧滑入。
在 iOS 7(或之前的任何版本)中,您可以在 loadView、viewDidLoad 或 viewWillAppear
中做一个简单的事情[yourTextView performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
在这种情况下,您将获得键盘从左到右的外观与推动视图控制器的运动对齐。
对于 iOS 7,我找到了以下最适合我的解决方案:
UIResponder-KeyboardCache
导入到您的项目中。
-将
[UIResponder cacheKeyboard:YES];
添加到键盘视图之前视图的 viewDidLoad
。最好在应用程序加载时立即执行此操作,或者在您负担得起的方便时间(例如在 HTTP 请求期间)执行此操作。在大多数情况下,只需查看之前的视图就足够了。
-将以下内容添加到键盘视图的
viewDidLoad
。
dispatch_async(dispatch_get_main_queue(), ^{
[_textField becomeFirstResponder];
});
解释一下,这将预加载键盘视图,这将消除第一次调用键盘视图的延迟。在主队列中的文本字段上调用
becomeFirstResponder
会使其随视图滑入,而不是在视图滑入之前向上动画。
您可以尝试将becomeFirstResponder消息发送到新的视图控制器,然后再将其推入堆栈。 例如:
-(void)functionWhereYouPushTheNewViewController {
yourNewViewController *newVC = [[yourNewViewController alloc] init];
[newVC.yourTextView becomeFirstResponder];
[self.navigationController pushViewController:newVC animated:YES];
}
我发现改变键盘之类的动画是相当困难的,如果你读过《人机界面指南》,苹果就很清楚地表明他们希望某些东西始终以某种方式发挥作用。 有多种方法可以更改某些动画的行为,但它们通常涉及未记录的 API 调用,并且是应用商店拒绝的理由。 例如,将视图从底部向上滑动将违反 HIG。
希望这有帮助。