斯威夫特的iOS -Remove查看文本字段时,TextView的,和背景抽头,但失去活动
斯威夫特的iOS -Remove查看文本字段时,TextView的,和背景抽头,但失去活动
首先我要说我玩的计划,但我目前在这一个新手。
我的纲领性观点和故事板对象的组合:
故事板对象:
- 按钮
- 文本字段
- 的TextView
纲领性意见:
- messageLabel
- viewForMessageLabel
在按下该按钮的viewForMessageLabel
加入。在viewDidLoad
我点击背景时添加一个轻击手势以删除viewForMessageLabel
。我还将相同的轻击手势添加到文本字段以删除viewForMessageLabel
(如果存在)。我再次将相同的轻击手势添加到textField以将其删除。
如果键盘存在,我会在viewDidLoad
的文本字段中添加另一个轻击手势,以解除它。我注意到事情是古怪的,我失去了触摸事件。
如果我按下按钮添加标签,当我触摸背景时,它不会被解雇。如果我按下textField,它将关闭它并显示键盘。如果我再次按下按钮,textField仍然显示,则会出现标签,我再次按下textField并且没有任何反应。当我按回车键隐藏键盘(我实现了该方法)时,键盘消失,按下按钮,出现viewForMessageLabel
,而我现在当我按下textField时,viewForMessageLabel
消失。 textField基本上也是如此。
我要的是
如果
viewForMessageLabel
存在,并且我按无论是背景,文本框,或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
}
}
这并不完全回答这个问题,但我发现周围的工作。如果我使用的方法@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)
}
}
开始=>
- 如果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()
}
你有很多重叠的轻拍手势识别器。默认情况下,我不确定点击是否通过。有点似乎你太过于复杂。 – toddg
@托德谢谢。我刚刚阅读了一篇文章,表示可以将其他操作添加到同一个水龙头中。我要去尝试一下。你为什么说我过于复杂呢? –