首先让我说我玩程序化,但我现在是新手。
我有程序化视图和故事板对象的混合:
StoryBoard对象:
程序化观点:
当我按下按钮时,添加了viewForMessageLabel
。在viewDidLoad
我添加了一个点击手势,以便在点按背景时删除viewForMessageLabel
。我还将相同的点按手势添加到textField,以移除viewForMessageLabel
(如果它存在)。我再次向textField添加相同的点击手势以将其删除。
如果键盘存在,我会在viewDidLoad
中向textField添加另一个点击手势以解除它。我注意到事情很古怪,我失去了触摸事件。
如果我在触摸背景时按下按钮添加标签,它就不会被解雇。如果我按下textField,它将关闭它并显示键盘。如果再次按下按钮,textField仍然处于启动状态,标签出现,我再次按下textField,没有任何反应。当我按下返回以隐藏键盘(我实现了方法)时,键盘消失,按下按钮,出现viewForMessageLabel
,现在当我按下textField时viewForMessageLabel
消失。基本上,textField也会发生同样的事情。
我想要的是
如果viewForMessageLabel
存在,我按下背景,textField或textView,它应该会消失。
如果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 :(得分: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()
}
答案 1 :(得分:1)
这并没有完全回答这个问题,但我找到了一个解决方法。如果我使用@Toddg建议的方法:
func removeLabelAndHideKeyboard() {
viewForMessageLabel.removeFromSuperview()
textField.resignFirstResponder()
}
它添加了将textField重新签名给极大帮助的函数。
同样在viewDidLoad里面我添加了:
textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown)
关键是使用 .touchDown 和NOT .editingDidBegin。这样我就可以在textField和textView之间来回切换,键盘会响应两者。我不得不在textView的键盘上添加另外一个-a toolBar,它上面有Done按钮以关闭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)
}
}