Custom UITextField clear button - objective-c

Is it possible to customize the image of the clear button in a UITextField? I have a dark textfield background and the "x" is not visible enough.

You can set your own custom clear button to the text field's rightView property. Make sure set the rightViewMode property to UITextFieldViewModeWhileEditing or UITextFieldViewModeAlways, whatever makes sense for your case.
If the button's position isn't right for your need, you can subclass UITextField and override the rightViewRectForBounds: method.
The documentation says the default for the clearButtonMode property is UITextFieldViewModeNever, but I suspect Interface Builder may set it to UITextFieldViewModeWhileEditing - Make sure you set it to the "never" value so it doesn't appear.
All these properties are documented in UITextField Class Reference.

You can access that property using KVO:
UIButton *clearButton = [myTextField valueForKey:#"_clearButton"];
[clearButton setImage:[UIImage new] forState:UIControlStateNormal];

Tested iOS7.0 - 8.4
It is possible to update the backgroundImage of all clear buttons using the following UIAppearance method. Unfortunately you cannot update the image of the button:
UIButton *defaultClearButton = [UIButton appearanceWhenContainedIn:[UITextField class], nil];
[defaultClearButton setBackgroundImage:[UIImage imageNamed:#"clearButtonBkg1.png"] forState:UIControlStateNormal];
Using the following images, this results in the following clear button:
White background image #3x:
Note: This will update the background image of ALL buttons contained in textfields

Swift 2.2+ / iOS 9+ version of #Brody Robertson's answer:
let defaultClearButton = UIButton.appearanceWhenContainedInInstancesOfClasses([UITextField.self])
defaultClearButton.setBackgroundImage(UIImage(named: "ClearIcon"), forState: UIControlState.Normal)

Swift 3
let customClearButton = UIButton.appearance(whenContainedInInstancesOf: [UITextField.self])
customClearButton.setBackgroundImage(UIImage(named: "custom_cb"), for: .normal)

depends on #Tuss László's answer
Swift 3.0
myTextField.clearButtonMode = .whileEditing
if let clearButton = myTextField.value(forKeyPath: "_clearButton") as? UIButton {
clearButton.setImage(UIImage(named:"myImage"), for: .normal)
clearButton.setImage(UIImage(named:"myImage"), for: .highlighted)
}
But really use it carefully. If Apple change implementations in future iOS releases, it would not be work

One approach would be to create a custom UITextField that has your desired image as a subview and clears the parent text field when tapped. You disable the default button and add your custom behavior in this custom text field.
This should get you started. If there are any more concrete questions, feel free to edit your question or comment here if it's a minor problem.

Related

UIAppearance has no effect on Label text color

I am setting the text color of all the labels in my app using UIAppearance. Yet the text color does not change.
Here is a sample of how i create the label
//show the loading message
MessageLabel *messageLabel = [[MessageLabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
messageLabel.text = #"\n\nLoading ...\n\n";
messageLabel.numberOfLines = 0;
messageLabel.textAlignment = NSTextAlignmentCenter;
[messageLabel sizeToFit];
self.tableview.backgroundView = messageLabel;
Here is how i set the text color
[[MessageLabel appearance] setTextColor:[UIColor blackColor]];
One note is that all these MessageLabel are BackgroundViews of UITableView
As arrteme mentioned, UILabel's textColor doesn't work with UIAppearance. I got around this by adding a UIAppearance compatible property that just wraps textColor. In Swift this would look something like
class MessageLabel: UILabel {
#objc dynamic var configurableTextColor: UIColor {
get {
return textColor
}
set {
textColor = newValue
}
}
...
}
and then to configure the appearance:
MessageLabel.appearance().configurableTextColor = .black
From the Documentation:
iOS applies appearance changes when a view enters a window, it
doesn’t change the appearance of a view that’s already in a window. To
change the appearance of a view that’s currently in a window, remove
the view from the view hierarchy and then put it back.
Referring to this, UIAppearance kind of doesn't really seem work with UILabel...
Since you're subclassing from UILabel, maybe it would make sense to set textcolor property initWithFrame: method on in your MessageLabel class?
Or another option, since you say these MessageLabel instances are used for UITableViewCell's background, maybe it would make sense to leave label's background clear and change background of cell itself, for example in tableView:willDisplayCell:forRowAtIndexPath: method in tableView's delegate?
If you instantiated a UILabel in code, you must manually set textColor property after you set the appearance.
messageLabel.textColor = [[UILabel appearance] textColor];

Xcode - UIDatePicker background color

My UIDatePicker's background is black (because the background for the whole screen is black probably), but I want white in the background for this UIDatePicker.
Is there any way to change the background color without subclassing it?
iOS 14 update
It looks that datePicker.backgroundColor doesn't work in iOS 14. It works. But you have to put it after preferredDatePickerStyle setting:
let picker = UIDatePicker()
if #available(iOS 13.4, *) {
picker.preferredDatePickerStyle = .wheels
}
picker.backgroundColor = .red
datePickerName.backgroundColor = [UIColor grayColor];
OBJECTIVE C
datePicker.backgroundColor = [UIColor greenColor]
SWIFT
DatePicker.backgroundColor = UIColor.blueColor()
DatePicker.setValue(UIColor.greenColor(), forKeyPath: "textColor")
DatePicker.setValue(0.8, forKeyPath: "alpha")
iOS 14 update
After iOS 14 setting background color this way
datePicker.backgroundColor = <# your bg color #>
doesn't work anymore.
So I'm using key value coding approach now:
datePicker.setValue(<# your bg color #> , forKey: "backgroundColor")
I had this same problem. I just created a UIView and put it behind the UIDatePicker
datePickerBackground = [[UIView alloc] initWithFrame:myDatePickerView.frame];
datePickerBackground.backgroundColor = [UIColor whiteColor];
[self.view insertSubview:datePickerBackground belowSubview:myDatePickerView];
I declared UIView *datePickerBackground; in my class. I reuse this same ViewController so I set datePickerBackground to nil on unLoad.
Simple follow these steps
First you set the delegate in your .h file like:
UIPickerViewDelegate, UIPickerViewDataSource
Then add that line where you created the datepicker
YourDatePicker = [[UIDatePicker alloc] init];
YourDatePicker.backgroundColor=[UIColor whiteColor];
In your case the color is white but you can change it to as you want.
Normally, I would say that UIDatePicker inherits from UIView and that you could set the background programatically via a line like yourDatePickerRef.backgroundColor = [UIColor whiteColor];, but it turns out that -- according to this related question -- UIDatePicker has a number of subviews inside of it, some of which are the backgrounds views.
It's these subviews that you need to set the background color to white (instead of clear or whatever it's currently set to).
Yes, it's a bit of a pain, but this makes UIDatePicker a potentially powerful object in terms of being able to customize the appearance of.
Why not add a plain UIView behind the picker. Set the view's background color to white. Give the view the same frame as the picker.
Note (based on your comment to Michael's answer):
Digging around the private subviews of a UIDatePicker is risky. It could break at any time. It is almost guaranteed that your solution will break for date pickers used on a device with a locale that doesn't use AM/PM since the picker will only have two components instead of three.

Can't change the caption of a UIButton from its own Touch Up Inside event

I just noticed this crazy behavior in UIButton:
If I try to set the caption of a UIButton from an IBAction that gets fired on the button's touch up inside event, the caption changes, but is quickly reverted to the old value.
If I do it in some other button's touch up inside event, it works as expected.
What monkey business is going on???
- (IBAction)removeText:(id)sender {
[[sender titleLabel] setText:#"New Text"];
}
titleLabel is a read-only property. You want to use:
[sender setTitle:#"title" forState:UIControlStateNormal];
Edit: Actually, looking it up the titleLabel's own properties are still accessible, but nevertheless the setTitle solution is the way to go....
Correct way would be :
- (IBAction)removeText:(id)sender {
[(UIButton*)sender setTitle:#"New Text" forState: UIControlStateNormal];
}

Is it possible to make a UITextField without rounded edges?

Rounded edges are getting kind of old, and I want my program to have a modern edge. Any idea how this can be done?
To clarify: I want the exact functionality of UITextField without rounded corners.
EDIT: Sorry, I'm a dumbass. I couldn't find the button because the textbox wasn't selected.
{insert facepalm emoticon here}
Just to help anyone who still runs into this, since it isn't clear enough you can use the Storyboard/Xib Interface Builder:
You can just change the borderStyle property of your UITextfield, or provide your own background image by setting backgroundImage property, here is a ref UITextField reference
Subclass UITextfield and override the drawrect: method. I think this should solve your problem.
You can modify a standard UITextView created in Interface Builder in viewDidLoad as follows:
[_textField setBorderStyle:UITextBorderStyleNone];
[_textField setBackgroundColor:[UIColor whiteColor]];
This can also be set the border style and background color directly in Interface Builder.
You need to set a background image and the background color.
UITextField *txtSearchField = [self.searchDisplayController.searchBar valueForKey:#"_searchField"];
[txtSearchField setBackgroundColor:[UIColor whiteColor]];
[txtSearchField setBackground:[[UIImage alloc]init]];

UITextField with black background, clearButton not visible

I try to display a UITextfield with a black background.
But with this black background, the clearButton is not visible.
I can touch it... because I know where is supposed to be, but until
I touch it, nothing is visible.
Here's my code:
textField.background = [UIImage blackColor];
textField.clearButtonMode = UITextFieldViewModeAlways;
How I can make the clearButton to appear ?
Thanks !
You'll need to draw and manage your own clear button, because there's no API for changing the appearance of the built-in button. Read about the rightView and rightViewMode properties of UITextField.
I think you may want to use UIColor to set the background:
textField.background = [UIColor blackColor];
I've created a subclass of UITextField. In this subclass, I used rightView to add and handle a custom delete button. This is the only solution I've found.