How do you customise UISearchBar colors in iOS7? - ios7

I have searched quite a bit but cannot find a good answer to this.
I want to change the backgroundColor of the inner rounded view.
Like in Tweetbot on the search tap where it changes from gray to blue.
I understand that I probably need to iterate over the subviews but I don't know how to get the right object. (for the backgroundColor it's not the _searchLabel)
The default contrast of this element is so bad it's not even funny :(

Ok, this works. But note that you can't set a UIBarStyle beforehand or it will override everything.
https://stackoverflow.com/a/19836215/1252720

If you're still looking for a better answer, I just stumbled across this thread and found a great solution: UISearchBar text color change in iOS 7
If you look at the answer given by Sandeep-Systematix (not the accepted answer, but the answer right below), he mentions a really clean way to modify subviews in any class with this method:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor blueColor]];
You can read more about this in Apple's documentation: https://developer.apple.com/library/ios/documentation/uikit/reference/UIAppearance_Protocol/Reference/Reference.html
That said, here's what you'll need to change the white, rounded background of the UITextField inside the UISearchBar:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor redColor]];
Now if you needed to create different UISearchBars with different styles, you would simply create a subclass of UISearchBar and you'd end up with something like this:
[[UITextField appearanceWhenContainedIn:[MyCustomSearchBar class], nil] setBackgroundColor:[UIColor redColor]];

Use this code.
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.contentView.bounds.size.width, 44.0f)];
_searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_searchBar.delegate = self;
[self.view addSubView:_searchBar];
UITextField *txfSearchField = [_searchBar valueForKey:#"_searchField"];
txfSearchField.backgroundColor = [UIColor redColor];

Related

CustomSearchBar color differs from the one in UINavigationBar

Im using:
#define colorApp [UIColor colorWithRed:254/256.f green:64/256.f blue:89/256.f alpha:1.0]
Inside the customSearchView init:
[self setBackgroundColor:colorApp];
searchBar = [[UISearchBar alloc] initWithFrame:frame];
searchBar.barTintColor = colorApp;
[self addSubview:searchBar];
Getting the next result:
I need the searchBarTint color to be the same as the navigation. Translucent doesn't seem to make the work.
I came up with the fix soon after I posted the question.
In case anyone ever faces this problem I used
[self.searchDisplayController.searchBar setBackgroundImage:[UIImage imageNamed:#"pinkBar.png"]
forBarPosition:0
barMetrics:UIBarMetricsDefault];
It seems backgroundColor and barTintColor aren't taking colors same way as the navigation for a UISearchDisplayController since iOS 7. But adding an image with that color just resolves that.
I know it's just a quick fix but it helped me and could help others as it is a minor visual issue.

Adding two right bar button items to the navigation bar

I have a navigation bar to which I have added right BarButton successfully. Both the NavigationBar and BarButton are created programmatically. Now according to my requirement I got to add two right BarButtons to my navigation Bar. Can anyone tell me how to do this? My app is targeting ios4.
This code will do the trick for you,
NSArray *barButtonItems= [[NSArray alloc] initWithObjects:self.addButton,self.sortbyButton,nil];
self.navigationItem.rightBarButtonItems=barButtonItems;
where addButton and sortbyButton are 2 separate BarButton Items
I know it is too late but I faced it recently. So here is what I did
Create a UIView in code and add the buttons as subviews into this view.
Create a ToolbarButton using [[UIBarButtonItem alloc] initWithCustomView:buttons]
Assign this toolbar button as the Left or right barbuttonItem as U wish.
If you application is targeting iOS 4 and above then you should take UISegmentControl and have two segments on it. Catch value changed action event and check which segment is selected and do you operation accordingly.
You can also set images to segments to make look and feel better.
As the documentation to UINavigationItem1 describes, it has a property rightBarButtonItems (as well as leftBarButtonItems) where you can give an array of UIBarButtons. They are display from right (index 0) to left (index n-1).
#Matthias, As stated in documentation, rightBarButtonItems property is available from iOS 5 and above and this function needs to be supported also on iOS 4.
So, UISegmentControl is best way to achieve this.
NSArray *segmentTextContent = [NSArray arrayWithObjects:
NSLocalizedString(#\"Group By\", #\"\"),
NSLocalizedString(#\"Filter By\", #\"\"),
nil];
UISegmentedcontrol *segmentedControl = [[UISegmentedControl alloc] initWithItems:segmentTextContent];
segmentedControl.selectedSegmentIndex = 0;
segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.frame = CGRectMake(0, 0, 125, 30);
[segmentedControl addTarget:self action:#selector(toggleUnit) forControlEvents:UIControlEventValueChanged];
segmentedControl.tintColor = [UIColor lightGrayColor];
defaultTintColor = [segmentedControl.tintColor retain];
self.navigationItem.rightBarButtonItem = segmentedControl;
[segmentedControl release];

Custom View with UILabel in it appears black

I have created a custom UIView that has some set of UILabels in it. I add those UILabels inside the custom view inside its drawRect method.
But the whole custom view appears black on the screen. I have not set any background color for the custom UIView. How Do I fix this?
I tried setting background color to ClearColor but it still looks black.
I tried setting opaque property of the custom view to false and the view obviously disappeared.
Please help.
don't do that in drawRect: method which is intended to draw in the graphic context. If you want to add some specific subviews do it in an init / initWithFrame method.
For me the best way is to create a custom uiviewcontroller subclass and initialize it using a xib (nib) file. Working at controller level is a good practice.
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(10,0,320,35)];
newView.backgroundColor=[UIColor clearColor];
UILabel *mytext = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 28.0)];
mytext.backgroundColor = [UIColor clearColor];
mytext.textColor = [UIColor blackColor];
mytext.editable = NO;
mytext.text = #"Your label";
[newView addSubview:mytext];
[mytext release];
[self.view addSubview:newView];
[newView release];
Just incase someone stumbles upon this thread like I did in 2021. Check to see if you have accidentally toggled 'dark mode'. It will show similar visual 'issues' to the question above.

UINavigationBar and new iOS 5+ appearance API - how to supply two background images?

I want to exploit the new iOS 5 appearance API to supply custom background images to all UINavigationBar instances in my app. To do this, it's as simple as this:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"whatever.png"] forBarMetrics:UIBarMetricsDefault];
However, for each instance, I want to provide a different image depending on the value of the translucent property, e.g.
// For UINavigationBar instances where translucent returns YES:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"whatever-translucent.png"] forBarMetrics:UIBarMetricsDefault];
// Otherwise:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"whatever.png"] forBarMetrics:UIBarMetricsDefault];
Given that the appearance APIs seem to be configured using class methods, is something like this possible?
At the moment, there's no way to do what you're describing - the appearance proxy doesn't know anything about any particular instance at the time you're calling for it.
In practical terms, what you'll probably need to do is figure out how many translucent bars you'd have v. how many non-translucent ones you had. Choose whichever you have more of and use the appearance proxy for that one - for the others, when you go to make it translucent (or ask for full-screen layout), you'll have to set the background image then.
In the meantime, could you file an enhancement request at http://bugreport.apple.com/ for what you're asking? It's not an unreasonable request. Thanks!
You can either set it globally with the class appearance proxy or set it on an instance of a navBar.
I'm currently setting background on an instance of the nav bar and it seems to be working. I have two different navBars with different backgrounds. If you set it on an instance, you should be able to condition the code.
UINavigationController *myNavController = [[UINavigationController alloc] initWithRootViewController:myView];
[viewControllers addObject:myNavController];
// not supported on iOS4
UINavigationBar *navBar = [myNavController navigationBar];
if ([navBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)])
{
// right here, you could condition bg image based on properties of this instance
// of the navBar or any other condition.
[navBar setBackgroundImage:[UIImage imageNamed:#"bg.jpg"] forBarMetrics:UIBarMetricsDefault];
}
If you want to set using the class method, you can set for all:
[[UINavigationBar appearance] setBackground ...
I will admit though that it's pretty new and I'm just figuring it out like most folks.
This answer probably won't be of much help to you, but it may be to others. IF you make a subclass, you can specify the appearance for each subclass separately. For instance, I have UITableviewCells and a custom class that is derived from UITableViewCells. I actually do this for a reason, but I discovered that i need to call [[UITableViewCells appearance] setFont:[...]] for both classes specifically.
Since you seem to want to do so based upon a variable that you will not know until runtime, you are probably out of luck!
You can do it like this if you know which classes contain the translucent bars:
[[UIBarButtonItem appearanceWhenContainedIn:[MyClassWithTranslucentBar class], [MyOtherClassWithTranslucentBar class], nil]
setTintColor:desiredColor];
I cant leave a comment so will have to be an answer. Rob Whitlow wrote a great article on this. Check it out: http://ios-blog.co.uk/tutorials/ios-custom-ui-series-tabbar-navbar/
Try this:
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
// Load resources for iOS 6.1 or earlier
navigationController1 = [self customizedNavigationController];
[navigationController1 setViewControllers:[NSArray arrayWithObject: self.homeViewController]];
[self setNavigationController:navigationController1];
[self.window setRootViewController:navigationController];
} else {
// Load resources for iOS 7 or later
navigationController1 = [[UINavigationController alloc] initWithRootViewController:self.homeViewController];
[self.window setRootViewController:navigationController1];
}
- (UINavigationController *)customizedNavigationController {
UINavigationController *navController = [[UINavigationController alloc] initWithNibName:nil bundle:nil];
// Ensure the UINavigationBar is created so that it can be archived. If we do not access the
// navigation bar then it will not be allocated, and thus, it will not be archived by the
// NSKeyedArchvier.
[navController navigationBar];
// Archive the navigation controller.
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:navController forKey:#"root"];
[archiver finishEncoding];
// Unarchive the navigation controller and ensure that our UINavigationBar subclass is used.
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[unarchiver setClass:[LNTNavigationBar class] forClassName:#"UINavigationBar"];
UINavigationController *customizedNavController = [unarchiver decodeObjectForKey:#"root"];
[unarchiver finishDecoding];
// Modify the navigation bar to have a background image.
LNTNavigationBar *navBar = (LNTNavigationBar *)[customizedNavController navigationBar];
[navBar setTintColor:[UIColor colorWithRed:0.39 green:0.72 blue:0.62 alpha:1.0]];
[navBar setBackgroundImage:[UIImage imageNamed:#"nav_bar_1024_46.png"] forBarMetrics:UIBarMetricsDefault];
[navBar setBackgroundImage:[UIImage imageNamed:#"nav_bar_1024_46.png"] forBarMetrics:UIBarMetricsLandscapePhone];
return customizedNavController;
}

Resize UITableViewCell content when delete button shows up

Is there any way to use autoresizing masks to move my content so that the delete button doesn't cover it up? Googling has told me that I need to set an autoresizing mask of UIViewAutoresizingFlexibleRightMargin on my subview. It seems to me like UIViewAutoresizingFlexibleWidth would actually make more sense; though I've tried them both and neither works.
The view that I am trying to shrink is just a label that is a subview of the cell's contentView. I am unsure if the contentView itself automatically resizes when the delete button shows up; but it seems like it isn't; otherwise my autoresizing mask should have worked.
If the presence of the delete button doesn't cause any views to be resized; is there anyway that I can do this manually?
You should use UIViewAutoresizingFlexibleLeftMargin.
Here's why. You want your contents to move to the left, basically making it seem like the delete button is pushing the contents to the left, out of it's way. flexibleLeftMargin basically means your UILabel will stay fixed to the right side of your contentView. The reason you want this, is because the delete button actually causes your contentView to shrink it's width.
The autoresizingmask of your UILabel refers to how it behaves inside the contentView, not the cell.
Give it a try, it should work.
This question is really old but I feel I should answer this anyway since I just found the solution myself.
Only the cell's ContentView gets resized with the confirmation button is shown. If you don't add your views (labels, imageviews, etc...) to the cell.contentView instead of adding them to the cell directly then they won't be resized when the contentView is resized. In my case, I was adding it to the cell directly.
So, instead of doing something like:
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, width-10, 20)];
[nameLabel setFont:[UIFont boldSystemFontOfSize:16]];
[nameLabel setHighlightedTextColor:[UIColor whiteColor]];
[nameLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[nameLabel setTag:101];
[cell addSubview:nameLabel];
[nameLabel release];
you should do:
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, width-10, 20)];
[nameLabel setFont:[UIFont boldSystemFontOfSize:16]];
[nameLabel setHighlightedTextColor:[UIColor whiteColor]];
[nameLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[nameLabel setTag:101];
[[cell contentView] addSubview:nameLabel]; // <<--- note the change in this line!
[nameLabel release];
Hope this helps others who stumble upon this issue.
I am using iOS 7, I got the same issue. I am using a separate xib for the UITableViewCell with auto layout enabled, so just added one more constraint to the label so that it will have a fixed gap on its right side.