斯威夫特的iOS -Remove查看文本字段时,TextView的,和背景抽头,但失去活动

问题描述:

enter image description hereenter image description here斯威夫特的iOS -Remove查看文本字段时,TextView的,和背景抽头,但失去活动

首先我要说我玩的计划,但我目前在这一个新手。

我的纲领性观点和故事板对象的组合:

故事板对象:

  1. 按钮
  2. 文本字段
  3. 的TextView

纲领性意见:

  1. messageLabel
  2. viewForMessageLabel

在按下该按钮的viewForMessageLabel加入。在viewDidLoad我点击背景时添加一个轻击手势以删除viewForMessageLabel。我还将相同的轻击手势添加到文本字段以删除viewForMessageLabel(如果存在)。我再次将相同的轻击手势添加到textField以将其删除。

如果键盘存在,我会在viewDidLoad的文本字段中添加另一个轻击手势,以解除它。我注意到事情是古怪的,我失去了触摸事件。

如果我按下按钮添加标签,当我触摸背景时,它不会被解雇。如果我按下textField,它将关闭它并显示键盘。如果我再次按下按钮,textField仍然显示,则会出现标签,我再次按下textField并且没有任何反应。当我按回车键隐藏键盘(我实现了该方法)时,键盘消失,按下按钮,出现viewForMessageLabel,而我现在当我按下textField时,viewForMessageLabel消失。 textField基本上也是如此。

我要的是

  1. 如果viewForMessageLabel存在,并且我按无论是背景,文本框,或TextView的就应该消失。

  2. 如果textField或textView的键盘存在,我按下背景键盘也应该消失。

我的代码:

class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate { 

    //MARK:- Outlets 
    @IBOutlet weak var textField: UITextField! 
    @IBOutlet weak var textView: UITextView! 
    @IBOutlet weak var button: UIButton! 

    let messagelabel: UILabel = { 
     let label = UILabel() 
     label.translatesAutoresizingMaskIntoConstraints = false 
     label.text = "Pizza Pizza Pizza Pizza Pizza" 
     label.font = UIFont(name: "Helvetica-Regular", size: 17) 
     label.sizeToFit() 
     label.numberOfLines = 0 
     label.textAlignment = .center 
     label.textColor = UIColor.white 
     label.backgroundColor = UIColor.clear 
     return label 
    }() 

    let viewForMessageLabel: UIView = { 
     let view = UIView() 
     view.translatesAutoresizingMaskIntoConstraints = false 
     view.backgroundColor = UIColor.red 
     return view 
    }() 

    //View Controller Lifecycle 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     textField.delegate = self 
     textView.delegate = self 

     // 0. hide viewForMessageLabel is background is tapped 
     let tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeViewForMessageLabel)) 
     view.addGestureRecognizer(tapGesture) 

     // 1. hide viewForMessageLabel if textView is tapped 
     textView.addGestureRecognizer(tapGesture) 

     // 2. hide keyboard if background if tapped 
     let hideKeyboard = UITapGestureRecognizer(target: self, action: #selector(hideKeyboardWhenBackGroundTapped)) 
     view.addGestureRecognizer(hideKeyboard) 

     // 3. hide keyboard if textView is tapped 
     textView.addGestureRecognizer(hideKeyboard) 

     // 4. hide viewForMessageLabel for textField if background is tapped 
     textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .editingDidBegin) 

    } 

    //MARK:- Button 
    @IBAction func buttonPressed(_ sender: UIButton) { 
     view.addSubview(viewForMessageLabel) 
     setViewForMessageLabelAnchors() 
     setMessageLabelAnchors() 
    } 

    //MARK:- Functions 
    func setViewForMessageLabelAnchors(){ 
     viewForMessageLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 44).isActive = true 
     viewForMessageLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true 
     viewForMessageLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true 
     viewForMessageLabel.addSubview(messagelabel) 
    } 

    func setMessageLabelAnchors(){ 
     messagelabel.topAnchor.constraint(equalTo: viewForMessageLabel.topAnchor, constant: 0).isActive = true 
     messagelabel.widthAnchor.constraint(equalTo: viewForMessageLabel.widthAnchor).isActive = true 
     viewForMessageLabel.bottomAnchor.constraint(equalTo: messagelabel.bottomAnchor, constant: 0).isActive = true 
    } 

    func removeViewForMessageLabel(){ 
     viewForMessageLabel.removeFromSuperview() 
    } 

    func hideKeyboardWhenBackGroundTapped(){ 
     textField.resignFirstResponder() 
    } 

    //MARK:- TextField Delegate 
    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     view.endEditing(true) 
     return true 
    } 

    func textViewDidBeginEditing(_ textView: UITextView) { 
     removeViewForMessageLabel() 
    } 

    //MARK:- TextView Delegate 
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { 
     if(text == "\n") { 
      textView.resignFirstResponder() 
      return false 
     } 
     return true 
    } 
} 
+0

你有很多重叠的轻拍手势识别器。默认情况下,我不确定点击是否通过。有点似乎你太过于复杂。 – toddg

+0

@托德谢谢。我刚刚阅读了一篇文章,表示可以将其他操作添加到同一个水龙头中。我要去尝试一下。你为什么说我过于复杂呢? –

这并不完全回答这个问题,但我发现周围的工作。如果我使用的方法@Toddg建议:

func removeLabelAndHideKeyboard() { 
    viewForMessageLabel.removeFromSuperview() 
    textField.resignFirstResponder() 
} 

它增加了resigning textField到帮助巨大的功能。

也在里面viewDidLoad中我加:

textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown) 

的关键有使用.touchDown和NOT .editingDidBegin。这样我就可以在textField和textView之间来回切换,并且键盘会响应这两者。我不得不1个件事-a工具栏添加到TextView的键盘已经完成按钮就可以了驳回的TextView:

func addDoneButtonOnKeyboard(){ 
     let toolBar = UIToolbar() 
     toolBar.sizeToFit() 
     doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissKeyboard)) 
     toolBar.setItems([doneButton!], animated: true) 
     textView.inputAccessoryView = toolBar 
    } 

    @objc func dismissTextViewKeyboard(){ 
     view.endEditing(true) 
    } 

这样,当TextView的存在,我可以关闭它。

在所有情况下,如果我按下textField,background或textView并且存在viewForMessageLabel,它将消失。

如果textField是第一响应者,并且它的键盘存在,我按背景它将消失。

我还没有想出如何在除了其他所有东西之外还触摸背景的时候关闭textView,所以我在toolBar上实现了一个Done按钮。如果按下该按钮,textView的键盘将会在调用我添加的dismissTextViewKeyboard()函数时被取消。两者都位于底部,其他所有内容都位于viewDidLoad中。

如果有人有更好的答案我会投它。

class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate { 


    //MARK:- Outlets 
    @IBOutlet weak var textField: UITextField! 
    @IBOutlet weak var textView: UITextView! 
    @IBOutlet weak var button: UIButton! 

    let messagelabel: UILabel = { 
     let label = UILabel() 
     label.translatesAutoresizingMaskIntoConstraints = false 
     label.text = "Pizza Pizza Pizza Pizza Pizza" 
     label.font = UIFont(name: "Helvetica-Regular", size: 17) 
     label.sizeToFit() 
     label.numberOfLines = 0 
     label.textAlignment = .center 
     label.textColor = UIColor.white 
     label.backgroundColor = UIColor.clear 
     return label 
    }() 

    let viewForMessageLabel: UIView = { 
     let view = UIView() 
     view.translatesAutoresizingMaskIntoConstraints = false 
     view.backgroundColor = UIColor.red 
     return view 
    }() 

    fileprivate var doneButton: UIBarButtonItem? 

    //View Controller Lifecycle 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     textField.delegate = self 
     textView.delegate = self 

     let tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeViewForMessageLabel)) 
     view.addGestureRecognizer(tapGesture) 

     textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown) 

     addDoneButtonOnKeyboard() 
    } 

    //MARK:- Button 
    @IBAction func buttonPressed(_ sender: UIButton) { 
     //removeMessage() 
     view.addSubview(viewForMessageLabel) 
     setBackgroundAnchors() 
     setMessageAndLabelAnchors() 
    } 

    //MARK:- Functions 
    func setBackgroundAnchors(){ 
     viewForMessageLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 44).isActive = true 
     viewForMessageLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true 
     viewForMessageLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true 
     viewForMessageLabel.addSubview(messagelabel) 
    } 

    func setMessageAndLabelAnchors(){ 

     messagelabel.topAnchor.constraint(equalTo: viewForMessageLabel.topAnchor, constant: 0).isActive = true 
     messagelabel.widthAnchor.constraint(equalTo: viewForMessageLabel.widthAnchor).isActive = true 
     viewForMessageLabel.bottomAnchor.constraint(equalTo: messagelabel.bottomAnchor, constant: 0).isActive = true 
    } 

    func removeViewForMessageLabel(){ 
     viewForMessageLabel.removeFromSuperview() 
     textField.resignFirstResponder() 
    } 

    //MARK:- TextField Delegate 
    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     view.endEditing(true) 
     return true 
    } 

    func textViewDidBeginEditing(_ textView: UITextView) { 
     removeViewForMessageLabel() 
    } 

    //MARK:- TextView Delegate 
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { 
     if(text == "\n") { 
      textView.resignFirstResponder() 
      return false 
     } 
     return true 
    } 

    //MARK:- Additional Functions 
    //add a done button to the keyboard when the textView is first responder 
    fileprivate func addDoneButtonOnKeyboard(){ 
     let toolBar = UIToolbar() 
     toolBar.sizeToFit() 
     doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissTextViewKeyboard)) 
     toolBar.setItems([doneButton!], animated: true) 
     textView.inputAccessoryView = toolBar 
    } 

    //dismiss the keyboard when the Done button is tapped 
    @objc func dismissTextViewKeyboard(){ 
     view.endEditing(true) 
    } 
} 

  1. 如果TextField的或TextView的键盘存在并且我按下键盘也应该消失的背景。
开始=>

您呈现这个就像是在当前是否显示键盘的条件,但您的代码不反映(它不应该)。您可以随时拨打resignFirstResponder多次,并且不会发生任何不良情况。您也可以在已被删除的视图上致电removeFromSuperview(请参阅here)。

因此,我认为你可以只连接到一个水龙头手势识别一个动作:

var tapGesture: UITapGestureRecognizer? 

override func viewDidLoad() { 
    super.viewDidLoad() 

    textField.delegate = self 
    textView.delegate = self 

    // 0. hide viewForMessageLabel is background is tapped 
    tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeLabelAndHideKeyboard)) 
    view.addGestureRecognizer(tapGesture) 

    // 1. hide viewForMessageLabel if textView is tapped 
    textView.addGestureRecognizer(tapGesture) 
} 

func removeLabelAndHideKeyboard() { 
    viewForMessageLabel.removeFromSuperview() 
    textField.resignFirstResponder() 
} 
+0

感谢您的帮助!我会尽快在几小时后回家尝试 –

+0

让我知道结果如何。 – toddg

+0

酷,我得到了你 –