2015-10-07 31 views
9

链接: UITextField text jumps的UITextField文本跳转为前一个问题的iOS 9

简述: 我ViewController 2个UITextField元素。当登录字段为firstResponder时,

self.passwordField.becomeFirstResponder() 

登录字段中的文本跳转到左上角并返回。而且更重要的是奇怪:这个故障仅再现第一次,那么你需要重新ViewController观察这种行为

这里是毛刺http://tinypic.com/player.php?v=6nsemw%3E&s=8#.VgVb3cuqpHx

我结束了这个视频(不适用于iOS 9工作) :

func textFieldShouldReturn(textField: UITextField) -> Bool { 
    if textField === self.loginField { 
     self.loginField.resignFirstResponder() 
     // Shitty workaround. Hi, Apple! 
     self.loginField.setNeedsLayout() 
     self.loginField.layoutIfNeeded() 

     self.passwordField.becomeFirstResponder() 
     return false 
    } 

    return true 
} 

有没有人被这个bug吓住了?有什么建议么?

键盘通知处理

我的主要观点是UIScrollView的,为此,我改变底部空间,上海华盈,这样用户可以滚动甚至当键盘显示

func keyboardWillShow(notification : NSNotification) { 
    let keyboardInfo = notification.userInfo! 
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue 
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! 

    UIView.animateWithDuration(animDuration, animations: { 
     self.scrollViewBottom.constant = keyboardFrame.height 
     self.view.layoutIfNeeded() 

     let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height 
     if offsetY > 0 { 
      self.scrollView.contentOffset = CGPointMake(0, offsetY) 
     } 
    }) 
} 

func keyboardWillHide(notification : NSNotification) { 
    self.scrollViewBottom.constant = 0 
    self.view.layoutIfNeeded() 
} 

当我发现键盘通知的全部内容在iOS7中,8和9非常不同。所以,在iOS 9中,即使键盘不显示/隐藏,在更改firstResponder时也会发送通知。此外,当我通过点击textField来更改firstResponder(而不是敲击由我的代码处理的键盘上的Next)时,只有KeyboardWillShow通知和没有KeyboardWillHide。至于我,USERINFO有一些垃圾帧值,这里使用记录下一个按钮改变第一响应时(工作正常,无毛刺):

2015年10月7日12:54:13.870 keyboardWillHide: [ UIKeyboardFrameBeginUserInfoKey:的NSRect:{{0,352},{320,216}}, UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460}, UIKeyboardFrameEndUserInfoKey:的NSRect:{{0,568},{320,216}}, UIKeyboardCenterEndUserInfoKey :NSPoint:{160,676}, UIKeyboardAnimationDurationUserInfoKey:0.25, UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect: {{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey: 7] 2015年10月7日12:54:13.896 keyboardWillShow: [UIKeyboardFrameBeginUserInfoKey:的NSRect:{{0,352},{320,216}}, UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460}, UIKeyboardFrameEndUserInfoKey:的NSRect :{{0,352},{320,216}}, UIKeyboardCenterEndUserInfoKey:NSPoint:{160,460}, UIKeyboardAnimationDurationUserInfoKey:0.25, UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:的NSRect: {{0,0},{320 ,216}},UIKeyboardAnimationCurveUserInfoKey:7]

在这里,当我在第二文本字段抽头登录:

2015-10-07 12:55:13。879 keyboardWillShow:[UIKeyboardFrameBeginUserInfoKey:的NSRect:{{0,352}, {320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160, 460},UIKeyboardFrameEndUserInfoKey:的NSRect:{{0,352},{320, 216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{160,460},
UIKeyboardAnimationDurationUserInfoKey:0.25, UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:的NSRect: {{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey:7]

分辨率

我发现我有另一个键盘控制器,它接收键盘通知并制作一些动画。这就是基于你编辑的问题,我可以看到这一点,当你点击键盘上的一个按钮,问题在于

+1

如何处理键盘?你有注册的键盘通知会出现/隐藏?如果是,你可以在那里发布你的代码吗? – haluzak

+0

Tnx的帮助,检查编辑后 – user3237732

+1

你越来越会隐藏通知,因为你在becomeFirstResponder()之前调用resignFirstResponder(),“跳跃”是由keyboardWillShow() – haluzak

回答

7

  1. 你打电话resignFirstResponder()然后becomeFirstResponder()。这通知keyboardWillHide通知,然后keyboardWillShow通知
  2. keyboardWillHide你有self.view.layoutIfNeeded()其布局的视图(和子视图 - 文本字段)没有动画。

因为这个文本字段布局是“固定”的,当你在做keyboardWillShow动画文本字段中的文本不“跳”了,因为你在做keyboardWillHide布局。

但是,当您只需点击另一个文本字段时,只调用keyboardWillShow,布局在文本字段中不是“固定的”,并且在为视图设置动画时,文本会执行“跳转”动画。

这就是为什么当你点击下一个键盘时它不会跳转,但是当你只需点击另一个文本框时它会跳转。

所以我建议把它改成这样:

func textFieldShouldReturn(textField: UITextField) -> Bool { 
    if textField === self.loginField { 
     self.passwordField.becomeFirstResponder() 
     return false 
    } 

    return true 
} 

func keyboardWillShow(notification : NSNotification) { 
    let keyboardInfo = notification.userInfo! 
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue 
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! 

    self.loginField.layoutIfNeeded() 
    self.passwordField.layoutIfNeeded() 

    if keyboardFrame.height != self.scrollViewBottom.constant { 
     UIView.animateWithDuration(animDuration, animations: { 
      self.scrollViewBottom.constant = keyboardFrame.height 
      self.view.layoutIfNeeded() 

      let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height 
      if offsetY > 0 { 
       self.scrollView.contentOffset = CGPointMake(0, offsetY) 
      } 
     }) 
    } 
} 
+0

遗憾的是没有帮助 – user3237732

+0

我甚评论我的键盘通知处理器 - 故障仍然存在 – user3237732

+0

裹这样UIView.performWithoutAnimation({ self.loginField.layoutIfNeeded() self.passwordField.layoutIfNeeded() }) ,而不是它的工作原理 – user3237732

6

TNX到haluzak

func textFieldShouldReturn(textField: UITextField) -> Bool { 
    if textField === self.loginField { 
     self.passwordField.becomeFirstResponder() 
     return false 
    } 

    return true 
} 

func keyboardWillShow(notification : NSNotification) { 
    let keyboardInfo = notification.userInfo! 
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue 
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! 

    UIView.performWithoutAnimation({ 
     self.loginField.layoutIfNeeded() 
     self.passwordField.layoutIfNeeded() 
    }) 

    if keyboardFrame.height != self.scrollViewBottom.constant { 
     UIView.animateWithDuration(animDuration, animations: { 
      self.scrollViewBottom.constant = keyboardFrame.height 
      self.view.layoutIfNeeded() 

      let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height 
      if offsetY > 0 { 
       self.scrollView.contentOffset = CGPointMake(0, offsetY) 
      } 
     }) 
    } 
} 
+2

'performWithoutAnimation'部分对我来说很重要。 – teradyl

0

将这个代码在你的键盘会显示通知,在你做任何动画:

UIView.performWithoutAnimation({ 
    self.yourTextField1.layoutIfNeeded() 
    self.yourTextField2.layoutIfNeeded() 
    //etc. 
}) 
2

我面临同样的问题,当我试图改变第一响应者。这个问题有更好的解决方案。只需实现UITextField子类并用于可以动画文本字段的地方(键盘,首先响应切换等)。有关问题

@interface UITextFieldFixed : UITextField 

@end 

@implementation UITextFieldFixed 

- (BOOL)resignFirstResponder 
{ 
    BOOL result = [super resignFirstResponder]; 
    [self setNeedsLayout]; 
    [self layoutIfNeeded]; 
    return result; 
} 

@end 

更多信息:https://github.com/foundry/UITextFieldBug

复制并粘贴Swift3 ...

class UITextFieldFixed: UITextField { 
    override func resignFirstResponder() -> Bool { 
     let r = super.resignFirstResponder() 
     self.setNeedsLayout() 
     self.layoutIfNeeded() 
     return r 
    } 
} 
+0

这是梦幻般的帖木儿,谢谢。我在Swift3中粘贴了相同的内容 - 随意编辑或撤消帖木儿! – Fattie

+0

@JoeBlow谢谢! –

+0

发送赏金在这里很好的回答 – Fattie

0

以下是你需要编写文本停止跳跃简单的代码。这对我来说很有用。

func textFieldDidEndEditing(_ textField: UITextField) { // Workaround for the jumping text bug. textField.resignFirstResponder() textField.layoutIfNeeded() }