【问题标题】:Keyboard to move the view only if the textfield is hidden仅在隐藏文本字段时使用键盘移动视图
【发布时间】:2016-07-24 04:15:43
【问题描述】:

我正试图让我的应用程序在键盘出现时移动视图,到目前为止,结果...至少可以说是混杂的。我可以让它移动,问题是它要么是硬编码的,要么只能部分工作。

我的视图中有多个文本字段,当我点击它们时,有时取决于我的滚动位置,它会被键盘隐藏。

现在我需要我的应用程序做的是仅当活动文本字段被键盘隐藏时才移动视图以查看文本字段。

我的视图层次结构如下:

所以我有一个滚动视图,在滚动视图中我有一个名为 ContentView 的 UIView,在 ContentView 中我有我所有的文本字段和标签。

问题是,我无法对其进行硬编码,因为我的应用程序是通用的,只有当它隐藏文本字段时,我才需要让键盘移动视图。因为在用户使用 iPad 的情况下,视图可能永远不必移动

我使用了以下堆栈溢出答案但没有结果:

Swift: Scroll View only when a TextField or Button is hidden by the Keyboard

Move view with keyboard using Swift

这是我的代码,实际上来自这些答案之一:

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(NewPaxController.keyboardWillShow), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(NewPaxController.keyboardWillHide), name: UIKeyboardWillHideNotification, object: nil)

}



func keyboardWillShow(notification:NSNotification) {
    if keyboardIsPresent == false {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            self.ContentView.frame.origin.y -= keyboardSize.height
            keyboardIsPresent = true
        }
    }
}

func keyboardWillHide(notification:NSNotification) {
    if keyboardIsPresent == true {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            self.ContentView.frame.origin.y += keyboardSize.height
            keyboardIsPresent = false
        }
    }
}

我几乎 100% 确定我所有的错误都来自我有一个 ContentView 的事实......但在我的情况下我需要它。提前感谢您的帮助

【问题讨论】:

  • 如果我给你Objective c中的代码,会有帮助吗?我不知道斯威夫特
  • 确实可以!我不知道目标 C,但我可能可以从中得到正确的想法。另外,我之前已经转换了 Obj-C 代码以满足我的需求!如果我迷路了,我会通知你
  • 问题是不管文本字段是否隐藏,它总是移动视图?
  • 是的!同样,当我关闭键盘时,视图会向下滚动太多,留下一个空白空间,其上方的键盘高度

标签: ios swift user-interface uiscrollview keyboard


【解决方案1】:

这是它的代码,很简单,但如果你仍然需要帮助,我会进一步解释。

#pragma mark - Keyboard Observer events

-(void)keyboardWillShow:(NSNotification*)notification {

    NSDictionary *info = [notification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    keyboardHeight = kbSize.height;
    [self updateScrollViewPosition];
}

-(void)keyboardDidChange:(NSNotification *)notification {

    NSDictionary *info = [notification userInfo];
    CGSize kbSizeBegin = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGSize kbSizeEnd = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    if (kbSizeBegin.height != kbSizeEnd.height) {
        keyboardHeight = kbSizeEnd.height;
        if (activeTextField && [activeTextField isFirstResponder]) {
            [self updateScrollViewPosition];
        }
    }
}

-(void)keyboardWillHide:(NSNotification*)notification {

    keyboardHeight = 0;
    activeTextField = nil;
    [self resignAllTextFields];
}

#pragma mark - UITextFieldDelegate Methods

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    activeTextField = textField;
    return YES;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField {

    activeTextField = textField;
    [self updateScrollViewPosition];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {

    keyboardHeight = 0;
    activeTextField = nil;
    [textField resignFirstResponder];
    return YES;
}

#pragma mark - Update Method

-(void)updateScrollViewPosition {

    if (keyboardHeight > 0 && activeTextField) {
        CGRect frame = activeTextField.frame;
        CGFloat yPoint = scrollView.frame.origin.y+frame.origin.y+frame.size.height+8.0;
        CGFloat height = self.view.frame.size.height-keyboardHeight;
        CGFloat diff = yPoint-height;
        if (diff > 0.0) {
            [scrollView setContentOffset:CGPointMake(0, diff) animated:YES];
        }
        else {
            CGFloat diff = scrollView.contentSize.height-scrollView.contentOffset.y;
            if (diff<scrollView.frame.size.height) {
                diff = scrollView.contentSize.height-scrollView.frame.size.height;
                if (diff < 0) {
                    diff = 0.0;
                }
                [scrollView setContentOffset:CGPointMake(0, diff) animated:YES];
            }
        }
    }
    else {
        CGFloat diff = scrollView.contentSize.height-scrollView.contentOffset.y;
        if (diff<scrollView.frame.size.height) {
            diff = scrollView.contentSize.height-scrollView.frame.size.height;
            if (diff < 0) {
                diff = 0.0;
            }
            [scrollView setContentOffset:CGPointMake(0, diff) animated:YES];
        }
    }
}

#pragma mark

编辑:根据要求提供一个简单的resignAllTextFields 方法。 containerView 是包含所有UITextField 的视图。

-(void)resignAllTextFields {

    for (UIView *view in containerView.subviews) {
        if ([view isKindOfClass:[UITextField class]]) {
            UITextField *textField = (UITextField*)view;
            [textField resignFirstResponder];
        }
    }
    [self updateScrollViewPosition];
}

【讨论】:

  • 非常感谢 Abdul,我会继续尝试转换它,但我认为它只是对我的代码块的补充,那是很多 Obj-c !!...我不幸的是没有足够的知识来使用它!
  • 能否提供resignAllTextFields的代码,谢谢
  • 它通常取决于视图的层次结构,它只包含调用 resignFirstResponder 的 textfield/textview 对象的代码。如果你的观点很复杂,我可以为它写一个递归代码。如果它更简单,例如您的字段存在于一个父视图中,则可以在其子视图上放置一个 for 循环,如果子视图是 textfield/textview 则调用此函数。
【解决方案2】:

当键盘出现时,您不应该修改框架

相反,您需要将滚动视图scrollView.contentInset.bottom 的底部插入从零设置为键盘高度。当键盘消失时,您将 inset 设置回零。

这整个问题只需要 10 行代码就可以解决。

字面上从通知中获取键盘高度,在显示 KB 时将其存储在类中的局部变量中,并使用该值在委托回调/事件处理程序方法中设置插入。

这里的诀窍是,设置非零插图将有效地将滚动视图与内容一起向上滚动,并将当前文本字段向上推。

【讨论】:

  • 除了设置 scrollView 插图之外,我在 KeyboardWillShow 方法中所做的键盘高度是不是完全一样??
  • 我只是在我的代码中这样做了,试图简单地将self.ContentView.frame.origin.y -= keyboardSize.height 修改为self.ScrollView.contentInset.bottom -= keyboardSize.height 并且视图根本没有移动......
  • 好吧,您确实设置了负插图,您应该将插图设置为 kb 高度...而不是从原始插图中减去高度
  • 就是这样!只需将self.ContentView.frame.origin.y -= keyboardSize.height 更改为self.ScrollView.contentInset.bottom = keyboardSize.height !非常感谢!
【解决方案3】:

您应该首先尝试使用以下代码定位UITextField 实例。

extension UIView {

    func firstResponder() -> UIView? {
        if self.isFirstResponder() {
            return self
        }

        for subview in self.subviews {
            if subview.isFirstResponder() {
                return subview
            }
        }

        return nil
    }

}

keyboardWillShow: 函数中决定当键盘出现时文本字段是否可见。

func keyboardWillShow(notification:NSNotification) {
    if keyboardIsPresent == false {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue(),
            let inputView = self.ContentView.firstResponder()
            where inputView.frame.maxY > self.ContentView.frame.size.height - keyboardSize.height {

            self.ContentView.frame.origin.y -= keyboardSize.height
            keyboardIsPresent = true

        }
    }
}

如果视图被移开,则仅在隐藏功能中将视图移回。

【讨论】:

  • 好主意,这有点用,但是:如果启用了预测文本,它会覆盖文本字段的一部分(中间的那个),当我的视图返回时,我有一个巨大的空白空间顶!
猜你喜欢
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 2018-12-22
  • 2021-05-07
  • 1970-01-01
  • 2014-03-18
  • 2011-01-19
  • 1970-01-01
相关资源
最近更新 更多