【问题标题】:Dismiss Keyboard when Touching Sibling触摸同级时关闭键盘
【发布时间】:2015-12-23 02:29:22
【问题描述】:

尽管有所有“关闭键盘”问题,但似乎没有一个涉及此特定场景的问题。

我正在开发具有以下(简化)层次结构的 ViewController:

  • UI 视图
    • UIScrollView
      • UIStackView
        • PLCustomViewOne
          • 用户界面按钮
          • UITextField
        • PLCustomViewTwo
          • 用户界面按钮
          • UITextField

ViewController 是从 XIB 加载的,两个 PLCustomView 也是如此。当用户选择 UIStackViews 包含的任何内容时,我似乎无法看到 endEditing(关闭键盘)的视图。

在视图中添加手势识别器肯定会起作用;但是,这要求层次结构中的每个视图都添加手势识别器,这似乎不太可扩展。这个真实版其实有不少子视图。

我尝试将touchesBegan 中的解除添加到每个自定义视图的 UIView 子类中,但这只会在用户触摸包含 firstResponder 的视图时解除键盘。例如,如果PLCustomViewOne 中的 textField 处于活动状态,则触摸该视图中的其他任何位置都会关闭键盘,但触摸它之外的位置,例如 PLCustomViewTwo,则不会。

【问题讨论】:

  • 你试过了吗[self.scrollvoew endEditing];
  • 您是否建议在顶级 UIView 中添加scrollView.endEditing(true)?问题是在顶级 UIView 上,touchesBegan 没有被调用。
  • @MichaelVoccola 如果以下答案未能解决您的问题,请提供反馈或其他信息。如果是,请关闭问题。

标签: ios iphone swift uiview


【解决方案1】:

在您的视图控制器类中,为您的两个自定义视图创建出口(通过故事板中的 ctrl-drag)

@IBOutlet weak var customViewOne: PLCustomViewOne!
@IBOutlet weak var customViewTwo: PLCustomViewTwo!

通过这些,您应该能够访问您的 UITextField 实例,例如

customViewOne.textField
customViewTwo.textField

(最好在自定义类中将此属性设为非私有)。此外(在您查看控制器类中)创建一个私有 UITextField 属性来保存(可能)当前(/最近使用的)文本字段。

private var currentTextField: UITextField?

重载UIViewController 子类的viewDidLoad 方法以初始化两个“公共”文本字段实例的委托

override func viewDidLoad() {
    super.viewDidLoad()

    // Handle the user input in the text fields through delegate callbacks (and set tags)
    customViewOne.textField.delegate = self
    customViewOne.textField.delegate = self
}

此外,使用UITextFieldDelegate 的两个textFieldShouldReturn(...) 和textFieldDidBeginEditing(...) 方法分别将(活动)文本字段状态作为第一响应者并更新currentTextField 引用。

// UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
    // User finished typing (hit return): hide the keyboard.
    textField.resignFirstResponder()
    return true
}

func textFieldDidBeginEditing(textField: UITextField) {
    currentTextField = textField
}

最后(也在视图控制器类中),将任何可能当前的文本字段作为第一响应者,以防在编辑过程中/或在 任何 UIView

... user does action/tap/gesture elsewhere {
    if let currentTextField = currentTextField {
        currentTextField.resignFirstResponder()
    }
}

这里的关键是您要跟踪哪个文本字段是第一响应者(通过视图控制器中的currentTextField 属性),然后只退出这个文本字段。

【讨论】:

  • 这确实解决了这个问题。它还为访问子视图中的当前文本字段增加了一些额外的灵活性,但代价是额外的复杂性。
  • @MichaelVoccola 很乐意为您提供帮助。
【解决方案2】:

通过将以下内容添加到自定义视图中,我能够达到预期的效果:

private func addTapToResignFirstResponder () {
    let action = UITapGestureRecognizer(target: self, action: Selector("dismissFirstResponder"))
    self.view.addGestureRecognizer(action)
}

func dismissFirstResponder () {
    UIApplication.sharedApplication().sendAction("resignFirstResponder", to:nil, from:nil, forEvent:nil)
}

addTapToResignFirstResponder() 在UIView 的初始化中被调用。

这将全局解除第一响应者,无论它在哪里,而无需参考。

dismissFirstResponder() 也可以在子类中被覆盖以增加灵活性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 2012-10-18
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    相关资源
    最近更新 更多