I'm using a UITextField to show results of a calculation but I don't want the keyboard to appear when the user taps on the UITextField.
I'm using a UITextField because I still want the user to be able to Copy and Paste the calculation back into the UITextField, but I don't want the keyboard to show up.
UIKeyboardWillHide only works after the keyboard is displayed.
Swift 4.2, This works for me.
put in viewDidLoad()
//It will Hide Keyboard
textField.inputView = UIView()
//It will Hide Keyboard tool bar
textField.inputAccessoryView = UIView()
//It will Hide the cursor
textField.tintColor = .white
Its quite simple to do with UITextField. Use this code in viewDidLoad()
self.txtresult.inputView = UIView()
self.txtresult.inputAccessoryView = UIView()
For iPads, according to this response of #Awais Jamil, add the following code
textField.inputAssistantItem.leadingBarButtonGroups = []
textField.inputAssistantItem.trailingBarButtonGroups = []
First set delegate with your UITextField in self class.
You can do with below 2 ways.
1. From storyboard
2. From Code ( You can write at viewDidLoad() )
textField.delegate = self
Then declare protocol UITextFieldDelegate in your class.
Now call delegate method.
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return true
}
textField.inputView = UIView()
This line of code in your textFieldDidBeginEditing func will do the job.
My func:
func textFieldDidBeginEditing(_ textField: UITextField) {
keyboardView.activeTextField = textField
textField.inputView = UIView()
}
You can hide keyboard in UITextFieldDelegate method textFieldDidBeginEditing:(textField: UITextField) like below :
func textFieldDidBeginEditing:(textField: UITextField) {
self.view.endEditing(true)
}
you could use an "empty" inputview like this:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
let inputView = UIView(frame: .zero)
inputView.backgroundColor = UIColor.clearColor()
inputView.opaque = false
textField.inputView = inputView
return true
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
You can try this as well VIA text field delegate method.
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.resignFirstResponder()
// your custom impl
}
Related
I'm trying to give a background color to a UITextField using SwiftUI since I'm trying to use some unique colours in my app to support both LightMode and DarkMode.
My colors are always defined as a ColorSet in the xcassets folder and this is the code I was using at first to achieve this background color.
TextField("Exam title", text: $title)
.padding()
.background(Color("cardBackground"))
.cornerRadius(8)
This way I'm able to change the background color of the TextField when I'm not using it.
This is how's the outcome of this
Correct Look
The problem I'm facing is that as soon as I tap on the TextField it goes back to its default color (I think it is the default one) and I'm unable to change that.
When editing
So what I did was creating a UIViewRepresentable implementation of the TextField, maybe that could have helped me much more than SwiftUI can do at this stage.
struct CustomUIKitTextField: UIViewRepresentable {
#Binding var text: String
var placeholder: String
var backgroundColor: UIColor = .red
func makeUIView(context: UIViewRepresentableContext<CustomUIKitTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
textField.placeholder = placeholder
textField.backgroundColor = backgroundColor
return textField
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomUIKitTextField>) {
uiView.text = text
uiView.backgroundColor = backgroundColor
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentCompressionResistancePriority(.required, for: .vertical)
}
func makeCoordinator() -> CustomUIKitTextField.Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: CustomUIKitTextField
init(parent: CustomUIKitTextField) {
self.parent = parent
}
func textFieldDidChangeSelection(_ textField: UITextField) {
parent.text = textField.text ?? ""
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print("Begin editing")
textField.backgroundColor = .brown
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("Finished Editing")
}
}
}
I've tried something as you can see (there are some things to just debug stuff) but I'm not that much experienced in UIKit so I don't really know what is the best way to tackle this problem and out there there's not much about this kind of problem.
Have you faced something similar before? How can I solve this problem?
EDIT:
If this can help this is the view hierarchy when the TextField is in editing mode and the selected elements that puts itself in front of the TextField is a UIFieldEditor
UIFieldEditor
first off, don't define background colour in SwiftUI:
.background(Color("cardBackground")) / remove this line of code
In the makeUIView method, setup a default background color, which is used, when user not tapping the textfield:
textfield.backgroundColor = .systemGray
Finally, use these methods in the Coordinator class to control background colour behaviour:
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.backgroundColor = .red
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
textField.backgroundColor = .systemGray
}
I got problem while showing timer picker. There are two text fields: 1. first one opens a number pad. 2. second opens time picker from material controls.
Once I start editing first TF & if I tap on second TF the number pad is not getting dismissed even if I tap on Done button.
the done button is created using ToolBar & the method contains "view.endEditing" code. It works fine normally but not in above condition.
override func viewDidLoad() {
super.viewDidLoad()
rateInPointsTextField.delegate = self
}
extension MyAvailabilityVC : UITextFieldDelegate{
let toolbar = UIToolbar()
toolbar.sizeToFit()
//done button for toolbaar
let done = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))
toolbar.setItems([done], animated: false)
self.rateInPointsTextField.inputAccessoryView = toolbar
#objc func donePressed(){
self.view.endEditing(true)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.fromTimeTextField{
let timePicker = MDTimePickerDialog()
timePicker.delegate = self
timePicker.tag = 100
timePicker.clockMode = .mode12H
timePicker.show()
self.view.endEditing(true)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.rateInPointsTextField.resignFirstResponder()
return true
}
}
Confirm UITextFieldDelegate in your view controller & set TF delegate to self
class YourViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var your_tf: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
your_tf.delegate = self;
}
....
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
Now when you will press done/return button of keyboard then keyboard will dismiss. If you want to dismiss from your created button then make call from done #Action fun to textFieldShouldReturn(your_tf) like this.
...
#objc func donePressed(){
textFieldShouldReturn(your_tf)
}
Is there a way to temporarily disable the interaction and input for all textfields on a ViewController if one is currently being edited. After keyboard or UIPicker disapears, I would like the textField interaction to be enabled again.
I understand to disable touch interaction I can use:
textField.isUserInteractionEnabled = false
But what if I also have textField2 and textField3 how can I temporarily disable user interaction of both textFields when I am editing textfield1 ?
Create outlet collection for all the textfields like
#IBOutlet var textFs:[UITextField]!
Then set the vc as the delegate for all of them in viewDidLoad
textFs.forEach { $0.delegate = self }
Implement
func textFieldDidBeginEditing(_ textField: UITextField) {
textFs.forEach {
if $0 != textField {
$0.isUserInteractionEnabled = false
}
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
textFs.forEach { $0.isUserInteractionEnabled = true }
}
When I tap on this UITextFieldmentioned on screen below, a numpad keyboard appears, the problem is that when I start tap on number, my UITextField do not update, stay with no number, only placeholder.
What I need to do?
Thanks
ADDING CODE!
#IBOutlet weak var salarioTextField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
updateView()
salarioTextField.delegate = self
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool
{
if textField == feriasTextField
{
feriasTextField.inputView = feriasPicker
}
else if textField == salarioTextField
{
salarioTextField.keyboardType = UIKeyboardType.NumberPad
}
else if textField == inicioTextField
{
textField.inputView = datePicker
textField.inputAccessoryView = toolbar
datePicker.date = inicioDate
}
else if textField == motivoTextField
{
motivoTextField.inputView = motivoPicker
}
else
{
textField.inputView = datePicker
textField.inputAccessoryView = toolbar
datePicker.date = fimDate
}
return true
}
func textFieldDidBeginEditing(textField: UITextField)
{
backgroundScrollView.scrollEnabled = true
let scrollSize = CGSizeMake(view.frame.width, view.frame.height)
backgroundScrollView.contentSize = scrollSize
activeTextField = textField
activeTextField?.becomeFirstResponder()
}
func textFieldDidEndEditing(textField: UITextField)
{
backgroundScrollView.contentSize = CGSizeMake(0, 800)
backgroundScrollView.scrollEnabled = true
}
Please ignore the others UITextField.
Make sure you have enabled user interaction for the field.
If you implement the delegate method textViewDidBeginEditing, you can put a breakpoint or a print statement here to see if it triggers.
You can try calling becomeFirstResponder on the field.
I just figured out what was happening.
I was returning false to the method below.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return true;
}
Just changed it to true and it's working.
Thanks for your help.
I have a button and text textfield in my view. when i click on the textfield a keyboard appears and i can write on the textfield and i also able to dismiss the keyboard by clicking on the button by adding:
[self.inputText resignFirstResponder];
Now I want to enable return key of keyboard. when i will press on the keyboard keyboard will disappear and something will happen. How can I do this?
Ensure "self" subscribes to UITextFieldDelegate and initialise inputText with:
self.inputText.delegate = self;
Add the following method to "self":
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == self.inputText) {
[textField resignFirstResponder];
return NO;
}
return YES;
}
Or in Swift:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == inputText {
textField.resignFirstResponder()
return false
}
return true
}
With extension style in swift 3.0
First, set up delegate for your text field.
override func viewDidLoad() {
super.viewDidLoad()
self.inputText.delegate = self
}
Then conform to UITextFieldDelegate in your view controller's extension
extension YourViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == inputText {
textField.resignFirstResponder()
return false
}
return true
}
}
While the other answers work correctly, I prefer doing the following:
In viewDidLoad(), add
self.textField.addTarget(self, action: #selector(onReturn), for: UIControl.Event.editingDidEndOnExit)
and define the function
#IBAction func onReturn() {
self.textField.resignFirstResponder()
// do whatever you want...
}
Just add a target on textField setup function on viewDidLoad, then add its related function as selector.
override func viewDidLoad() {
super.viewDidLoad()
textField.addTarget(self, action: #selector(textFieldShouldReturn(sender:)), for: .primaryActionTriggered)
}
#objc func textFieldShouldReturn(sender: UITextField) {
textField.resignFirstResponder()
}
Use Target-Action UIKit mechanism for "primaryActionTriggered" UIEvent sent from UITextField when a keyboard done button is tapped.
textField.addTarget(self, action: Selector("actionMethodName"), for: .primaryActionTriggered)