customizing UISearchBarIconClear for UIControlStateHighlighted does not work - ios

I have a UISearchBar for which I have set a custom UISearchBarIconClear for UiControlStateNormal.
[mySearchBar setImage:myImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
This part works as it should but unfortunately when tapping the clear button, it changes from the image I set, to the original default gray one.
I have tried setting the image for UIControlStateHighlighted, but apparently that does not work.
The documentation actually states
Valid states are UIControlStateNormal and UIControlStateDisabled.
What's the point of setting a custom button for the default state if you can't set it for the highlighted state? Am I missing something? Any thoughts or workarounds appreciated, thanks!

I had the same problem, and adjusting the order of the statements solved it:
So instead of doing UIControlStateNormal first then UIControlStateHighlighted, set the image for Highlighted state first
[searchBar setImage:clearIcon forSearchBarIcon:UISearchBarIconClear state:UIControlStateHighlighted];
[searchBar setImage:clearIcon forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];

How about using appearance proxy?
[[UIButton appearanceWhenContainedIn:[UITextField class], [UISearchBar class], nil] setImage:myImage forState:UIControlStateHighlighted];

I just had the same problem as you described with the clear icon reseting to the default icon upon being pressed.
This seems to be due to me trying to use the same UIImage for both the normal and highlighted state, switching to a different image for the highlighted state fixed the problem.

Came across the same issue a little bit earlier today, here is my really ugly workaround that I probably wouldn't use myself.
for(UIView *subView in searchBar.subviews) {
if([subView isKindOfClass: [UITextField class]]){
UITextField *searchField = (UITextField *)subView;
CGFloat myWidth = 26.0f;
CGFloat myHeight = 30.0f;
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, myWidth, myHeight)];
[myButton setImage:[UIImage imageNamed:#"searchbariconclear"] forState:UIControlStateNormal];
[myButton setImage:[UIImage imageNamed:#"searchbariconclear"] forState:UIControlStateHighlighted];
[myButton addTarget:self action:#selector(clearsearchbar) forControlEvents:UIControlEventTouchUpInside];
searchField.rightView = myButton;
searchField.rightViewMode = UITextFieldViewModeAlways;
searchField.clearButtonMode = UITextFieldViewModeNever;
}
}
And then..
- (void)clearsearchbar {
for(UIView *subView in searchBar.subviews) {
if([subView isKindOfClass: [UITextField class]]){
UITextField *searchField = (UITextField *)subView;
searchField.text = nil;
}
}
}
Three problems with this approach..
Since we're digging around inside the subviews of the searchbar it could break some day with an OS update.
This doesn't behave exactly like UISearchBarIconClear, in that the clear icon will always be visible.. You could potentially try testing with other UITextFieldViewModes using this approach, I didn't mainly because, from what I know none of the others would be ideal here, for some reason or the other.
Maybe it's just me, but I don't really think that something that introduces two problems when trying to solve one, is a solution. :-)
If anyone has a better way of tackling this problem, I'd love to hear it too.

Related

UIButton.titleLabel.frame.size always with zero values

i develop one project in xcode on Objective C. All was fine before last two days. Now all my buttons and other controls do not show their title text or images. I try to add new button from storyboard but it text still not showing.
Also i try to add new button from code but result the same.
- (void) addTestButtonProgramatically {
testButton = [UIButton buttonWithType:UIButtonTypeCustom];
[testButton addTarget:self
action:#selector(testButtonSelector:)
forControlEvents:UIControlEventTouchUpInside];
[testButton setTitle:#"TEST TEXT" forState:UIControlStateNormal];
[testButton setBackgroundColor:[UIColor colorWithRed:0.6 green:0.1 blue:1.0 alpha:1.0]];
testButton.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:testButton];
}
- (IBAction)testButtonSelector:(id)sender {
[testButton.titleLabel sizeToFit]; //this row make text of my button shown
}
Maybe i mistakenly changed the setting which made such behavior. I try to lunch my project on another computer and issue is still there too.
Then i try to create new clear project and there everything was fine, text of buttons is visible.
Edit:
I find cause of my issue. It was because i redefine - (void) layoutSubvies method on UIButton category.
#interface UIButton (Coordinator)
#end
#implementation UIButton (Coordinator)
- (void) layoutSubviews {
[super layoutSubviews];
}
#end
Thens for all who help me find that.
add [testButton.titleLabel sizeToFit] to addTestButtonProgramatically method. why are you fitting size of button's text in it's own click..?!. you should do it when you setup the button
Update :
[self.button layoutIfNeeded]; // call this after adding button in view if you are using autolayout

How to set background color for UIActionSheet

In the following method
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet{
I have set:
[button setBackgroundColor:[UIColor redColor]];
This is for one button.
But here is what I get:
What I want to know is how to set the color only on button without the side gaps ?
Any guidance or help is appreciated.
Thanks.
I also need the custom UIAcionSheet but default actionsheet doesn't support the customization functionality so i used the other customer controller UICustomActionSheet and got the expected result like
If you want to change the title color use the below code.
for (UIView *view in actionSheet.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
}
}

UIButton does not change background on touchUpInside

I have some custom type UIButtons placed pragmatically in a custom view. The view is basically a menu. I am generating the buttons with the following code, inside the view's .m file:
-(void) generateButtons: (NSMutableArray *) buttonsArray
{
UIImage *barItemImage = [[UIImage imageNamed:#"ipad-menubar-button.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
float buttonWidth = (self.frame.size.width - (2 * FIRSTBUTTONXCOORDINATE) - 25)/ 6.0f;
float xCoord = FIRSTBUTTONXCOORDINATE;
float yCoord = (self.frame.size.height - BUTTONHEIGHT) / 2.0f;
for (int i = 0; i < buttonsArray.count; i++)
{
NSString* buttonTitle = [buttonsArray objectAtIndex:i];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(botButtonAction:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:buttonTitle forState:UIControlStateNormal];
button.frame = CGRectMake(xCoord, yCoord, buttonWidth, BUTTONHEIGHT);
button.tag = i;
[button setBackgroundImage:barItemImage forState:UIControlStateNormal];
xCoord += buttonWidth + 5;
[self addSubview:button];
}
}
On touchUpInside, botButtonAction is called and it does what it is supposed to. However, the buttons do not usually give any visual indication of the touchUpInside. When I touchDown on a button and swipe in any direction, then I see the background color get darker. Sometimes, I see the same visual indication on touchUpInside. It seems completely random though.
Any ideas as to what I might be doing wrong here?
Edit: Sorry, I got occupied with other issues. Here is the code for botButtonAction and the method it calls
-(void) botButtonAction: (UIButton *) sender
{
if (self.delegate)
[self.delegate optionsMenuAction:self data:sender.tag];
}
-(void)optionsMenuAction:(OptionsMenueView *)view data:(int)tag
{
if (self.PDFVC)
{
[self.navigationController popToViewController:self animated:YES];
}
if (!self.optionsMenue.isAtWPC || tag != WPC)
[self transitionFromViewAtIndex:self.selectedVCIndex toView:tag];
else
[self transitionFromViewAtIndex:self.selectedVCIndex toView:WPList];
}
But since I am using touchUpInside, these methods don't get called on touchDown. I just want the button to be highLight (grayout the bg a little) on touchDown. As I state before, that happens on touchDown and swipe.
Edit
I had so far been running this on actual devices (iPad air and iPad 2). When I tried running it on the simulator, I get the correct result. On mouse click, the button gets highlighted.
Edit
I think I figured out the exact problem (still looking for a solution). If I touchDown precisely on the button and the touch does not cover any part of the insets, then the highlighting works. However, if the touch covers part of the button and also part of the insets/outside, then the highlighting doesn't work.
add this line:
[button setBackgroundImage:HighlightImage forState:UIControlStateHighlighted];
change the title colour when tap on the button like this
[yourButon setTitleColor:[UIColor colorYouWant] forState:UIControlStateHighlighted];
hope this will help you......
put this code in botButtonAction:
-(void)botButtonAction:(UIButton *)sender
{
[sender setBackgroundImage:[UIImage imageNamed:#"some iamge.png"]
forState:UIControlStateNormal];
}
or use the code below code in for loop
[button setBackgroundImage:[UIImage imageNamed:#"back_button_press.png"] forState: UIControlStateHighlighted];
or if you want to give some color then setcolour of button
I had this problem at some point too. These other answers will give you the result you seek normally. However.... You are using [UIButton buttonWithType:UIButtonTypeCustom].. Which is really buggy if you do not alloc/init the UIButton.. Try changing this line to a normal button allocation and then add the following lines of the answers in this post. This should work for you.
So in short,
replace [UIButton buttonWithType:UIButtonTypeCustom];
with [[UIButton alloc] init];
And then add the following changes to your code to change the image.
[myNewlyAllocatedButton setBackgroundImage:[UIImage imageNamed:#"back_button_press.png"] forState: UIControlStateHighlighted];

Changing UISearchBar search field background

I have a UISearchBar contained within a UIView and the UIView has been assigned to a UITableView's tableHeaderView. I'm trying to style the UISearchBar to look like this:
Out of the gate, this is what it looks like:
There are loads of SO questions and answers on how to style UISearchBar, its search field, etc., some with particular attention to backgrounds. Many of them involve traversing the UISearchBar's subviews, finding a UISearchBarBackground (or _UISearchBarSearchFieldBackgroundView) object, and setting its background color directly. I'm trying to find a supported API for doing this, however...
The setSearchFieldBackgroundImage:forState: method seems to have great potential, but this is what I get when I use a 1px white (or transparent) image using UIControlStateNormal:
Any ideas as to how to get this to work? I'd appreciate someone pointing me to a SO post that answers this, but I really do think I've read them all. Thanks a ton.
you can use the appearanceWhenContainedIn to target elements without traversing the view hierarchy. Something like:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor whiteColor]];
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor lightGrayColor]];
UPDATE:
As appearanceWhenContainedIn is now deprecated, use
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar self]]] <your setter here>];
I think the problem here is that when you use setSearchFieldBackgroundImage:forState:, the height of your image actually determines the height of the search field. The standard search field (at least as of iOS 8) is 28 points tall, so an image that height should give the effect you're after.
(Somewhat confusingly, this also means that a nine-part stretchable image generally won't look right—so if you were going for a look that wasn't just white on white, you need to use a three-part stretchable image that only stretches horizontally.)
Above iOS 5.0
[[UISearchBar appearance] setSearchFieldBackgroundImage:[UIImage imageNamed:#"YourBackground.png"]forState:UIControlStateNormal];
Please try following code
[[UISearchBar appearance]setBackgroundImage:[UIImage imageNamed:#“searchbar_bg.png"]];
for (UIView *searchbuttons in searchBar.subviews) {
if ([searchbuttons isKindOfClass:[UIButton class]]) {
UIButton *cancelbutton = (UIButton *)searchbuttons;
[cancelbutton setBackgroundImage:[UIImage imageNamed:#“canelBtn.png"] forState:UIControlStateNormal];
}
}
UITextField *searchField = [searchBar valueForKey:#"_searchField"];
searchField.background = [UIImage imageNamed:#"bg.png"];
You can use either the barTintColor or the backgroundImage property of the UISearchBar to directly accomplish what you are trying to do.
I reproduced your problem, and it seems to be solved by:
self.searchDisplayController.searchBar.barTintColor = [UIColor whiteColor];
or
self.searchDisplayController.searchBar.backgroundImage = [self imageWithColor:[UIColor whiteColor]];
P.S. If you are using the backgroundImage solution, you'll need to make the method imageWithColor as follows
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Tell me if it works!
iO9 Perfect works.
- (void)viewDidLoad
{
[super viewDidLoad];
[[self searchSubviewsForTextFieldIn:self.searchBar] setBackgroundColor: [UIColor redColor]];
}
- (UITextField*)searchSubviewsForTextFieldIn:(UIView*)view
{
if ([view isKindOfClass:[UITextField class]]) {
return (UITextField*)view;
}
UITextField *searchedTextField;
for (UIView *subview in view.subviews) {
searchedTextField = [self searchSubviewsForTextFieldIn:subview];
if (searchedTextField) {
break;
}
}
return searchedTextField;
}
#joneswah's answer is depricated in iOS 9.
For iOS 9 put this in your AppDelegate.m. I also added workaround for keyboard opening lag, when keyboard is initiated for the first time.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Remove lag on oppening the keyboard for the first time when clicked on any UITextField
UITextField *lagFreeField = [[UITextField alloc] init];
[self.window addSubview:lagFreeField];
[lagFreeField becomeFirstResponder];
[lagFreeField resignFirstResponder];
[lagFreeField removeFromSuperview];
//searchBar background color change
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar class]]] setBackgroundColor:[UIColor greenColor]];//background color
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar class]]] setTextColor:[UIColor blackColor];//text color
return YES;
}
As others suggested, you need to traverse through your searchbar's subviews and finding the UITextField instance. BUT, you need to set its layer.backgroundColor, as setting the backgroundColor property has no effect. I'll give an example:
for view in searchBar.subviews {
for subview in view.subviews {
if let searchField = subview as? UITextField {
searchField.layer.backgroundColor = UIColor.whiteColor().CGColor
}
}
}
This will give you what you need.
My answer stably works on ios 5 and above, including this 10. Without hacks and KVO, by Apple Way
The following code will achieve the result.
_sbAddress.barTintColor = [UIColor whiteColor];
for (UIView *subView in _sbAddress.subviews) {
for(id field in subView.subviews){
if ([field isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)field;
[textField setPlaceholder:#"Search"];
}
}
}
OR
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setPlaceholder:#"Search"];

How to change highlighted color of buttons in UIActionSheet - iPad

I would change the highlighted color of buttons in UIActionSheet in iPad app, because I need to change the default blue in an another color... I only found solution that uses undocumented function, and maybe this is the only way to do this ! But I would avoid to use a solution that could prevent me to go on the App Store...
Any ideas or github project to link ?
I solved in this way:
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet {
//Gets an array af all of the subviews of our actionSheet
NSArray *subviews = [actionSheet subviews];
for (UIView *v in subviews) {
if ([v isKindOfClass:[UIButton class]]) {
UIButton *b = (UIButton*)v;
[b setBackgroundImage:[UIImage imageNamed:#"backActionSheetHighlighted.png"] forState:UIControlStateHighlighted];
[b setBackgroundImage:[UIImage imageNamed:#"backActionSheet.png"] forState:UIControlStateNormal];
}
}
}
the result is the following:
follow the link, you will find how to add subview in action sheet http://www.ifans.com/forums/showthread.php?t=301851. Then in button you can try this:
[myButton setBackgroundImageByColor:[UIColor greenColor] forState:UIControlStateHighlighted ];

Resources