The cursor in the UITextView at the top is showing up completely fine, however the second UITextView just below it places the cursor 3-4 lines below it should be. So when I type anything in it, as shown in the screenshot below, it isn't right. The code for this view controller is shown below the screenshot.
class AddQuestionViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var questionTextView: UITextView!
#IBOutlet weak var answerTextView: UITextView!
#IBOutlet weak var doneBarButton: UIBarButtonItem!
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var answerLabel: UILabel!
weak var delegate: AddQuestionViewControllerDelegate?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.questionTextView.layer.borderWidth = 0.5
self.questionTextView.layer.borderColor = UIColor.lightGrayColor().CGColor
self.questionTextView.layer.cornerRadius = 8
self.answerTextView.layer.borderWidth = 0.5
self.answerTextView.layer.borderColor = UIColor.lightGrayColor().CGColor
self.answerTextView.layer.cornerRadius = 8
self.questionTextView.becomeFirstResponder()
}
#IBAction func cancel() {
delegate?.addQuestionViewControllerDidCancel(self)
}
#IBAction func done() {
let item = Question()
item.question = questionTextView.text
item.answer = answerTextView.text
item.checked = false
delegate?.addQuestionViewController(self, didFinishAddingQuestion: item)
}
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if textView == questionTextView {
let oldText: NSString = questionTextView.text
let newText: NSString = oldText.stringByReplacingCharactersInRange(range, withString: text)
if newText.length > 0 {
doneBarButton.enabled = true
} else {
doneBarButton.enabled = false
}
}
return true
}
func textViewDidChange(textView: UITextView) {
let temp: NSString = textView.text
if textView == questionTextView {
self.questionLabel.hidden = temp.length > 0
} else {
self.answerLabel.hidden = temp.length > 0
}
}
func textViewDidEndEditing(textView: UITextView) {
let temp: NSString = textView.text
if textView == questionTextView {
self.questionLabel.hidden = temp.length > 0
} else {
self.answerLabel.hidden = temp.length > 0
}
}
}
Could it be a UILabel instead of a UITextView? UILabel tend to "center" the text and not alligning it to the left corner.
You probably have solved this by now, just in case I'm posting this:
self.automaticallyAdjustsScrollViewInsets = false
textView.contentOffset = CGPointZero
Related
I want to change borderColor from lightGray to black when textField is firstResponder. And if the textField resigns again, I want to change it to gray. TextField's textColor changes color automatically without tableView's reload, but borderColor doesn't. Is there a way to change the color by observing the values without reloading the tableView?
class ChangePasswordViewController: UITableViewController {
#IBOutlet weak var newPasswordTextField: RoundTextField!
#IBOutlet weak var checkingNewPasswordTextField: RoundTextField!
#IBOutlet weak var explainLabel: UILabel!
#IBOutlet weak var changePwButton: FillRoundButton!
let viewModel = ChangePasswordViewModel()
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
newPasswordTextField.tag = 0
checkingNewPasswordTextField.tag = 1
configureNotificationObservers()
}
func configureNotificationObservers() {
newPasswordTextField.addTarget(self, action: #selector(textDidChange(sender:)), for: .editingChanged)
checkingNewPasswordTextField.addTarget(self, action: #selector(textDidChange(sender:)), for: .editingChanged)
}
// MARK: - Actions
#objc func textDidChange(sender: RoundTextField) {
if sender == newPasswordTextField {
viewModel.pwValue = sender.text
} else {
viewModel.confirmPwValue = sender.text
}
updateForm()
}
}
extension ChangePasswordViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
if textField.tag == 0 {
viewModel.pwValue = textField.text ?? ""
} else {
viewModel.confirmPwValue = textField.text ?? ""
}
}
}
extension ChangePasswordViewController: FormViewModel {
func updateForm() {
changePwButton.isEnabled = viewModel.pwFormIsValid
newPasswordTextField.layer.borderColor = UIColor.yellow.cgColor
newPasswordTextField.textColor = .yellow
}
}
enter image description here
I am working on an app in which I have to pass 6 digits OTP through 6 textFields in which you to provide only one character and after that it automatically goes to another textField. I created 6 textFields outlets and used this code. The problem I have is that I want to change the specific textField OTP number but the problem is that if I want to change the OTP number of textfield 4 after tapping cross button it automatically goes to the textfield 3. How can I fix this issue?
The code I used:
import UIKit
class OneTimePasswordViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var txtOTP1: UITextField!
#IBOutlet weak var txtOTP2: UITextField!
#IBOutlet weak var txtOTP3: UITextField!
#IBOutlet weak var txtOTP4: UITextField!
#IBOutlet weak var txtOTP5: UITextField!
#IBOutlet weak var txtOTP6: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
txtOTP1.delegate = self
txtOTP2.delegate = self
txtOTP3.delegate = self
txtOTP4.delegate = self
txtOTP5.delegate = self
txtOTP6.delegate = self
self.txtOTP1.becomeFirstResponder()
}
}
And here is the code for creating logic:
func textField(_ textField: UITextField, shouldChangeCharactersIn range:NSRange, replacementString string: String) -> Bool {
if (range.length == 0){
if textField == txtOTP1 {txtOTP2?.becomeFirstResponder()}
if textField == txtOTP2 {txtOTP3?.becomeFirstResponder()}
if textField == txtOTP3 {txtOTP4?.becomeFirstResponder()}
if textField == txtOTP4 {txtOTP5?.becomeFirstResponder()}
if textField == txtOTP5 {txtOTP6?.becomeFirstResponder()}
if textField == txtOTP6 {txtOTP6?.resignFirstResponder()}
textField.text? = string
return false
}
else if (range.length == 1) {
if textField == txtOTP6 {txtOTP5?.becomeFirstResponder()}
if textField == txtOTP5 {txtOTP4?.becomeFirstResponder()}
if textField == txtOTP4 {txtOTP3?.becomeFirstResponder()}
if textField == txtOTP3 {txtOTP2?.becomeFirstResponder()}
if textField == txtOTP2 {txtOTP1?.becomeFirstResponder()}
if textField == txtOTP1 {txtOTP1?.resignFirstResponder()}
textField.text? = ""
return false
}
return true
}
You can try My 3rd party library:-
https://github.com/Datt1994/DPOTPView
For Solution:-
In viewDidLoad add tag & delegate to all textfield
import UIKit
class OneTimePasswordViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var txtOTP1: UITextField!
#IBOutlet weak var txtOTP2: UITextField!
#IBOutlet weak var txtOTP3: UITextField!
#IBOutlet weak var txtOTP4: UITextField!
#IBOutlet weak var txtOTP5: UITextField!
#IBOutlet weak var txtOTP6: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
txtOTP1.delegate = self
txtOTP1.tag = 1000
txtOTP2.delegate = self
txtOTP2.tag = 2000
txtOTP3.delegate = self
txtOTP3.tag = 3000
txtOTP4.delegate = self
txtOTP4.tag = 4000
txtOTP5.delegate = self
txtOTP5.tag = 5000
txtOTP6.delegate = self
txtOTP6.tag = 6000
self.txtOTP1.becomeFirstResponder()
}
}
In UITextFieldDelegate extension implement shouldChangeCharactersIn function like below, It will also work with textField.textContentType = .oneTimeCode
extension OneTimePasswordViewController : UITextFieldDelegate {
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.trimmingCharacters(in: CharacterSet.whitespaces).count != 0 {
textField.text = string
if textField.tag < count*1000 {
let next = textField.superview?.viewWithTag((textField.tag/1000 + 1)*1000)
next?.becomeFirstResponder()
} else if textField.tag == count*1000 {
textField.resignFirstResponder()
}
} else if string.count == 0 { // is backspace
textField.text = ""
}
return false
}
}
I am having some problems with function textFieldShouldReturn as far at i understand it should be called when enter are pressed on the keyboard but it does not. I have tried to search for solution on google and here but have not found a answer that solved the problem because most of the answers here on the webpage i have fund are a 3 years or older and the solutions from those did not help much.
I am using it in a UIView where the delegates for the textField is set in the function awakeFromNib() and i have tried some other delegate function textViewDidChangeSelection that does work so i am at a lost why it is not working.
Here is how the xib file looks
Here is the code that i am using as a popup:
import UIKit
class CuePointPopup: UIView,UITextFieldDelegate,UITextViewDelegate
{
#IBOutlet var labelCueNumberInImage: UILabel!
#IBOutlet var labelCueNumber: UILabel!
#IBOutlet var labelLayerName: UILabel!
#IBOutlet var labelPageNumber: UILabel!
#IBOutlet weak var view: UIImageView!
#IBOutlet var textFieldWhoText: UITextField!
#IBOutlet var textViewWhatText: UITextView!
#IBOutlet var textFieldWhereText: UITextField!
#IBOutlet var textFieldPageNumber: UITextField!
#IBOutlet var textFieldCueText: UITextField!
#IBOutlet var boxArrowLeft: UIImageView!
#IBOutlet var boxArrowRight: UIImageView!
#IBOutlet var boxArrowLeftTopConstraint: NSLayoutConstraint!
#IBOutlet var boxArrowRightTopConstraint: NSLayoutConstraint!
var cuePointObj:CuePoint!
var blockBtnClickedSave:((CuePoint) -> ())!
var blockBtnClickedCancel:((CuePoint) -> ())!
var blockBtnClickedDelete:((CuePoint) -> ())!
var blockTextChangedForPageNumber:((String, CuePoint) -> ())!
#IBOutlet var btnOutletVisibleOnPage: UIButton!
var isVisible = false
class func loadNib() -> CuePointPopup
{
return Bundle.main.loadNibNamed("CuePointPopup", owner: self,options: nil)!.last as! CuePointPopup
}
override func awakeFromNib() {
self.textFieldWhoText.delegate = self
self.textViewWhatText.delegate = self
self.textFieldWhereText.delegate = self
self.textFieldCueText.delegate = self
textViewWhatText.text = "Hello"
}
func setViewData(cueModel:CuePoint) {
self.cuePointObj = cueModel
labelCueNumberInImage.text = cueModel.cueNumber
labelCueNumber.text = "Cue #:" + cueModel.cueNumber
labelLayerName.text = "Layer #:" + cueModel.layerName
labelPageNumber.text = "Page #:" + cueModel.pageNumber
textFieldPageNumber.text = cueModel.pageNumber
textFieldWhoText.text = cueModel.whoString
textViewWhatText.text = cueModel.whatString
textFieldWhereText.text = cueModel.whereString
textFieldCueText.text = cueModel.cueTextString
if cueModel.isVisibleOnPage == true {
btnOutletVisibleOnPage.setImage(UIImage(named: "SelectedBox"), for: [])
btnOutletVisibleOnPage.tag = 1
}else{
btnOutletVisibleOnPage.setImage(UIImage(named: "UnselectedBox"), for: [])
btnOutletVisibleOnPage.tag = 0
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
if textField.text != "" {
if blockTextChangedForPageNumber != nil {
self.blockTextChangedForPageNumber(textField.text!, self.cuePointObj)
}
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
//self.view.endEditing(true)
if self.textFieldWhoText.isEditing {
self.textFieldWhoText.endEditing(true)
} else if self.textFieldCueText.isEditing{
self.textFieldCueText.endEditing(true)
} else if self.textFieldWhereText.isEditing {
self.textFieldWhereText.endEditing(true)
} else {
self.textViewWhatText.endEditing(true)
}
//self.view.endEditing(true)
return false
}
}
Here is how i load the XIB
#IBOutlet weak var bookView: UIView!
var objCuePopup:CuePointPopup!
if objCuePopup != nil {
objCuePopup.removeFromSuperview()
}
objCuePopup = CuePointPopup.loadNib()
objCuePopup = CuePointPopup.loadNib()
objCuePopup.frame = CGRect(x:cuePointModal.cueX, y:0, width:465, height:410)
objCuePopup.center = CGPoint(x:objCuePopup.center.x, y:cuePointModal.cueY + 5)
//Set Y value for Popup View
if objCuePopup.frame.origin.y < bookView.frame.origin.y {
objCuePopup.frame.origin.y = bookView.frame.origin.y
}
let popupMaxY = objCuePopup.frame.maxY
let bookViewMaxY = bookView.frame.maxY
if popupMaxY > bookViewMaxY {
objCuePopup.frame.origin.y = bookViewMaxY - objCuePopup.frame.size.height
}
//Set X value for Popup View
if cuePointModal.cueX > 455 {
objCuePopup.frame.origin.x = cuePointModal.cueX - 455
objCuePopup.boxArrowLeft.isHidden = true
objCuePopup.boxArrowRight.isHidden = false
let rightY = cuePointModal.cueY - objCuePopup.frame.origin.y
objCuePopup.boxArrowRightTopConstraint.constant = rightY + 3
}else{
objCuePopup.frame.origin.x = cuePointModal.cueX + 40
objCuePopup.boxArrowLeft.isHidden = false
objCuePopup.boxArrowRight.isHidden = true
let leftY = cuePointModal.cueY - objCuePopup.frame.origin.y
objCuePopup.boxArrowLeftTopConstraint.constant = leftY + 3
}
objCuePopup.setViewData(cueModel: cuePointModal)
objCuePopup.textFieldWhoText.delegate = self
objCuePopup.textFieldWhereText.delegate = self
objCuePopup.textViewWhatText.delegate = self
objCuePopup.textFieldCueText.delegate = self
bookView.addSubview(objCuePopup)
I hope that someone here can help me with this problem.
This question is not duplicated from these:
How to disable/enable the return key in a UITextField?
How to enable or disable the keyboard return key
Enable and Disable Keyboard return key on demand in iOS
I have two TextFields.
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
textField1 has the Next button like the Return Key;
textField2 has the Go button like the Return Key;
textField1
textField2
I would like to enable the Go button of the second TextField just if both TextFields are not empty.
I tried to use someTextField.enablesReturnKeyAutomatically with TextFieldDelegate, but did not work.
Thank you for help.
Below: textField2 is disabled as long as textField1 is empty. If the latter is non-empty, we enable textField2, but enable the Go button only if textField2 is non-empty (via .enablesReturnKeyAutomatically property),
/* ViewController.swift */
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// text field delegates
textField1.delegate = self
textField2.delegate = self
// set return key styles
textField1.returnKeyType = UIReturnKeyType.Next
textField2.returnKeyType = UIReturnKeyType.Go
// only enable textField2 if textField1 is non-empty
textField2.enabled = false
// only enable 'go' key of textField2 if the field itself is non-empty
textField2.enablesReturnKeyAutomatically = true
}
// UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
if (textField1.text?.isEmpty ?? true) {
textField2.enabled = false
textField.resignFirstResponder()
}
else if textField == textField1 {
textField2.enabled = true
textField2.becomeFirstResponder()
}
else {
textField.resignFirstResponder()
}
return true
}
}
Runs as follows:
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField === textField2 {
setReturnKeyState(for: textField, isEnabled: shoulEnableReturnKey(), delay: 0.1) // A bit hacky it needs delay here
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField === textField2 {
if var text = textField.text, let range = Range(range, in: text) {
text.replaceSubrange(range, with: string)
setReturnKeyState(for: textField, isEnabled: shoulEnableReturnKey())
}
}
return true
}
private func shoulEnableReturnKey() -> Bool {
textField1.hasText && textField2.hasText
}
}
extension UITextFieldDelegate {
func setReturnKeyState(for textField: UITextField, isEnabled: Bool, delay: Double? = nil) {
textField.enablesReturnKeyAutomatically = false
if textField.delegate != nil {
if let delay = delay {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
textField.setValue(isEnabled, forKeyPath: "inputDelegate.returnKeyEnabled")
}
} else {
textField.setValue(isEnabled, forKeyPath: "inputDelegate.returnKeyEnabled")
}
}
}
}
I am new to iOS and Swift. I am trying to add a background image for a slide right effect. I want that image to stick to the right of the screen no matter what orientation. The image will always be a set size (now its (382x145px). How can I adjust it on landscape orientation so that the picture stays to the right.
Here is my custom view cell class.
class CustomRouteViewCell: UITableViewCell {
#IBOutlet var downImage: UIImageView!
#IBOutlet var downTime: UILabel!
#IBOutlet weak var leadingSpaceConstraint: NSLayoutConstraint!
#IBOutlet weak var trailingSpaceConstraint: NSLayoutConstraint!
#IBOutlet var locationTitle: UILabel!
#IBOutlet weak var panView: UIView!
#IBOutlet var timerLabel: UILabel!
var indexRow: Int = 0
var timeInterval: Int = 0
override func awakeFromNib() {
super.awakeFromNib()
self.selectedBackgroundView = nil
var img = UIImage(named: "tableSwipeArrow.png")!
self.panView.backgroundColor = UIColor(patternImage: img)
if self.respondsToSelector(Selector("setLayoutMargins:")) {
layoutMargins = UIEdgeInsetsZero
}
if self.respondsToSelector(Selector("setPreservesSuperviewLayoutMargins:")) {
preservesSuperviewLayoutMargins = false
}
var panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePanGesture:")
panGestureRecognizer.delegate = self
addGestureRecognizer(panGestureRecognizer)
}
func handlePanGesture(recognizer: UIPanGestureRecognizer) {
switch(recognizer.state) {
case UIGestureRecognizerState.Changed:
var translation = recognizer.translationInView(recognizer.view!)
var little = CGFloat(trailingSpaceConstraint.constant + translation.x * -1)
trailingSpaceConstraint.constant = fmax(0, little)
leadingSpaceConstraint.constant = fmin(0, leadingSpaceConstraint.constant + translation.x)
recognizer.setTranslation(CGPointZero, inView: recognizer.view!)
timeInterval = Int(trailingSpaceConstraint.constant / 30) * 5
timerLabel.text! = "\(timeInterval)"
case UIGestureRecognizerState.Ended, UIGestureRecognizerState.Cancelled:
var refreshAlert = Alarm.getReminderView(self.timeInterval, view: self.parentViewController!.view)
self.parentViewController?.presentViewController(refreshAlert, animated: true, completion: nil)
leadingSpaceConstraint.constant = 0
trailingSpaceConstraint.constant = 0
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.layoutIfNeeded()
})
default:
trailingSpaceConstraint.constant = 0
leadingSpaceConstraint.constant = 0
}
}
}
extension CustomRouteViewCell: UIGestureRecognizerDelegate
{
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.isKindOfClass(UIPanGestureRecognizer) {
var velocity = (gestureRecognizer as! UIPanGestureRecognizer).velocityInView(gestureRecognizer.view!)
return fabs(velocity.x) > fabs(velocity.y)
}
return true;
}
}
Use auto layout to link the position of the images.
In your case you can connect the trailing of the background image with the container view.
Hold Control on image and link the Trailing Attribute with the main view
Just adjust the constant to 0.