【发布时间】:2015-10-14 23:03:15
【问题描述】:
我正在创建一个包含多个 UIViewControllers 的注册向导。
我目前已经设置好了,所以用户输入他的电子邮件,单击键盘上的“开始”按钮,然后下一个 UIViewController 从右侧滑入,用户将在其中输入他的姓名。但问题是,当我调用presentViewController 将下一个UIViewController 带入时,它会关闭键盘。
我希望键盘在切换ViewControllers 时始终保持打开状态。如果您查看 Facebook 的 iOS 应用程序,他们会在他们的注册页面上做我正在尝试做的事情。
任何帮助或建议将不胜感激。我读过一些关于使用覆盖窗口的文章,但不知道如何去做,因为我的注册向导中有多个 UIViewController。
这是我在注册向导中的初始控制器:
class SignUpEmailViewController: UIViewController {
var titleLabel = UILabel.newAutoLayoutView()
var emailField = SignUpTextField(placeholder: "Enter your email address")
var emailLabel = UILabel.newAutoLayoutView()
var continueButton = SignUpContinueButton.newAutoLayoutView()
var footerView = SignUpFooterView.newAutoLayoutView()
let presentAnimationController = PushInFromLeftAnimationController()
let dismissAnimationController = PushInFromRightAnimationController()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupGestures()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
emailField.becomeFirstResponder()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupViews() {
view.backgroundColor = UIColor.colorFromCode(0xe9eaed)
titleLabel.text = "Get Started"
titleLabel.font = UIFont(name: "AvenirNextLTPro-Demi", size: 18)
titleLabel.textColor = Application.greenColor
emailField.enablesReturnKeyAutomatically = true
emailField.returnKeyType = .Go
emailField.delegate = self
emailLabel.text = "You'll use this email when you log in and if you ever need to reset your password."
emailLabel.font = UIFont(name: "AvenirNextLTPro-Regular", size: 13)
emailLabel.textColor = .colorFromCode(0x4e5665)
emailLabel.numberOfLines = 0
emailLabel.textAlignment = .Center
continueButton.addTarget(self, action: "continueButtonPressed", forControlEvents: .TouchUpInside)
continueButton.hidden = true
view.addSubview(titleLabel)
view.addSubview(emailField)
view.addSubview(emailLabel)
view.addSubview(continueButton)
view.addSubview(footerView)
setupConstraints()
}
func setupGestures() {
let gestureRecognizer = UISwipeGestureRecognizer(target: self, action: "swipeHandler")
gestureRecognizer.direction = .Down
view.addGestureRecognizer(gestureRecognizer)
let tapGesture = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tapGesture)
}
func setupConstraints() {
titleLabel.autoAlignAxisToSuperviewAxis(.Vertical)
titleLabel.autoPinEdgeToSuperviewEdge(.Top, withInset: screenSize.height * 0.2)
emailField.autoAlignAxisToSuperviewAxis(.Vertical)
emailField.autoPinEdge(.Top, toEdge: .Bottom, ofView: titleLabel, withOffset: 15)
emailField.autoSetDimensionsToSize(CGSize(width: screenSize.width * 0.85, height: 40))
emailLabel.autoAlignAxisToSuperviewAxis(.Vertical)
emailLabel.autoPinEdge(.Top, toEdge: .Bottom, ofView: emailField, withOffset: 10)
emailLabel.autoSetDimension(.Width, toSize: screenSize.width * 0.85)
continueButton.autoAlignAxisToSuperviewAxis(.Vertical)
continueButton.autoPinEdge(.Top, toEdge: .Bottom, ofView: emailField, withOffset: 10)
continueButton.autoSetDimensionsToSize(CGSize(width: screenSize.width * 0.85, height: 30))
footerView.autoSetDimension(.Height, toSize: 44)
footerView.autoPinEdgeToSuperviewEdge(.Bottom)
footerView.autoPinEdgeToSuperviewEdge(.Leading)
footerView.autoPinEdgeToSuperviewEdge(.Trailing)
}
override func prefersStatusBarHidden() -> Bool {
return true
}
func swipeHandler() {
dismissViewControllerAnimated(true, completion: nil)
}
func continueButtonPressed() {
presentNextViewController()
}
func dismissKeyboard() {
view.endEditing(true)
}
func presentNextViewController() {
let toViewController = SignUpNameViewController()
toViewController.transitioningDelegate = self
toViewController.firstNameField.becomeFirstResponder()
presentViewController(toViewController, animated: true, completion: nil)
}
}
extension SignUpEmailViewController: UIViewControllerTransitioningDelegate {
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return presentAnimationController
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return dismissAnimationController
}
}
extension SignUpEmailViewController: UITextFieldDelegate {
func textFieldShouldReturn(textField: UITextField) -> Bool {
presentNextViewController()
return true
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
continueButton.hidden = true
emailLabel.hidden = false
return true
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
continueButton.hidden = false
emailLabel.hidden = true
return true
}
}
这是我要展示的控制器:
class SignUpNameViewController: UIViewController, UIViewControllerTransitioningDelegate {
var titleLabel = UILabel.newAutoLayoutView()
var textFieldContainer = UIView.newAutoLayoutView()
var firstNameField = SignUpTextField(placeholder: "First name")
var lastNameField = SignUpTextField(placeholder: "Last name")
var continueButton = SignUpContinueButton.newAutoLayoutView()
var footerView = SignUpFooterView.newAutoLayoutView()
let presentAnimationController = PushInFromLeftAnimationController()
let dismissAnimationController = PushInFromRightAnimationController()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
firstNameField.becomeFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupGestures()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupViews() {
view.backgroundColor = UIColor.colorFromCode(0xe9eaed)
titleLabel.text = "What's your name?"
titleLabel.font = UIFont(name: "AvenirNextLTPro-Demi", size: 18)
titleLabel.textColor = Application.greenColor
firstNameField.returnKeyType = .Next
firstNameField.enablesReturnKeyAutomatically = true
lastNameField.returnKeyType = .Next
lastNameField.enablesReturnKeyAutomatically = true
continueButton.addTarget(self, action: "continueButtonPressed", forControlEvents: .TouchUpInside)
view.addSubview(titleLabel)
view.addSubview(textFieldContainer)
textFieldContainer.addSubview(firstNameField)
textFieldContainer.addSubview(lastNameField)
view.addSubview(continueButton)
view.addSubview(footerView)
setupConstraints()
}
func setupGestures() {
let gestureRecognizer = UISwipeGestureRecognizer(target: self, action: "swipeHandler")
gestureRecognizer.direction = .Right
view.addGestureRecognizer(gestureRecognizer)
let tapGesture = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tapGesture)
}
func setupConstraints() {
titleLabel.autoAlignAxisToSuperviewAxis(.Vertical)
titleLabel.autoPinEdgeToSuperviewEdge(.Top, withInset: screenSize.height * 0.2)
textFieldContainer.autoPinEdge(.Top, toEdge: .Bottom, ofView: titleLabel, withOffset: 15)
textFieldContainer.autoAlignAxisToSuperviewAxis(.Vertical)
textFieldContainer.autoSetDimensionsToSize(CGSize(width: screenSize.width * 0.8, height: 40))
let spaceBetweenTextFields: CGFloat = 5
let textFieldSize = ((screenSize.width * 0.8) - spaceBetweenTextFields) / 2
let textFields: NSArray = [firstNameField, lastNameField]
textFields.autoDistributeViewsAlongAxis(.Horizontal, alignedTo: .Horizontal, withFixedSize: textFieldSize, insetSpacing: false)
firstNameField.autoPinEdgeToSuperviewEdge(.Top)
firstNameField.autoPinEdgeToSuperviewEdge(.Bottom)
lastNameField.autoPinEdgeToSuperviewEdge(.Top)
lastNameField.autoPinEdgeToSuperviewEdge(.Bottom)
continueButton.autoAlignAxisToSuperviewAxis(.Vertical)
continueButton.autoPinEdge(.Top, toEdge: .Bottom, ofView: textFieldContainer, withOffset: 10)
continueButton.autoSetDimensionsToSize(CGSize(width: screenSize.width * 0.8, height: 30))
footerView.autoSetDimension(.Height, toSize: 44)
footerView.autoPinEdgeToSuperviewEdge(.Bottom)
footerView.autoPinEdgeToSuperviewEdge(.Leading)
footerView.autoPinEdgeToSuperviewEdge(.Trailing)
}
override func prefersStatusBarHidden() -> Bool {
return true
}
func dismissKeyboard() {
view.endEditing(true)
}
func swipeHandler() {
dismissViewControllerAnimated(true, completion: nil)
}
func continueButtonPressed() {
let toViewController = SignUpPasswordViewController()
toViewController.transitioningDelegate = self
presentViewController(toViewController, animated: true, completion: {})
}
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return presentAnimationController
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return dismissAnimationController
}
}
这是我的自定义过渡:
class PushInFromLeftAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.35
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let finalFrameForVC = transitionContext.finalFrameForViewController(toViewController)
let containerView = transitionContext.containerView()
let bounds = UIScreen.mainScreen().bounds
toViewController.view.frame = CGRectOffset(finalFrameForVC, bounds.size.width, 0)
containerView!.addSubview(toViewController.view)
UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {
fromViewController.view.frame = CGRectOffset(finalFrameForVC, -bounds.size.width, 0)
toViewController.view.frame = finalFrameForVC
}, completion: {
finished in
transitionContext.completeTransition(true)
})
}
}
【问题讨论】:
-
在这个问题上查看我的 cmets:stackoverflow.com/q/33127863/341994
-
嘿@matt,我检查了你的答案并更新了我的问题以显示我的代码。知道当他们在注册向导中从 ViewController 切换到 ViewController 时,facebook 是如何保持键盘打开的吗?也许他们实际上并没有切换视图控制器,而是只是动画 TextFields 滑入?
-
或者是向获得第一响应者角色的窗口添加 UITextField 的唯一解决方案?这似乎有点乱
-
问题是,正如我们在其他 cmets 中讨论的那样,只有视图层次结构中的视图才能成为第一响应者。也许您可以通过自定义过渡动画来解决这个问题,因为这样您就可以完全控制整个过程中的视图。实际上,看起来您可能已经在这样做了。
-
我也是这么想的@matt。我更新了我的问题以显示我的自定义转换。我从来没有从视图层次结构中删除 fromViewController 的视图,我只是将它滑出屏幕,这就是为什么我不确定为什么键盘仍然被关闭的原因。
标签: ios swift uiviewcontroller wizard presentviewcontroller