How can I change the color only of extra letters when typing in UITextField in Swift and return the color back when deleting?
I was able only to change color of all letters, when exceeding the limit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var inputLimitField: UITextField!
#IBOutlet weak var characterCountLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
characterCountLabel.text = "10/10"
inputLimitField.delegate = self
}
func checkRemainingChars() {
let allowedChars = 10
let charsInTextView = -(inputLimitField.text?.count ?? 0)
let remainingChars = allowedChars + charsInTextView
characterCountLabel.textColor = .black
inputLimitField.textColor = .black
inputLimitField.layer.borderColor = UIColor.systemGray3.cgColor
if remainingChars < 0 {
characterCountLabel.textColor = .red
inputLimitField.textColor = .red
inputLimitField.layer.borderColor = UIColor.red.cgColor
inputLimitField.layer.cornerRadius = 6.0
inputLimitField.layer.borderWidth = 1.0
}
characterCountLabel.text = ("\(String(remainingChars))/10")
}
func textFieldDidChangeSelection(_ textField: UITextField) {
checkRemainingChars()
}
}
this is what I expected to get
enter image description here
and this is what I really get enter image description here
p.s. also I can't put a letter counter in the corner through TF's border, because there is a mistake when I import Material Components: No such module 'MaterialComponents'
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 want to create a tab bar at the top of my page and contain only text, and when one clicked it will change the text color and underline the selected item... as shown in the image below...
I searched a lot but didn't find something to help me achieve this..
Can someone please tell me how can i do this?
Take Three Buttons and three imageviews.take action for three buttons and take outlets for images and labels as given below . use this link to easy identify.it's perfectly working for you. click here
class ViewController: UIViewController
{
#IBOutlet weak var imgDetails: UIImageView!
#IBOutlet weak var imgPassword: UIImageView!
#IBOutlet weak var imglocations: UIImageView!
#IBOutlet weak var lblDetailsTittle: UILabel!
#IBOutlet weak var lblPasswordTittle: UILabel!
#IBOutlet weak var lblLocationTittle: UILabel!
override func viewDidLoad()
{
super.viewDidLoad()
//if you want select by default Details use this code otherwise uncomment it.
imgDetails.backgroundColor = UIColor.green
imgPassword.backgroundColor = UIColor.clear
imglocations.backgroundColor = UIColor.clear
lblDetailsTittle.textColor = UIColor.black
lblPasswordTittle.textColor = UIColor.lightGray
lblLocationTittle.textColor = UIColor.lightGray
}
#IBAction func btnDetailsTouchUpInSide(_ sender: Any)
{
imgDetails.backgroundColor = UIColor.green
imgPassword.backgroundColor = UIColor.clear
imglocations.backgroundColor = UIColor.clear
lblDetailsTittle.textColor = UIColor.black
lblPasswordTittle.textColor = UIColor.lightGray
lblLocationTittle.textColor = UIColor.lightGray
}
#IBAction func btnPasswordTouchUpInSide(_ sender: Any)
{
imgPassword.backgroundColor = UIColor.green
imgDetails.backgroundColor = UIColor.clear
imglocations.backgroundColor = UIColor.clear
lblPasswordTittle.textColor = UIColor.black
lblLocationTittle.textColor = UIColor.lightGray
lblDetailsTittle.textColor = UIColor.lightGray
}
#IBAction func btnLocationsTouchUpInSide(_ sender: Any)
{
imglocations.backgroundColor = UIColor.green
imgDetails.backgroundColor = UIColor.clear
imgPassword.backgroundColor = UIColor.clear
lblLocationTittle.textColor = UIColor.black
lblPasswordTittle.textColor = UIColor.lightGray
lblDetailsTittle.textColor = UIColor.lightGray
}
}
I am struggling to get this to work.
I have a struct in place to help to pass data through each .swiftfile. (Only have one view controller).
This is my Message class where both the text layer and the shapes (SCNBox) are called/created.
struct MessagesStruct {
var text = String()
}
class Message: SCNNode {
public var messageDataArray = [MessagesStruct]()
public let textArray = Array<MessagesStruct>()
public let textLayer = CATextLayer()
override init() {
super.init()
let layer = CALayer()
layer.backgroundColor = UIColor.black.withAlphaComponent(0.8).cgColor
textLayer.frame = layer.bounds
textLayer.fontSize = 30
// generateTextOnLabel() -- Don't work
var data = String()
for each in Array<MessagesStruct>() {
data = each.text
}
textLayer.string = data
textLayer.alignmentMode = kCAAlignmentCenter
textLayer.foregroundColor = UIColor.white.cgColor
textLayer.display()
layer.addSublayer(textLayer)
textLayer.layoutIfNeeded()
textLayer.isWrapped = true
layer.layoutIfNeeded()
let box = SCNBox(width: 8.5, height: 1.25, length: 0.01, chamferRadius: 4)
box.firstMaterial?.locksAmbientWithDiffuse = true
self.geometry = box
let shape = SCNPhysicsShape(geometry: box, options: nil)
self.physicsBody = SCNPhysicsBody(type: .static, shape: shape)
self.physicsBody?.isAffectedByGravity = false
self.geometry?.firstMaterial?.diffuse.contents = layer
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func generateTextOnLabel() {
var dataToDisplay = String()
for data in textArray {
dataToDisplay = data.text
}
textLayer.string = dataToDisplay
}
}
This is my ViewControler class, I have taken out all the irrelevant lines of code e.g. IBOulets etc.
class ViewController: UIViewController, ARSCNViewDelegate, UITextViewDelegate {
#IBOutlet var sceneView: ARSCNView!
#IBOutlet var generateNotesButton: UIButton!
#IBOutlet var addNotesButton: UIButton!
#IBOutlet var saveButton: UIButton!
var messagesArray: [MessagesStruct] = []
var refToMessages = Message()
#IBAction func saveButton_TouchUpInside(_ sender: Any) {
var notes = MessageStruct()
notes.text = textView.text
messagesArray.append(notes)
}
#IBAction func generateNotes_TouchUpInside(_ sender: Any) {
for _ in 0...notesArray.count {
let messageNode = Message()
refToMessages.messagesDataArray.append(contentsOf: messagesArray)
sceneView.scene.rootNode.addChildNode(messageNode)
}
}
As far as I am aware, the data is passed through as I have used the print command. However, the text layer is always blank. When printing to console I can retrieve the values in the array and the length using the .count method. But there is an issue of trying to get the data in the array to display. I have tried to utilise an array and even a struct but nothing works. Only time the label displays any text is when I write something like this:
textLayer.string = "Hello World"
As you can guess, the label will appear with the message Hello World.
Can anyone help me to overcome this small issue? I have never used CATextLayer() and I'm treating it almost like a UILabel so this may be my downfall. But I am running out of options and just cannot get this to work.
Thank you.
i am doing a form using textfield and textview
after i key in all the information and click the submit button, the app will close and jump to my viewcontroller.swift and show like the below photo
and this is my viewcontroller.swift
import UIKit
import MessageUI
class ContactViewController:UIViewController,MFMailComposeViewControllerDelegate,UITextViewDelegate,UITextFieldDelegate {
#IBOutlet weak var message: UITextView!
#IBOutlet weak var contactSubject: UITextField!
#IBOutlet weak var contactNumber: UITextField!
#IBOutlet weak var contactEmail: UITextField!
#IBOutlet weak var contactName: UITextField!
#IBOutlet weak var contactDes: UILabel!
#IBOutlet weak var contactTitle: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
contactTitle.text = "SEND US A MESSAGES"
contactTitle.sizeToFit()
contactDes.text = "Do you have anything in your mind to tell us?\nPlease don’t hesitate to get in touch to us via our contact form."
contactDes.sizeToFit()
//Contact Form
contactName.delegate = self
contactEmail.delegate = self
contactNumber.delegate = self
contactSubject.delegate = self
message.delegate = self
self.message.isUserInteractionEnabled = true
self.message.isEditable = true
let borderColor : UIColor = UIColor.init(red: 46.0/255.0, green: 49.0/255.0, blue: 146.0/255.0, alpha: 1)
contactName.layer.borderWidth = 1
contactName.layer.borderColor = borderColor.cgColor
contactEmail.layer.borderWidth = 1
contactEmail.layer.borderColor = borderColor.cgColor
contactSubject.layer.borderWidth = 1
contactSubject.layer.borderColor = borderColor.cgColor
contactNumber.layer.borderWidth = 1
contactNumber.layer.borderColor = borderColor.cgColor
message.layer.borderWidth = 1
message.layer.borderColor = borderColor.cgColor
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
contactName.resignFirstResponder()
contactEmail.resignFirstResponder()
contactNumber.resignFirstResponder()
contactSubject.resignFirstResponder()
return true
}
#IBAction func submitbtn(_ sender: Any) {
let mailVC = MFMailComposeViewController()
mailVC.mailComposeDelegate = self
mailVC.setSubject(contactSubject.text!)
let email = contactEmail.text!.lowercased()
let finalemail = email.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)
let mailcontent = "Name :\(contactName.text!)\n\n Email:\(finalemail)\n\n Contact Numer :\(contactNumber.text!)\n\n Subject :\(contactSubject.text!)\n\n Message :\(message.text!)"
mailVC.setMessageBody(mailcontent, isHTML: false)
let toRecipent = "abc#example.com"
mailVC.setToRecipients([toRecipent])
self.present(mailVC, animated: true, completion: nil)
}
}
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