所以我基本上有一个表格,由几个文本字段组成。用户像往常一样输入字段。但是用户也可以选择双击文本字段,它会显示一个模态视图控制器,允许用户从与该字段相关的多个选项中进行选择。
我可以以某种方式在键盘“上方”呈现模态,这样当它被关闭时,键盘对于在我呈现模态之前已经是第一响应者的字段仍然处于活动状态?
现在,键盘在模态出现时消失,并在模态消失时重新出现。在我看来它很笨重,而且让人分心。希望简化它,并减少屏幕上的动画数量。
所以我基本上有一个表格,由几个文本字段组成。用户像往常一样输入字段。但是用户也可以选择双击文本字段,它会显示一个模态视图控制器,允许用户从与该字段相关的多个选项中进行选择。
我可以以某种方式在键盘“上方”呈现模态,这样当它被关闭时,键盘对于在我呈现模态之前已经是第一响应者的字段仍然处于活动状态?
现在,键盘在模态出现时消失,并在模态消失时重新出现。在我看来它很笨重,而且让人分心。希望简化它,并减少屏幕上的动画数量。
编辑:我已经为 iOS 12 和 Swift 更新了这个答案。修改后的示例项目(包含新的 Swift 和更新的 Objective-C 实现)在这里。
您可以创建一个新的UIWindow
并将其放置在默认窗口上,同时隐藏键盘的窗口。
我在Github 上有一个示例项目,但基本过程如下。
UIViewController
类。我打电话给我OverlayViewController
的。根据需要设置相应的视图。根据您的问题,您需要回传一些选项,所以我制定了一个委托协议OverlayViewController
,并将主窗口的根视图控制器(类ViewController
)作为我们的委托。protocol OverlayViewControllerDelegate: class {
func optionChosen(option: YourOptionsEnum)
}
class ViewController: UIViewController {
/// The text field that responds to a double-tap.
@IBOutlet private weak var firstField: UITextField!
/// A simple label that shows we received a message back from the overlay.
@IBOutlet private weak var label: UILabel!
/// The window that will appear over our existing one.
private var overlayWindow: UIWindow?
UITapGestureRecognizer
到您的UITextField
.override func viewDidLoad() {
super.viewDidLoad()
// Set up gesture recognizer
let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTapRecognizer.numberOfTapsRequired = 2
doubleTapRecognizer.delegate = self
firstField.addGestureRecognizer(doubleTapRecognizer)
firstField.becomeFirstResponder()
}
UITextField
有内置的手势识别器,所以我们需要让多个UIGestureRecognizer
s同时操作。extension ViewController: UIGestureRecognizerDelegate {
// Our gesture recognizer clashes with UITextField's.
// Need to allow both to work simultaneously.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
UIWindow
,指定你的OverlayViewController
作为根视图控制器,并显示它。请注意,我们将窗口级别设置为UIWindowLevelAlert
使其显示在前面。然而,尽管有警报窗口级别,键盘仍然会在前面,所以我们也必须手动隐藏它的窗口。重要的是不要将新设置UIWindow
为键或更改第一响应者,UITextField
否则键盘将被关闭。
以前(在 iOS 10 之前?)我们可以侥幸逃脱overlayWindow.makeKeyAndVisible()
,但现在将其设置为 key 将关闭键盘。此外,键盘的窗口现在在每个公开定义的值前面都有一个非标准UIWindow.Level
值。我通过在层次结构中找到键盘的窗口并将其隐藏来解决这个问题。
@objc func handleDoubleTap() {
// Prepare the overlay window
guard let overlayFrame = view?.window?.frame else { return }
overlayWindow = UIWindow(frame: overlayFrame)
overlayWindow?.windowLevel = .alert
let overlayVC = OverlayViewController.init(nibName: "OverlayViewController", bundle: nil)
overlayWindow?.rootViewController = overlayVC
overlayVC.delegate = self
// The keyboard's window always appears to be the last in the hierarchy.
let keyboardWindow = UIApplication.shared.windows.last
keyboardWindow?.isHidden = true
}
func optionChosen(option: YourOptionsEnum) {
// Your code goes here. Take action based on the option chosen.
// ...
// Dismiss the overlay and show the keyboard
overlayWindow = nil;
UIApplication.shared.windows.last?.isHidden = false
}
我现在不能尝试这个,但为了其他目的已经实现了类似的。在呈现模态控制器的动作中,我假设手势识别器或委托方法,首先截取屏幕截图并将其放在imageView
当前子视图中。稍后返回时,只需删除imageView
.
听起来可能很疯狂,但我记得在过渡期间键盘移动会导致类似的笨拙行为的过渡中这样做了。实施起来并不难。
如果您在尝试时遇到问题,也许有人会提供一些代码。我可以稍后参考我自己的工作并添加一个示例,但现在不行。
@Rob Bajorek 的回答非常好。对于 iOS 9,10,有一些小的变化。
而不是代码:
[self.overlayWindow setWindowLevel:UIWindowLevelAlert];
[self.overlayWindow makeKeyAndVisible];
输入以下代码:
NSArray *windows = [[UIApplication sharedApplication] windows];
UIWindow *lastWindow = (UIWindow *)[windows lastObject];
[self.overlayWindow setWindowLevel:lastWindow.windowLevel + 1];
[self.overlayWindow setHidden:NO];
为了使键盘显示任何文本接受字段,例如UITextField or UITextView or UISearchBar
应该是第一响应者,并且它们应该在视图中可见。这意味着响应视图应该位于窗口的顶层层次结构中。
如果您不需要此效果,ViewController
您可以添加ViewController.view
作为带有动画的 self.view 的子视图,而不是呈现。
您可以访问 iOS 中的键盘框架。
您需要实现代码来监听键盘通知(如 UIKeyboardWillShowNotification 和 UIKeyboardWillChangeFrameNotification)。该通知将向您发送有关键盘框架的信息。
请查看windows 参考中“键盘通知用户信息键”的描述。
你会发现对你有用的目的:
UIKeyboardBoundsUserInfoKey一个 NSValue 对象的键,它包含一个 CGRect,它在窗口坐标中标识键盘的边界矩形。该值足以获得键盘的大小。如果要获取屏幕上键盘的来源(动画之前或之后),请使用通过 UIKeyboardCenterBeginUserInfoKey 或 UIKeyboardCenterEndUserInfoKey 常量从用户信息字典中获取的值。
使用键盘框架的信息,您可以在那里显示模态视图。
只需在您的文本字段和 UITextfield *flagTextfield 中添加一个点击手势;
UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(DoubleTapMethod:)];
doubleTap.numberOfTapsRequired = 2;
[self.txtTest addGestureRecognizer:doubleTap];
-(void)DoubleTapMethod:(UITapGestureRecognizer *)gesture
{
[flagTextfield resignFirstResponder];
NSLog(@"DoubleTap detected");
//Set your logic on double tap of Textfield...
//presents a modal view controller
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
flagTextfield = textfield;
}