How to dynamically change the display text of a button in xcode using tags - ios

Im trying to create an email us button in my app where the text displayed changes depending on what version of the app youre using. Currently the text is "Email: " and i want to add an email address to that text.
The button is in a table view cell, and i want to change this text using tags, how would i go about this or is there another option?
P.S The reason i want to do it with tags is when i try to hook the button up to an outlook the build will fail
let sendEmailButton = cell.viewWithTag(666)!
var rect = sendEmailButton.frame
rect.origin.x = 19
sendEmailButton.frame = rect
rect.origin.y = 75
sendEmailButton.frame = rect
change text here to be add email address
In this code i'm moving the button into its position, and then i want to change its text. Again, there no outlet as that caused fails due to it being in a table view. I realise this screen should not be in a table view, but its the way my company does it and i have to work with it

cast your button as UIButton like this:
guard let sendEmailButton = cell.viewWithTag(666) as? UIButton else { return }
and than just set title
sendEmailButton.setTitle("here goes your text", for: .normal)

For your code it will be work.
if let button = cell.viewWithTag(666) as? UIButton {
button.setTitle("Set Your Text here", for: .normal)
}

Related

In iOS 14 how do you tap a button programmatically?

In iOS 14 I have configured a button to display a menu of questions. On its own the button is working perfectly. Here’s how it’s configured:
let button = UIButton()
button.setImage(UIImage(systemName: "chevron.down"), for: .normal)
button.showsMenuAsPrimaryAction = true
button.menu = self.menu
I have it set on a text field’s rightView. This is how it looks when the menu is displayed.
When a menu item is tapped, that question appears in a label just above the text field. It works great. Except….
I also want the menu to appear when the user taps in the text field. I don’t want them to have to tap on the button specifically. In the old days of target-action this was easy: button.sendActions(for: .touchUpInside). I tried that and .menuActionTriggered and .primaryActionTriggered but none of those work. I think sendActions() is looking for the old selector based actions.
But there’s a new sendActions(for: UIControl.Event) method. Here’s what I’m trying in textFieldShouldBeginEditing():
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
let tempAction = UIAction { action in
print("sent action")
}
menuButton.sendAction(tempAction)
print("textField tapped")
return false
}
Sure enough, “sent action” and “textField tapped” appear in the console when the text field is tapped. But I have no idea what UIAction I could send that means “display your menu”. I wish there was this method: send(_: UIControl.Event).
Any ideas on how to get the button to display its menu when the text field is tapped?
ps. yes, textFieldShouldBeginEditing will need to know if a question has been selected and in that case will need to allow editing. That part is easy.
From what I read, you cannot programmatically trigger UIContextMenuInteraction as interactions seem to be handled internally by itself unlike send(_: UIControl.Event)
I see this mentioned on this SO post here
Also in the docs it seems that we don't have access to interaction management Apple needs to decide 3D touch is available or default back to long tap
From the docs
A context menu interaction object tracks Force Touch gestures on devices that support 3D Touch, and long-press gestures on devices that don't support it.
Workaround
I can propose the following workaround for your use case. My example was created using frame instead of auto layout as faster and easier to demo the concept this way, however you will need to make adjustments using autolayout
1. Create the UI elements
// I assume you have a question label, answer text field and drop down button
// Set up should be adjusted in case of autolayout
let questionLabel = UILabel(frame: CGRect(x: 10, y: 100, width: 250, height: 20))
let answerTextField = UITextField(frame: CGRect(x: 10, y: 130, width: 250, height: 50))
let dropDownButton = UIButton()
2. Regular setup of the label and the text view first
// Just regular set up
private func configureQuestionLabel()
{
questionLabel.textColor = .white
view.addSubview(questionLabel)
}
// Just regular set up
private func configureAnswerTextField()
{
let placeholderAttributes = [NSAttributedString.Key.foregroundColor :
UIColor.lightGray]
answerTextField.backgroundColor = .white
answerTextField.attributedPlaceholder = NSAttributedString(string: "Tap to select a question",
attributes: placeholderAttributes)
answerTextField.textColor = .black
view.addSubview(answerTextField)
}
3. Add the button to the text view
// Here we have something interesting
private func configureDropDownButton()
{
// Regular set up
dropDownButton.setImage(UIImage(systemName: "chevron.down"), for: .normal)
dropDownButton.showsMenuAsPrimaryAction = true
// 1. Create the menu options
// 2. When an option is selected update the question label
// 3. When an option is selected, update the button frame
// Update button width function explained later
dropDownButton.menu = UIMenu(title: "Select a question", children: [
UIAction(title: "Favorite movie") { [weak self] action in
self?.questionLabel.text = action.title
self?.answerTextField.placeholder = "Add your answer"
self?.answerTextField.text = ""
self?.updateButtonWidthIfRequired()
},
UIAction(title: "Car make") { [weak self] action in
self?.questionLabel.text = action.title
self?.answerTextField.placeholder = "Add your answer"
self?.answerTextField.text = ""
self?.updateButtonWidthIfRequired()
},
])
// I right align the content and set some insets to get some padding from
// the right of the text field
dropDownButton.contentHorizontalAlignment = .right
dropDownButton.contentEdgeInsets = UIEdgeInsets(top: 0.0,
left: 0.0,
bottom: 0.0,
right: 20.0)
// The button initially will stretch across the whole text field hence we
// right aligned the content above
dropDownButton.frame = answerTextField.bounds
answerTextField.addSubview(dropDownButton)
}
// Update the button width if a menu option was selected or not
func updateButtonWidthIfRequired()
{
// Button takes the text field's width if the question isn't selected
if let questionText = questionLabel.text, questionText.isEmpty
{
dropDownButton.frame = answerTextField.bounds
return
}
// Reduce button width to right edge as a question was selected
dropDownButton.frame = CGRect(x: answerTextField.frame.width - 50.0,
y: answerTextField.bounds.origin.y,
width: 50,
height: answerTextField.frame.height)
}
4. End Result
Start with a similar view to yours
Then I tap in the middle of the text field
It displays the menu as intended
After selecting an option, the question shows in the label and the placeholder updates
Now I can start typing my answer using the text field and the button is only active on the right side since it was resized
And the button is still active
Final thoughts
Could be better to put this into a UIView / UITextField subclass
This was an example using frames with random values, adjustments need to made for autolayout
Edits from OP (too long for a comment):
I had tried setting contentEdgeInsets so the button was way over to the left but it covered up the placeholder text.
Your idea of simply adding the button as a subview of the text field was the key, but...
After selecting a question and resizing the button, if the text field was the first responder, tapping the button had no effect. The button was in the view hierarchy but the text field got the tap.
So, when a question is selected, I remove the button from its superview (the textfield) and add it to the textField's rightView. Then it would accept a tap even if the textField was the first responder.
And, as you suspected, I had to pin the button to the textField with constraints.

How to implement Material chips in UITextfield using Swift 4

I have needed this type of chips UITextfield with a cancel button
let chipView = MDCChipView()
chipView.titleLabel.text = "Furkan#vijapura.com"
chipView.setTitleColor(UIColor.red, for: .selected)
chipView.sizeToFit()
chipView.backgroundColor(for: .selected)
self.view.addSubview(chipView)
self.userAdd.addSubview(chipView)
You can achieve this by creating a collectionView with multiple cells you can define the layout of each cell and your last cell will contain a text field.
Please let me know if you need a reference code for doing this.
Supposing that you have installed via pods:
Text Field with Floating Placeholder
let textFieldFloating = MDCMultilineTextField()
scrollView.addSubview(textFieldFloating)
textFieldFloating.placeholder = "Full Name"
textFieldFloating.textView.delegate = self
textFieldControllerFloating = MDCTextInputControllerUnderline(textInput: textFieldFloating) // Hold on as a property
Text Field with Character Count and Inline Placeholder
// First the text field component is setup just like a UITextField
let textFieldDefaultCharMax = MDCMultilineTextField()
scrollView.addSubview(textFieldDefaultCharMax)
textFieldDefaultCharMax.placeholder = "Enter up to 50 characters"
textFieldDefaultCharMax.textView.delegate = self
// Second the controller is created to manage the text field
textFieldControllerDefaultCharMax = MDCTextInputControllerUnderline(textInput: textFieldDefaultCharMax) // Hold on as a property
textFieldControllerDefaultCharMax.characterCountMax = 50
textFieldControllerDefaultCharMax.isFloatingEnabled = false
Also If you want to follow a Git Project Use: https://github.com/Skyscanner/SkyFloatingLabelTextField

Customize Text Field

Hi I want to build some thing that look like the picture !
my problem is that text field can't be two section and use tiny pictures in it just like a picture
I want to make some thing just like the picture even the green part in the right of the each text field
here is what I want to do
Make a custom view and add it as
textField.rightViewMode = .always
// Set rightview mode
var rightImageView = UIImageView(image: UIImage(named: "image_icon"))
textField.rightView = rightImageView// Set right view as image view }
//textField Its your textfield object , Change it with your own
Try like this

Swift - Set label to be on top of other view items

I'm creating a basic sketching app using swift 1.2 and Xcode 6.4. The feature I'm working on is adding text to the image for future manipulation.
So far I have the text the user enters adding to the drawing via label, but it is being placed (I assume) behind the UIImage that is to be drawn upon. This is preventing the associated tap gesture from being recognised. The label is also obscured when drawn over.
How do I place the label on top of everything else to prevent it being drawn over? The end goal is to allow the user to move the label.
If I was using my usual web stack I'd set the z-index of the element to a high value via CSS.
Edit: Using view.bringSubviewToFront(label) prevents the text from being drawn over, but does not allow the tap gesture to be picked up.
Heres my code:
func printText(){
println(textString)
var label = UILabel(frame: CGRectMake(5, 100, 200, 50 ))
label.textAlignment = NSTextAlignment.Center
label.text = textString;
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))
label.addGestureRecognizer(tap)
self.view.addSubview(label);
}
func handleTap() {
print("tap working")
}
Any help much appreciated.
If you want z-index use:
label.layer.zPosition = 1;
Also you could play with bringToFront method on the parent view:
self.view.bringSubviewToFront(label);
You can check that function here :
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/
Also, you should add the following:
label.userInteractionEnabled = true
to enable touches.
Try using those in the parent view:
view.bringSubviewToFront(label)
view.sendSubviewToBack(imageView)
It all depends on what you can, or want to do.
You can call label to front by
self.view.bringSubviewToFront(label)
or
You can send image view to the back by
self.view.sendSubviewToBack(imageView)

Subclassing UINavigationBar with Swift

I'm writing an app that gives a user tokens to spend and I want to display the user's current number of tokens in a UINavigationBar. What I would like to have is a label with the number of tokens, and an image of a coin in the top right corner of my navigation bar.
I've been searching for ways to customize the UINavigationBar, and have found plenty of posts related to adding an image to cover the entire bar, and changing the title. However, I can't find a simple way to do what I want.
I think I need to subclass UINavigationBar and add the text/image myself, but being new to iOS development and Swift, I was hoping that someone could point me in the right direction.
You can create a custom view contains subviews UILabel and UIImageView to show the token number and token image. Add it to right bar button item of the navigation controller.
It will look like:
Below code will create the custom view. Here you can observe that it is a local variable. However, you can manage global variable for custom view or create a whole new class and manage it independently for real-time updates to show token number.
// Custom to hold token number and image
let tokenView = UIView(frame: CGRect(x:0, y:0, width:100, height:44))
tokenView.backgroundColor = UIColor.yellow
// Label to show token number
let tokenLabel = UILabel(frame: CGRect(x:0, y:0, width:60, height:44))
tokenLabel.text = "1234"
tokenLabel.textAlignment = NSTextAlignment.right
let imageHeight = CGFloat(30)
let marginY = CGFloat((tokenView.frame.size.height / 2) - (imageHeight / 2))
// ImageView to display token image
let tokenImage = UIImageView(image: UIImage(named: "coin"))
tokenImage.frame = CGRect(x:70, y:marginY, width:30, height:30)
tokenView.addSubview(tokenLabel)
tokenView.addSubview(tokenImage)
// Add custom view as a right bar button item
let barButtonItem = UIBarButtonItem(customView: tokenView)
self.navigationItem.rightBarButtonItem = barButtonItem
To display the current number of tokens you can just set the title. In your view controller:
navigationItem.title = '\(numberOfCoins) coins"
If you want to do anything more fancy you can set your own title view instead of the standard UILabel:
navigationItem.titleView = UIView(...) // your custom view
To show the coin in the top right corner you'd set the rightBarButtonItem:
navigationItem.rightBarButtonItem = UIBarButtonItem(
image: UIImage(named:"Coin"),
style: .Plain,
target:self,
action:"tappedCoinButton:")

Resources