How to customize the UISegmentedControl in iOS? - iphone

I am customizing the UISegmentedControl, but I got a problem.
How to apply background image in the UISegmentedControl ? Changing the tint color does not fulfill my requirements.
Thanks

////Segmented Controll
NSArray *segmentTextContent = [NSArray arrayWithObjects: #"First",#"Second",#"Third",#"Forth", nil];
segmentedControl = [[UISegmentedControl alloc] initWithItems:segmentTextContent];
segmentedControl.frame = CGRectMake(2, 5, 316, 35);
[segmentedControl addTarget:self action:#selector(segmentAction) forControlEvents:UIControlEventValueChanged];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.enabled = true;
segmentedControl.selectedSegmentIndex = 0;
// cutomize the font size inside segmentedControl
for (id segment in [segmentedControl subviews])
{
for (id label in [segment subviews])
{
if ([label isKindOfClass:[UILabel class]])
{
[label setTextAlignment:UITextAlignmentCenter];
[label setFont:[UIFont boldSystemFontOfSize:11]];
//[label setTextColor:[UIColor greenColor]];
}
}
}

You could try http://idevrecipes.com/2010/12/11/custom-segmented-controls/.

Related

Change Cancel Button BackgroundColor and Text of UISearchBar in iOS7

I have the following code that changes the background of the Cancel button in the UISearchBar.
for( UIView *subview in self.searchBar.subviews ){
if ([subview isKindOfClass:[UIButton class]]) {
[(UIButton *)subview setEnabled:YES];
[(UIButton *)subview setTitle:#"New Button Text" forState:UIControlStateNormal];
((UIButton *)subview).tintColor = [UIColor colorWithRed:4/255.0 green:119/255.0 blue:152/255.0 alpha:1.0];
}
}
The problem is that this code does not work in iOS7! What changed in the structure of the views in the UISearchBar?
Edit: Tested here and this is the new Hierarchy of the UISearchBar:
UISearchBar:
---UIView:
------UISearchBarBackground
------UISearchBarTextField
------UINavigationButton
The problem is that i cannot test if ([sub isKindOfClass:[UINavigationButton class]]). This line throws a compile error: Use of undeclared identifier: UINavigationButton
[Edited]
Try this codes.
Add in AppDelegate if you want to change all cancel button.
[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor redColor],
UITextAttributeTextColor,
[UIColor whiteColor],
UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(0, 0)],
UITextAttributeTextShadowOffset,
nil]
forState:UIControlStateNormal];
In iOS7 , we need to add objectAtIndex:0 and subviews.
The searchBar sub views hierarchy has been changed in iOS7, try the below:
in iOS7:
NSArray *searchBarSubViews = [[self.searchBar.subviews objectAtIndex:0] subviews];
iOS6 and before:
NSArray *searchBarSubViews = self.searchBar.subviews;
Solution: I created my own button. This way I can manage all the properties without having to discover what Apple did with the elements
I only have to create a UIView aux to contain the searchBar and the new Button.
self.searchBar.showsCancelButton = NO; //don`t show the original cancelButton
self.cancelSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.cancelSearchButton.frame = CGRectMake(250, 6, 60, 31);
[self.cancelSearchButton setTitle:#"Cancelar" forState:UIControlStateNormal];
[self.cancelSearchButton addTarget:self action:#selector(searchBarCancelButtonClicked) forControlEvents:UIControlEventTouchUpInside];
NSString *fontName = [[self.cancelSearchButton titleLabel] font].fontName;
[[self.cancelSearchButton titleLabel] setFont:[UIFont fontWithName:fontName size:11.0]];
UIView *aux = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
aux.backgroundColor = [UIColor colorWithRed:230/255.0 green:230/255.0 blue:230/255.0 alpha:1.0];
aux.layer.borderWidth = 1.0f;
aux.layer.borderColor = [UIColor lightGrayColor].CGColor;
aux.layer.cornerRadius = 0.0f;
[aux addSubview:self.searchBar];
[aux addSubview:self.cancelSearchButton];
- (void)searchBarCancelButtonClicked{
//do whatever I want to do here
}
You can take advantage of the iOS Runtime Property _cancelButton to achieve this.
UIButton *cancelButton = [self.searchBar valueForKey:#"_cancelButton"];
[cancelButton setTitleColor:[UIColor yourColor] forState:UIControlStateNormal];
For changing text
[self.searchBar setValue:#"customString" forKey:#"_cancelButtonText"];

UIToolbar as right button in a UINavigationbar, contain 2 buttons without spaced between them

I wanted to make my right bar button contain 2 buttons. So I did that by using a UIToolbar. But the problem is that the 2 buttons sit apart from each other, while the affect I would like to achieve is too have them sitting flush against each other.
Here is an image of how they look now
Here is the code I use to achieve the buttons so far
UIToolbar *tools = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0f, 2.0f, 120.0f, 40.01f)]; // 44.01 shifts it up 1px for some reason
tools.clearsContextBeforeDrawing = NO;
tools.clipsToBounds = YES;
tools.tintColor = [UIColor blueColor];
tools.barStyle = -1;// -1; // clear background
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:2];
UIButton * upButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
upButton.frame = CGRectMake(0, 07, 46, 30);
upButton.titleLabel.font = [UIFont fontWithName:#"Arial-BoldMT" size:16];
[upButton setTitle:#"" forState:UIControlStateNormal];
upButton.backgroundColor = [UIColor clearColor];
[upButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
[upButton addTarget:self action:#selector(pageDown) forControlEvents:UIControlEventTouchUpInside];
[upButton setBackgroundImage:[UIImage imageNamed:#"page_up.png"] forState:UIControlStateNormal];
[upButton setBackgroundImage:[UIImage imageNamed:#"page_up_action.png"] forState:UIControlStateSelected];
UIBarButtonItem *toggleSegmentedControlBarItemOne = [[UIBarButtonItem alloc] initWithCustomView:upButton];
[buttons addObject:toggleSegmentedControlBarItemOne];
UIButton * downButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
downButton.frame = CGRectMake(0, 07, 46, 30);
downButton.titleLabel.font = [UIFont fontWithName:#"Arial-BoldMT" size:16];
[downButton setTitle:#"" forState:UIControlStateNormal];
downButton.backgroundColor = [UIColor clearColor];
[downButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
[downButton addTarget:self action:#selector(pageUp) forControlEvents:UIControlEventTouchUpInside];
[downButton setBackgroundImage:[UIImage imageNamed:#"page_down.png"] forState:UIControlStateNormal];
[downButton setBackgroundImage:[UIImage imageNamed:#"page_down_action.png"] forState:UIControlStateSelected];
UIBarButtonItem *toggleSegmentedControlBarItemTwo = [[UIBarButtonItem alloc] initWithCustomView:downButton];
[buttons addObject:toggleSegmentedControlBarItemTwo];
[tools setItems:buttons animated:NO];
[buttons release];
UIBarButtonItem *twoButtons = [[UIBarButtonItem alloc] initWithCustomView:tools];
[tools release];
self.navigationItem.rightBarButtonItem = twoButtons;
[twoButtons release];
Can anybody please advise me how to get those two buttons to sit beside each other without any gap?
Many Thanks,
-Code
You can add UISegmentedControl as customView to your navigationItem and set its momentary property to true, that way you will get exactly what you want.
Here is sample code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = #"Test";
UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 90, 30)];
segControl.momentary = YES;
segControl.segmentedControlStyle = UISegmentedControlStyleBar;
segControl.tintColor = [UIColor darkGrayColor];
[segControl insertSegmentWithImage:[UIImage imageNamed:#"up.png"] atIndex:0 animated:NO];
[segControl insertSegmentWithImage:[UIImage imageNamed:#"down.png"] atIndex:1 animated:NO];
[segControl addTarget:self action:#selector(segButtonDown:) forControlEvents:UIControlEventValueChanged];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:segControl];
}
- (void)segButtonDown:(id)sender {
UISegmentedControl *segControl = (UISegmentedControl *)sender;
switch (segControl.selectedSegmentIndex) {
case 0:
NSLog(#"Up");
break;
case 1:
NSLog(#"Down");
default:
break;
}
}
And here is image how it looks like.
And here you can see events in console.
2012-11-25 16:03:47.805 test2[13886:c07] Up
2012-11-25 16:03:48.367 test2[13886:c07] Down
2012-11-25 16:03:48.930 test2[13886:c07] Up
2012-11-25 16:03:49.538 test2[13886:c07] Down
take a look at this tutorial, maybe it helps :
Xcode: Multiple Buttons in Nav Bar
Add a no space space between two buttons.
two do this.
UIBarButtonItem *noSpace = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil] autorelease];
noSpace.width = -10.0;
insert this noSpace objet to you'r array (buttons in your case). between two objects of UIBarButtonItem.
it'l be ok..

How to add an image & a system bar button item to a UISegmentedControl?

I have an UISegmentedControl as the navigation bar's right bar button item. This is achieved by the following code...
UISegmentedControl *segmentedControl = [ [UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Segment1",#"Segment2",nil]];
[segmentedControl addTarget:self action:#selector(segmentClicked) forControlEvents:UIControlEventValueChanged]; //Where segmentClicked is the method for segment click action
segmentedControl.frame = CGRectMake(0, 0, 90, 35);
UIBarButtonItem *rightBaritem = [ [UIBarButtonItem alloc] initWithCustomView:segmentedControl];
[segmentedControl release];
self.navigationItem.rightBarButtonItem = rightBaritem;
[rightBaritem release];
The above code fine and it will show a segmented Control with two segments "Segment1" & "Segment2".
But I want to show an image instead of Segment1 & a system bar button (Say UIBarButtonSystemItemAdd) instead of Segment2.
Image can be inserted in Segmented control by the code,
UISegmentedControl *segmentedControl = [ [UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:[UIImage imageNamed:#"<image_name.image_type>"],???????,nil]];
But i dont know how to include UIBarButtonSystemItemAdd in the place of ???????.
Thanks in Advance..
This code may solve your problem.This solved my problem that I was facing at the same time.But don't think this is the accurate one.I got the desired which I need to display.This works fine with two buttons.
UISegmentedControl *doneButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Done"]];
doneButton.momentary = YES;
doneButton.frame = CGRectMake(240, 7.0f, 70.0f, 30.0f);
doneButton.tintColor = [UIColor blackColor];
[doneButton addTarget:self action:#selector(Done:) forControlEvents:UIControlEventValueChanged];
[menustyle addSubview:doneButton];
[doneButton release];
doneButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Close"]];
doneButton.momentary = YES;
doneButton.frame = CGRectMake(10, 7.0f, 70.0f, 30.0f);
doneButton.tintColor = [UIColor blackColor];
[doneButton addTarget:self action:#selector(Krishna:) forControlEvents:UIControlEventValueChanged];
[menustyle addSubview:doneButton];
[doneButton release];

UISegmentControl configuration

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 75, 25)];
label.textAlignment = UITextAlignmentRight;
label.tag = kLabelTag;
label.font = [UIFont boldSystemFontOfSize:14];
label.text = #"Lawn Sign";
[cell.contentView addSubview:label];
[label release];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:nil];
NSArray * item = [ NSArray arrayWithObjects:#"No",#"Install",#"Replace",#"Move", nil];
[segmentedControl initWithItems:item];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.frame = CGRectMake(90, 10, 200, 30);
[segmentedControl setMomentary:YES];
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
segmentedControl.tag = 14;
[cell.contentView addSubview:segmentedControl];
[segmentedControl release];
Here's my UISegmentedControl configuration for a cell in the tableview but when I tap on an option in the segmentedControl, it doesn't switch.
You've set the control to be momentary. Change this:
[segmentedControl setMomentary:YES];
to this:
[segmentedControl setMomentary:NO];
and the control will show its selected state.

How to differentiate selected, non selected section on segmented controller

I have used the following code to create a segmented controller, but I can't differentiate which is selected and which is not selected. How do I differentiate?
UISegmentedControl *segmentedControl;
segmentedControl = [[UISegmentedControl alloc] initWithItems:nil];
[segmentedControl insertSegmentWithTitle:#"Male" atIndex:0 animated:YES];
[segmentedControl insertSegmentWithTitle:#"Female" atIndex:1 animated:YES];
segmentedControl.segmentedControlStyle = UISegmentedControlStylePlain;
segmentedControl.frame = CGRectMake(100,10,200,30);
[segmentedControl setMomentary:YES];
[segmentedControl addTarget:self action:#selector(segmentSwitch:) forControlEvents:UIControlEventValueChanged];
- (void)segmentSwitch:(id)sender
{
segmentedControl = (UISegmentedControl *) sender;
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
UIView *firstView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, 20,20)];
firstView.backgroundColor=[UIColor greenColor];
UIView *secondView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, 20,20)];
firstView.backgroundColor=[UIColor brownColor];
if (selectedSegment == 0)
{
NSLog(#"first segment");
//toggle the correct view to be visible
strGender =[[NSMutableString alloc]initWithString:#"Male"];
[firstView setHidden:NO];
[secondView setHidden:YES];
}
else
{
NSLog(#"second segment");
//toggle the correct view to be visible
strGender =[[NSMutableString alloc]initWithString:#"Female"];
[firstView setHidden:YES];
[secondView setHidden:NO];
}
}
There are a few things here. Based on your comment to #Surjit's answer, you will have to use insertSegmentWithImage:atIndex:animated if you want to change the color of the segment. You will need to have images for each segment for both selected and non-selected state.
But there are few problems in your segmentSwitch: method. You are creating both firstView and secondView but not adding them to the view hierarchy. You are setting the background color of firstView twice. You probably intended one of the calls to be to secondView. And there's no point changing the hidden property of the two views without them being on the screen. If you are looking to switch between two views of different colors, then declare them as ivars and initialize them elsewhere and then switch their hidden on segment switch.
UISegmentedControl *segmentedControl;
segmentedControl = [[UISegmentedControl alloc] initWithItems:nil];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBezeled;
segmentedControl.frame = CGRectMake(0, 6, 320, 40);
segmentedControl.selectedSegmentIndex = 0;
segmentedControl.tintColor = [UIColor blackColor];
segmentedControl.backgroundColor = [UIColor blackColor];
[segmentedControl setMomentary:YES];
[segmentedControl addTarget:self action:#selector(segmentSwitch:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:segmentedControl];
// here is the code how to differenciate selected , non selected section on segmented //controller
int selectedSegment = segmentedControl.selectedSegmentIndex;
if(selectedSegment == 0)
{
// code 1
}
else if(selectedSegment == 1)
{
// code 2
}enter code here
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
UISegmentedControl *segmentedControl; // add this to your (.h) file
segmentedControl = [[UISegmentedControl alloc] initWithItems:nil];
[segmentedControl insertSegmentWithTitle:#"Red" atIndex:0 animated:YES];
[segmentedControl insertSegmentWithTitle:#"Green" atIndex:1 animated:YES];
[segmentedControl insertSegmentWithTitle:#"Blue" atIndex:2 animated:YES];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBezeled;
segmentedControl.frame = CGRectMake(0, 0, 320, 40);
segmentedControl.selectedSegmentIndex = 0;
segmentedControl.tintColor = [UIColor blackColor];
segmentedControl.backgroundColor = [UIColor blackColor];
[segmentedControl setMomentary:NO]; // imp property (change it & see magic)
[segmentedControl addTarget:self action:#selector(segmentSwitch:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:segmentedControl];
}
(IBAction)segmentSwitch:(id)sender {
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
if (selectedSegment == 0)
self.view.backgroundColor = [UIColor blueColor];
else if (selectedSegment == 1)
self.view.backgroundColor = [UIColor greenColor];
else if (selectedSegment == 2)
self.view.backgroundColor = [UIColor redColor];
}
Just copy & paste this code.
see this example here i am setting tint color for selected
and unselected segment index.
But before that please unchecked the momentary state from xib
for UISegmentedControl.
- (void)segmentAction:(id)sender{
UIColor *tintcolor1=[UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1.0];
UIColor *tintcolor2=[UIColor colorWithRed:211/255.0 green:78/255.0 blue:65/255.0 alpha:1.0];
for (int i=0; i<[segment_controller.subviews count]; i++)
{
if ([[segment_controller.subviews objectAtIndex:i]isSelected] )
{
[[segment_controller.subviews objectAtIndex:i] setTintColor:tintcolor2];
}else
{
[[segment_controller.subviews objectAtIndex:i] setTintColor:tintcolor1];
}
}