Adding the "Clear" Button to an iPhone UITextField - ios

How do you add that little "X" button on the right side of a UITextField that clears the text? I can't find an attribute for adding this sub-control in Interface Builder in the iPhone OS 2.2 SDK.
Note: In Xcode 4.x and later (iPhone 3.0 SDK and later), you can do this in Interface Builder.

This button is a built-in overlay that is provided by the UITextField class, but as of the iOS 2.2 SDK, there isn't any way to set it via Interface Builder. You have to enable it programmatically.
Add this line of code somewhere (viewDidLoad, for example):
Objective-C
myUITextField.clearButtonMode = UITextFieldViewModeWhileEditing;
Swift 5.0
myUITextField.clearButtonMode = .whileEditing

You can also set this directly from Interface Builder under the Attributes Inspector.
Taken from XCode 5.1

Swift 4+:
textField.clearButtonMode = UITextField.ViewMode.whileEditing
or even shorter:
textField.clearButtonMode = .whileEditing

you can add custom clear button and control the size and every thing using this:
UIButton *clearButton = [UIButton buttonWithType:UIButtonTypeCustom];
[clearButton setImage:img forState:UIControlStateNormal];
[clearButton setFrame:frame];
[clearButton addTarget:self action:#selector(clearTextField:) forControlEvents:UIControlEventTouchUpInside];
textField.rightViewMode = UITextFieldViewModeAlways; //can be changed to UITextFieldViewModeNever, UITextFieldViewModeWhileEditing, UITextFieldViewModeUnlessEditing
[textField setRightView:clearButton];

Swift 4 (adapted from Kristopher Johnson's answer)
textfield.clearButtonMode = .always
textfield.clearButtonMode = .whileEditing
textfield.clearButtonMode = .unlessEditing
textfield.clearButtonMode = .never

Objective C :
self.txtUserNameTextfield.myUITextField.clearButtonMode = UITextFieldViewModeWhileEditing;
Swift :
txtUserNameTextfield.clearButtonMode = UITextField.ViewMode.WhileEditing;

this don't work, do like me:
swift:
customTextField.clearButtonMode = UITextField.ViewMode.Always
customTextField.clearsOnBeginEditing = true;
func textFieldShouldClear(textField: UITextField) -> Bool {
return true
}

On Xcode 8 (8A218a):
Swift:
textField.clearButtonMode = UITextField.ViewMode.whileEditing;
The "W" went from capital to non-cap "w".

func clear_btn(box_is : UITextField){
box_is.clearButtonMode = .always
if let clearButton = box_is.value(forKey: "_clearButton") as? UIButton {
let templateImage = clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate)
clearButton.setImage(templateImage, for: .normal)
clearButton.setImage(templateImage, for: .highlighted)
clearButton.tintColor = .white
}
}

Use below lines of code. If rightView is there clear button is not showing.
self.txtField.rightView = nil
self.txtField.rightViewMode = .never
self.txtField.clearButtonMode = UITextField.ViewMode.always

On Xcode Version 8.1 (8B62) it can be done directly in Attributes Inspector. Select the textField and then choose the appropriate option from Clear Button drop down box, which is located in Attributes Inspector.

Related

2 line text UIButton

I have a UIButton and the text of the button is filled by a randomiser.
However my problem is that sometimes the number of characters in a text is too many, leading to the button now showing the whole text.
Would it be possible to check if the characters are too many and then have it drop the rest of the text to another text line? So basically having to text lines instead of one for the UIButton?
Objectivc-C
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2;
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if u need
else use this
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
[button setTitle: #"Line1\nLine2" forState: UIControlStateNormal];
Swift
button.titleLabel!.lineBreakMode = .ByWordWrapping
button.titleLabel!.numberOfLines = 2
button.titleLabel!.textAlignment = .Center
else use this
button.titleLabel!.lineBreakMode = .ByWordWrapping
button.titleLabel!.textAlignment = .Center
button.setTitle("Line1\nLine2", forState: .Normal)
Swift3
buttonName.titleLabel!.lineBreakMode = .byWordWrapping
buttonName.titleLabel!.textAlignment = .center
buttonName.setTitle("Line1\nLine2", for: .normal)
In the Interface Builder, change the Line Break mode to Word Wrap for the UIButton control:
And to center the text, make the title Attributed instead of Plain.
Assuming you are using a storyboard or .xib file, click on your button and open the Attributes inspector on the right, then in the Button section, look for the 'Line Break' field. Drop this down and you will see 2 options (among others) - 'Character wrap' and 'Word wrap', these provide the functionality you are after.
alternatively In code you can use one of the following
[BUTTON setLineBreakMode:NSLineBreakByWordWrapping]
[BUTTON setLineBreakMode:NSLineBreakByCharWrapping]
I had a problem with UILabels growing when auto layout was used rather than word wrapping. The solution was to set the preferredMaxLayoutWidth to force it to wrap the text.
For a button you can do the same thing using:
button.titleLabel.preferredMaxLayoutWidth = <max width required>.

UiTextField changes font while editing in Swift 1.2 & 2.0

I have a UITextField with a custom font, everything worked fine until Swift update to 1.2 and 2.0. Afterwards, each time I try to edit a text field, it changes its font to a different one that seems a sort of Times New Roman. Does anyone have experience of that?
I came across this same issue and figured out a solution. The problem boils down to setSecureTextEntry changing the font when it is set, and not changing it back when it is unset. In fact, you can never change the font back as long as your UITextField has first responder.
The trick is to resignFirstResponder before you call setSecureTextEntry: and then becomeFirstResponder again. This will work (as of iOS 9.2), but it triggers the keyboard show/hide animation and will cause the screen to "shake". To get around that, you'll need to kill the keyboard animation as well.
Here's my full solution:
- (void)setSecureTextEntry:(BOOL)secureTextEntry {
__weak typeof(self) weakSelf = self;
[UIView performWithoutAnimation:^{
BOOL resumeResponder = NO;
if([[weakSelf textEntryField] isFirstResponder]) {
resumeResponder = YES;
[[weakSelf textEntryField] resignFirstResponder];
}
[[weakSelf textEntryField] setSecureTextEntry:secureTextEntry];
if(resumeResponder) {
[[weakSelf textEntryField] becomeFirstResponder];
}
}];
}
PS: This isn't a Swift bug. It's a UIKit bug. I had the same issue with Objective-C.
I had a weird case of fonts changing its size and font type, when secureTextEntry for an UiTextField was toggled by using a button action.
Had to explicitly manage font for the UiTextField by using these lines of code:
password.font = UIFont(name: "systemFont", size: 14)
password.font = UIFont.systemFontOfSize(14)
Complete Code used in the Show Password Button:
//Function associated with the button for show password option
#IBAction func switchShowPasswordAction(sender: AnyObject) {
if showPassword{
showPassword = false
password.secureTextEntry = !showPassword
}else{
showPassword = true
password.secureTextEntry = !showPassword
}
//Changing font fix
password.font = UIFont(name: "systemFont", size: 14)
password.font = UIFont.systemFontOfSize(14)
}
Post applying this change:
Since I used custom fonts we need to preserve the original font. Create an extension to UITextField:
extension UITextField {
func enablePasswordModeWithShowHide() {
secureTextEntry = false
let showButton = UIButton(type: UIButtonType.System)
showButton.setTitle("HIDE", forState: .Normal)
showButton.titleLabel?.textAlignment = .Right
showButton.sizeToFit()
rightView = showButton
rightViewMode = .Always
showButton.addTarget(self, action: "handleShowHideTapped", forControlEvents: .TouchUpInside)
showButton.tintColor = UIColor.blackColor()
}
func handleShowHideTapped() {
secureTextEntry = !secureTextEntry
let font = self.font
self.font = nil
self.font = font
if let oldText = text {
text = "";
text = oldText;
}
if let button = rightView as? UIButton {
button.setTitle(secureTextEntry ? "SHOW" : "HIDE", forState: .Normal)
button.sizeToFit()
}
}
}
Where it could be implemented like this:
passwordTextField.enablePasswordModeWithShowHide()
All of these answers pretty much work, but I had to use a different solution to achieve the results I needed, considering I'm using a custom font.
You need to make the text field attributed in the storyboard inspector pane for the UITextField, as follows:
Then, in code, you need to manage the toggling of the visibility, setting the attributed text each time, to ensure its properly formatted. I also resignFirstResponder() on the field just to take care of some positioning glitch that I still haven't figured out yet.
func toggleShowPass() {
self.showing = !showing
txtpassword.secureTextEntry = !showing
textFieldPassword.resignFirstResponder()
let string = textFieldPassword.text!
let attrString = NSMutableAttributedString(string: string)
textFieldPassword.addAttribute(NSFontAttributeName, value: UIFont(name: "AvenirNext-Regular", size: 16.0)!, range: NSMakeRange(0, string.characters.count))
textFieldPassword.attributedText = attrString
}
Set defaultTextAttributes with custom font attribute after toggling the secureTextEntry flag
NSDictionary *attrsDictionary =
#{ NSFontAttributeName://customfont};
_passwordtextfield.defaultTextAttributes = attrsDictionary;
I had to apply the following solution with latest Xcode 7.1.1 which actually worked in my case I suspect this issue is of framework.
- (IBAction)btnPasswordShowAction:(id)sender {
self.txtPassword.secureTextEntry = !self.txtPassword.secureTextEntry;
NSString *tmpString = self.txtPassword.text;
self.txtPassword.text = #" ";
self.txtPassword.text = tmpString;
[self.txtPassword setFont:nil];
self.txtPassword.font = [UIFont fontWithName:#"OpenSans-Regular" size:16.0];
}
#pragma mark - Textfield Delegate Methods
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self.txtPassword setFont:nil];
self.txtPassword.font = [UIFont fontWithName:#"OpenSans-Regular" size:16.0];
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[self.txtPassword setFont:nil];
self.txtPassword.font = [UIFont fontWithName:#"OpenSans-Regular" size:16.0];
return YES;
}

How to get an image for a "Star" (Favorite) UIBarButtonItem?

I am new to iOS. I'm looking to put a "Star" button on the top menu of my app. Is there a way to get the star button built into iOS similar to UIBarButtonSystemItemAdd
If not, how can I get an image similar to the common favorite(s) star used by Apple in iOS?
Similar to this:
A simple and quick way is to use FontawesomeKit.
You can easily create the button like this:
FAKFontAwesome *icon = [FAKFontAwesome starIconWithSize:20];
[icon addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor]];
UIBarButtonItem *favButton = [[UIBarButtonItem alloc] initWithImage:[icon imageWithSize:CGSizeMake(20, 20)]
style:UIBarButtonItemStylePlain
target:self
action:#selector(doSomething:)];
I think it's not possible. But if you want some icons, you can check this link, another one.
EDIT:
You can also extract the Artwork of a component: See this repository
Following up what andreamazz said, here's code to have a colored star (favorite) button in the navBaritem (swift):
let favAwesome = FAKFontAwesome.starIconWithSize(30.0) as FAKFontAwesome
favAwesome.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor())
let favBtn = UIButton.buttonWithType(UIButtonType.System) as UIButton
favBtn.frame = CGRectMake(0,0,30,30)
favBtn.setImage(favAwesome.imageWithSize(CGSizeMake(30, 30)), forState: .Normal)
favBtn.addTarget(self, action: "favorite", forControlEvents: UIControlEvents.TouchUpInside)
// favBarBtn is a class instance so we can access in the action method
favBarBtn = UIBarButtonItem(customView: favBtn)
navigationItem.rightBarButtonItem = favBarBtn
// your custom code here to find isFavorite
if isFavorite {
favBtn.tintColor = UIColor.redColor()
} else {
favBtn.tintColor = UIColor.blueColor()
}
then there is the "favorite" method to change the color (and set/unset favorite):
func favorite() {
// your custom favoriting code here
let favBtn = favBarBtn?.customView as UIButton!
if isFavorite {
favBtn.tintColor = UIColor.redColor()
} else {
favBtn.tintColor = UIColor.blueColor()
}
}

UITextField __CFStringEncodeByteStream EXC_BAD_ACCESS

I have a strange exception on a UITextField. I solved it but have no clue as to why it does.
After running the application I set the UITextField appearance as follows:
UITextField *textfieldAppearance = [UITextField appearance];
textfieldAppearance.font = [_theme textfieldFont];
textfieldAppearance.textColor = [_theme textfieldColor];
if (textDirectionRTL) {
textfieldAppearance.textAlignment = NSTextAlignmentRight;
}
textfieldAppearance.backgroundColor = [UIColor clearColor];
As you can see, there's nothing unusual about it, but when the controller with the UITextField opens I get a __CFStringEncodeByteStream + 17 EXC_BAD_ACCESS exception.
The solution was to comment out the backgroundColor setting.
I have the exact same appearance setting on UITextView and everything's ok.
Moreover, when I set the UITextField backgroundColor in the code within awakeAfterUsingCoder, everything works like a charm.
I'm running the app in XCode Version 4.6.3 (4H1503) simulator
Any clue to this strange behavior?
This is crashing because you are using the appearance proxy, which doesn't support all customisations. It doesn't seem to support backgroundColor so you will have to modify that on each text field individually
First of all why are u using UIAppearance class to customize the UItextfield..?? All the properties u are trying to set are present in UItextField itself...!
textField.backgroundColor = [UIColor clearColor];
textField.textColor = [UIColor redColor];
textField.textAlignment = UITextAlignmentCenter;
textField.font = [UIFont fontWithName:#"font name" size:12.0];
//Set the properties as you want.
Refer here for more

How can I set the title of a UIButton as left-aligned?

I need to display an email address on the left side of a UIButton, but it is being positioned to the centre.
Is there any way to set the alignment to the left side of a UIButton?
This is my current code:
UIButton* emailBtn = [[UIButton alloc] initWithFrame:CGRectMake(5,30,250,height+15)];
emailBtn.backgroundColor = [UIColor clearColor];
[emailBtn setTitle:obj2.customerEmail forState:UIControlStateNormal];
emailBtn.titleLabel.font = [UIFont systemFontOfSize:12.5];
[emailBtn setTitleColor:[[[UIColor alloc]initWithRed:0.121 green:0.472 blue:0.823 alpha:1]autorelease] forState:UIControlStateNormal];
[emailBtn addTarget:self action:#selector(emailAction:) forControlEvents:UIControlEventTouchUpInside];
[elementView addSubview:emailBtn];
[emailBtn release];
Set the contentHorizontalAlignment:
// Swift
emailBtn.contentHorizontalAlignment = .left;
// Objective-C
emailBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
You might also want to adjust the content left inset otherwise the text will touch the left border:
// Swift 3 and up:
emailBtn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0);
// Objective-C
emailBtn.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
You can also use interface builder if you don't want to make the adjustments in code.
Here I left align the text and also indent it some:
Don't forget you can also align an image in the button too.:
In Swift 3+:
button.contentHorizontalAlignment = .left
Swift 4+
button.contentHorizontalAlignment = .left
button.contentVerticalAlignment = .top
button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
UIButton *btn;
btn.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
Using emailBtn.titleEdgeInsets is better than contentEdgeInsets, in case you don't want to change the whole content position inside the button.
Here is explained how to do it and why it works so:
http://cocoathings.blogspot.com/2013/03/how-to-make-uibutton-text-left-or-right.html
in xcode 8.2.1 in the interface builder it moves to:
There is a small error in the code of #DyingCactus.
Here is the correct solution to add an UILabel to an UIButton to align the button text to better control the button 'title':
NSString *myLabelText = #"Hello World";
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
// position in the parent view and set the size of the button
myButton.frame = CGRectMake(myX, myY, myWidth, myHeight);
CGRect myButtonRect = myButton.bounds;
UILabel *myLabel = [[UILabel alloc] initWithFrame: myButtonRect];
myLabel.text = myLabelText;
myLabel.backgroundColor = [UIColor clearColor];
myLabel.textColor = [UIColor redColor];
myLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:14.0];
myLabel.textAlignment = UITextAlignmentLeft;
[myButton addSubview:myLabel];
[myLabel release];
Hope this helps....
Al
For Swift 2.0:
emailBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
This can help if any one needed.
In Swift 5.0 and Xcode 10.2
You have two ways to approaches
1) Direct approach
btn.contentHorizontalAlignment = .left
2) SharedClass example (write once and use every ware)
This is your shared class(like this you access all components properties)
import UIKit
class SharedClass: NSObject {
static let sharedInstance = SharedClass()
private override init() {
}
}
//UIButton extension
extension UIButton {
func btnProperties() {
contentHorizontalAlignment = .left
}
}
In your ViewController call like this
button.btnProperties()//This is your button
Try
button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
tl;dr: Using UIButton.Configuration - do titleAlignment = .center but also add a subtitle and make its font microscopic.
So, we're on iOS 15+, we're using the new UIButton.Configuration APIs, buttons now go multi-line by default and you're trying to figure out - how do I make the button's title be centered or trailing aligned, as opposed to the default (leading). For example you have an image and a button title underneath and and you want it centered.
Seems reasonable to try this:
configuration.titleAlignment = .center
But it doesn't change anything.
By trying thing out in Interface Builder, I noticed the following: titleAlignment only has an effect if there is a subtitle along with the title.
I am not sure if this is an omission on Apple's side (which might be fixed later) or if there is a good reason for it. In any case, we need a way to make it work without a subtitle. Perhaps some clever contentInset or UIControl.contentHorizontalAlignment can do the trick, but I'd be worried to use these in cases where we have to think about other languages, dynamic type etc.
Here's a solution which is still hacky, but would do the job:
Add a subtitle which contains just a space, then make the font microscopic, e.g. 0.01.
This is how to do it in code, assuming you are already working with a UIButton.Configuration:
configuration.titleAlignment = .center
configuration.title = "Hello hi"
configuration.subtitle = " "
configuration.subtitleTextAttributesTransformer = UIConfigurationTextAttributesTransformer({ input in
var output = input
output.font = .systemFont(ofSize: 0.01)
return output
})
Not an ideal solution and it might break in the future, but for some use cases the best available solution at the moment.
if you use button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10), you will get an warning that states 'contentEdgeInsets' was deprecated in iOS 15.0: This property is ignored when using UIButtonConfiguration. An alternative solution is:
iOS 15.0+
var button: UIButton = {
let button = UIButton(configuration: .filled())
button.configuration?.contentInsets = NSDirectionalEdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20)
button.contentHorizontalAlignment = .leading
return button
}()
SwiftUI
You should change the alignment property of the .frame modifier applied to the Text. Additionally, set the multiline text alignment to .leading.
Button {
// handler for tapping on the button
} label: {
Text("Label")
.frame(width: 200, alignment: .leading)
.multilineTextAlignment(.leading)
}

Resources