UISegmentedControl in Mail app - iphone

How do I get a UISegmentedControl that is like the one in the Mail App, so that it is the same colour as UIToolbar buttons (as if both segments were in the selected state).
I want to use the segmented control for exactly the same purpose as Mail.
(on the iPad, so a grey not blue color)

This is code from Apple Sample codes... NavBar and both the images used in the code..
you shoud be able to get exact same view as mail App.
// "Segmented" control to the right
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
[UIImage imageNamed:#"up.png"],
[UIImage imageNamed:#"down.png"],
nil]];
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
segmentedControl.frame = CGRectMake(0, 0, 90, 30);
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.momentary = YES;
defaultTintColor = [segmentedControl.tintColor retain]; // keep track of this for later
UIBarButtonItem *segmentBarItem = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];
[segmentedControl release];
self.navigationItem.rightBarButtonItem = segmentBarItem;
[segmentBarItem release];

You seek the tintColor property!
When you use a UISegmentedControl you can change its tint color to any color you can dream up. So, if you added the UISegmentedControl in Interface Builder then you would style it in your - (void)viewWillAppear:(BOOL)animated method as such (assuming you had it hooked up to a #synthesized ivar:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Set the tintColor to match the navigation bar
self.mySegmentedControl.tintColor = [UIColor colorWithRed:.94 green:.94 blue:.94 alpha:1];
... do whatever else in your viewWillAppear ...
}
Now obviously you will want to play with the red, green, blue, and alpha's that I've put in the sample code above, but you can literally tint the UISegmentedController any color you would like (or make it as transparent as you would like), so it's just a matter of finding the RGBA values that look perfect to you.
Remember that per Apple's docs that the default value of this property is nil (no color). UISegmentedControl uses this property only if the style of the segmented control is UISegmentedControlStyleBar.
Good luck!

I dont know exactly what you mean.. but i believe the "UISegmentedControlStyleBar" as segmentedControlStyle could it be.
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar
You can set this property in the IB too! (It's the property called "style")

The style I'm looking for is undocumented: it is style 4.
It looks like he up/down control here: http://media.mobilemeandering.com/wp-content/uploads/2010/04/ipad-mail-message-2.png
(not my image btw)
It basically makes all segments look selected, it's intended for momentary pushes, and is effectively multiple tool bar buttons pushed up together.
So it can't be set in IB but must be set in code or manually in the nib/xib file, by opening the nib as a text file.

I'm not sure I exactly understand what you're trying to do, but I'll give it a shot.
The solution is not obvious, you need to use a UISearchDisplayController in order to get a matching UISearchBar and UISegmentedControl.
See the TableSearch sample code for an example.

Related

UISegmentedControl inside title of UINavigationBar looks unformatted

I'm trying to add a UISegmentedControl within the title of a UINavigationController. However, the formatting looks like this (i.e. its ugly).
When I want it to look like this (pretty :). Can anyone help??
I've read the popular example by Red Artisan here. But I'm not showing this as my first view (like Red Artisan does), so I've moved a lot of the code out of App Delegate. In App Delegate, I do set up this screen to be a UINavigationController with its rootView a UIViewController.
GenInfoViewController *genInfoController = [[GenInfoViewController alloc] initWithNibName:#"GenInfoViewController" bundle:nil];
UINavigationController *genInfoNavController = [[UINavigationController alloc] initWithRootViewController:genInfoController];
Then in viewDidLoad of GenInfoViewController.m I do the following:
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"Info",#"Map"]];
self.navigationItem.titleView = self.segmentedControl;
To style a segmented control, set the segmentedControlStyle property to one of the following:
UISegmentedControlStylePlain
UISegmentedControlStyleBordered
UISegmentedControlStyleBar
UISegmentedControlStyleBezeled
For example:
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"Info",#"Map"]];
self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBordered;
self.navigationItem.titleView = self.segmentedControl;
    
There's some relevant Q+As on here regarding styling segment controls:
Custom segment control
Remove rounded corner
Change font size
Change colour of selected segment
If you'd like to try a custom segmented control, check out all the available CocoaControls and CocoaPods.
Yup, you need to set the property "segmentedControlStyle" on your UISegmented control.
Your options are as follows:
typedef enum {
UISegmentedControlStylePlain,
UISegmentedControlStyleBordered,
UISegmentedControlStyleBar, // This is probably the one you want!
UISegmentedControlStyleBezeled,
} UISegmentedControlStyle;
So the following should probably do the trick:
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"Info",#"Map"]];
self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
self.navigationItem.titleView = self.segmentedControl;
One thing you might also want to consider is setting the "tintColor" of the segmented control too.
self.segmentedControl = [UIColor blackColour];
Will leave you with something like this:
Obviously there is lots of other customisation you can do too. Take a look at the documentation here: http://developer.apple.com/library/ios/#documentation/uikit/reference/UISegmentedControl_Class/Reference/UISegmentedControl.html

Displaying notification badge like counter in UINavigationbar

I have a requirement to display number of pending notifications in iPhone navigation bar. The appearance should be like that of notification badge - but these are not APNS notifications. They are the ones sent from private server with similar purpose.
I tried adding a right/left button (UIBarButtonItem) in my UINavigationbar but it seems like it is very rigid in appearance. I can't set its width, fonts etc. See my code:
self.notifButton = [[UIBarButtonItem alloc] initWithTitle:#"0" style:
UIBarButtonItemStyleBordered target:self action:#selector(TouchNotif)];
NSMutableArray *items = [[NSMutableArray alloc] init];
[items addObject:self.notifButton];
self.navigationItem.rightBarButtonItems = items;
Because of other 2 items also added to items array, navbar is cluttered. Their fonts, width etc I cannot play with, or maybe I don't know how should I create them.
My questions:
1) What is proper way to accommodate at least 3 items in navbar right area? I am asking this because I don't find a way to play with width and font of the UIButtons I use.
2) If I want to have custom appearance for my notification button (just like notification badge) - are there any pointers how do I make it? Which control to use, how to set its frame and font which will be allowed within UINavigationBar?
Please help.
You need to create a UIBarButtonItem that contains a custom view using initWithCustomView.
The custom view could be a custom UIButton with a number badge as subview. With this custom view you can also control the width of the buttons.
There is no public API to create a notification badge directly. In case of a tab bar item you could set a badge using the property badgeValue - but not with UIBarButtonItem.
Here you need to use this open source control: MKNumberBadgeView.
Note that the property rightBarButtonItems is available since iOS 5.
If you only need one item set the rightBarButtonItem instead.
UIButton * buttton = [UIButton buttonWithType:UIButtonTypeCustom];
[buttton setFrame:CGRectMake(285, 20, 20, 20)];
[buttton.layer setCornerRadius:10];
[buttton setTitle:#"23" forState:UIControlStateNormal];
[buttton.titleLabel setFont:[UIFont systemFontOfSize:12]];
[buttton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[buttton setBackgroundColor:[UIColor whiteColor]];
[self.navigationController.view addSubview:buttton];
First get the respective barbuttonitem in navigationController by
let baritem = navigationItem.right/leftBarButtonItem
baritem.badgeValue = "\(correspondingValues)"

How can I style an MKUserTrackingBarButtonItem?

I'm adding the items programatically, but MKUserTrackingBarButtonItem doesn't seem to offer any way to style it to fit in with a BlackTranslucent UIToolBar...
MKUserTrackingBarButtonItem is a subclass of UIBarButtonItem which has a tintColor property. You can use this to make your button black.
MKUserTrackingBarButtonItem *userTrackingBarButtonItem =
[[MKUserTrackingBarButtonItem alloc] initWithMapView:self.mapView];
[self.navigationController.toolbar setBarStyle:UIBarStyleBlack];
[userTrackingBarButtonItem setTintColor:[UIColor blackColor]];
If you do set it to black like this, the user will never know when it's activated, as the blue color is never shown.

Adding button to left of UISearchBar

I am tearing my hair out on this one. My client wants to add a button to the left of a search bar like the example below:
(source: erik.co.uk)
But I just can't figure out how to do it. Apple don't seem to provide any documented method for adding custom buttons to a UISearchBar, let alone to the left of the search bar.
I've tried hacking around in Interface Builder adding a UIToolbar with a button in it to the left but I cannot find any combination of styles where the two line up properly to give the impression that they are one. There is always what looks like one pixel difference in the vertical alignment as you can see from the picture below:
(source: erik.co.uk)
I've searched around and just can't find the answer, but as we can see from the screenshot it must be possible!
Thank you in advance for your help.
Erik
Use a navigation bar instead of a toolbar. Set the search bar to the navigation bar's title view.
In Interface Builder:
Result:
You can replace the Bookmark image instead, and adjust its offset if necessary.
For example:
[self.searchDisplayController.searchBar setImage:[UIImage imageNamed:#"plus2"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal];
[self.searchDisplayController.searchBar setPositionAdjustment:UIOffsetMake(-10, 0) forSearchBarIcon:UISearchBarIconBookmark];
Handle the button event in the delegate method:
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar
This is how it looks:
The first solution is to use UINavigationBar instead of UIToolbar, as KennyTM noticed. But you may not be satisfied with Navigation bar, like in my case, when I need to use 3 buttons (Navigation bar is allow to use only 2 buttons) - see the left picture. This is how I did it:
Use Toolbar with 3 buttons and Flexible Space Bar Button Item in the place where search bar should be placed.
Put search bar on (not in) the toolbar. To do so in Interface Builder, do not drag & drop the search bar on the toolbar. Instead, put it somewhere nearby and then move it to place using the arrow keys on the keyboard (or by changing X & Y position in Interface Builder).
Search bar left black line under it (see the right picture). To hide it I put one additional view with the height 1px and a white background over it.
It looks a bit dirty for me, so if you have a better solution, let me know.
The easiest solution is to add your SearchBar in TOP of your Toolbar, (not in), I give you the best solution I use in my company eBuildy:
UIBarButtonItem *mySettingsButton = [[UIBarButtonItem alloc] initWithTitle:#"Settings" style:UIBarButtonItemStyleBordered target:self action:#selector(refresh)];
UIBarButtonItem *mySpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *myRefreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(refresh)];
UIToolbar *myTopToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0,0,320,40)];
UISearchBar *mySearchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(70,1,220,40)];
[myTopToolbar setItems:[NSArray arrayWithObjects:mySettingsButton,mySpacer,myRefreshButton, nil] animated:NO];
[self.view addSubview:myTopToolbar];
[self.view addSubview:mySearchBar];
answering an old question here but i was struggling with this one myself recently and found some shortcomings with the other answers for the situation i was trying to address. here's what i did in a subclass of UISearchBar:
first add a UIButton property (here "selectButton"). then override the initWithFrame method and do something similar to the following:
-(id)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame])
{
self.selectButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.selectButton.contentEdgeInsets = (UIEdgeInsets){.left=4,.right=4};
[self.selectButton addTarget:self action:#selector(pressedButton:) forControlEvents:UIControlEventTouchUpInside];
self.selectButton.titleLabel.numberOfLines = 1;
self.selectButton.titleLabel.adjustsFontSizeToFitWidth = YES;
self.selectButton.titleLabel.lineBreakMode = UILineBreakModeClip;
[self addSubview:self.selectButton];
[self.selectButton setFrame:CGRectMake(5, 6, 60, 31)];
}
return self;
}
Now you want to override the layout subviews method to resize the searchbar to the appropriate width, depending on whether or not the cancel button is showing. That should look something like this:
-(void)layoutSubviews
{
[super layoutSubviews];
float cancelButtonWidth = 65.0;
UITextField *searchField = [self.subviews objectAtIndex:1];
if (self.showsCancelButton == YES)
[searchField setFrame:CGRectMake(70, 6, self.frame.size.width - 70 - cancelButtonWidth, 31)];
else
[searchField setFrame:CGRectMake(70, 6, self.frame.size.width - 70, 31)];
}
Note that in the above method I added a constant for the cancelButtonWidth. I tried adding code to get the width from [self cancelButton] but that seems only accessible at runtime and doesn't allow the project to compile. In any case this should be a good start for what you need
If you want a custom button on the right, taking place of the Cancel button, just use this code (valid for iOS 9 and up):
[self.searchBar setShowsCancelButton:YES];
[[UIBarButtonItem appearanceWhenContainedIn:[self.searchBar class], nil] setTitle:#""];
[[UIBarButtonItem appearanceWhenContainedIn:[self.searchBar class], nil] setImage:[UIImage imageNamed:#"search"]];

How do you add more than one UIBarButton on UINavigationItem.rightBarButtonItem (or leftBarButtonItem)?

I have tried this approach/hack:
http://blog.blackwhale.at/2009/06/uibuttons-in-uinavigationbar/
The problem is this leaves a faint seam. I tried setting the background image of the nested toolbar to an image I captured of what it should be. That didn't work. The image was not applied. I have also tried using a nested UINavigationBar and that didn't seem to work.
I have seen this done in several iPhone apps. Does anyone know how?
[EDIT] I want the buttons to look like normal UIBarButtonItems and be able to use system styles like UIBarButtonSystemItemAdd, UIBarButtonSystemItemRefresh. The link I provided does this except you can see a faint seam because it is a UIToolbar nested in the navigationbar..
Please don't mention this breaking the Human Interface Guidelines. (We know).
I appreciate you contributing your hacks... thats the only way to do this!
iOS 5.0 now supports multiple buttons. See the iOS documentation for UINavigationItem. Specifically, the following:
Properties:
#property(nonatomic, copy) NSArray *leftBarButtonItems;
#property(nonatomic, copy) NSArray *rightBarButtonItems;
#property BOOL leftItemsSupplementBackButton;
Methods:
- (void)setLeftBarButtonItems:(NSArray *)items animated:(BOOL)animated;
- (void)setRightBarButtonItems:(NSArray *)items animated:(BOOL)animated;
I posted code to add two buttons to the right of the navigationBar. You can set barStyle = -1 instead of subclassing UIToolbar.
To get rid of the background ('seam') of a UIToolbar, create a subclass of UIToolbar and override the (void)drawRect:(CGRect)rect method. Leave that blank and your UIToolbar will no longer have a background.
Just used this in my own project and worked great. Found this in the comments of: http://osmorphis.blogspot.com/2009/05/multiple-buttons-on-navigation-bar.html
UIView *parentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, myWidth, myHeight)];
// make UIView customView1... (UILabel, UIButton, etc.) with desired frame and settings
[parentView addSubview:customView1];
[customView1 release];
// make UIView customView2... (UILabel, UIButton, etc.) with desired frame and settings
[parentView addSubview:customView2];
[customView2 release];
UIBarButtonItem *customBarButtomItem = [[UIBarButtonItem alloc] initWithCustomView:parentView];
[parentView release];
self.navigationItem.rightBarButtonItem = customBarButtomItem;
[customBarButtomItem release];
see uicatalogue example available at apple's site for free...they used uisegmented control to show three buttons in place of right bar button on navigaion bar...
I can't comment but in addition to #iworkinprogress I had to set the UIToolbar background color to clear:
[toolbar setBackgroundColor:[UIColor clearColor]];
This was also found in the comments of http://osmorphis.blogspot.com/2009/05/multiple-buttons-on-navigation-bar.html.
In iOS 4.x the clearColor seems to have no effect on the UIToolbar, whereas overriding its drawRect: did.
I came up with a helper function I'm using all over my project. Basically it checks if there is already a button on the bar and either add the new one or merge it with existing buttons. So you can call the function just once or multiple times:
+ (void)AddButtonToBar:(UIViewController *)controller withImage:(NSString *)imageName withAction:(SEL)action withFrame:(CGRect) frame{
UIButton *newButton =[[UIButton alloc] init];
[newButton setBackgroundImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
newButton.frame = frame;
[newButton addTarget:controller action:action forControlEvents:UIControlEventTouchUpInside];
if ([[controller.navigationItem rightBarButtonItems] count] == 0)
[controller.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:newButton]];
else {
NSMutableArray *existingButtons = [[NSMutableArray alloc] initWithArray:[controller.navigationItem rightBarButtonItems]];
[existingButtons addObject:[[UIBarButtonItem alloc] initWithCustomView:newButton]];
[controller.navigationItem setRightBarButtonItems:(NSArray *)existingButtons];
}
}
Call it from the view controller:
[Helper AddButtonToBar:self withImage:#"imageName.png" withAction:#selector(myAction) withFrame:CGRectMake(0, 0, 24, 24)];