Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing UISegmentedControl in iOS 5

Here is my problem. I am customizing a UISegmentedControl by setting the background and divider images in the following way:

[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected forLeftSegmentState:UIControlStateSelected rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segUnselectedSelected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateSelected barMetrics:UIBarMetricsDefault];

[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];

When I try to make the 1st segmented selected within viewDidLoad

self.segmentedControl.selectedIndex = 1;

I get the following weird thing:

enter image description here

instead of:

enter image description here

Does anyone know if this is a bug and how could I provide a bug report? If not, what could be wrong with my code?

like image 584
nimeshdesai Avatar asked Feb 02 '12 14:02

nimeshdesai


4 Answers

After doing some tests and trying several different locations for the customization, I believe this may indeed be a bug.

Even with a very simple straight UISegmentedControl, this is what I get (using Xcode 4.3.1, iOS 5.1):

After launching and selecting the middle element in code: After launching and selecting the middle element in code

After user-clicked away and clicking back on middle element: After user-clicked away and clicking back on middle element

I used 3px wide images for the separators and 1px wide images for the backgrounds.

Edit: I think I found a workaround: try queueing the instruction to select the element, rather than executing it in viewDidLoad, like this:

dispatch_async(dispatch_get_main_queue(),^{
   self.segmentedControl.selectedSegmentIndex = 1;
});

On my example above, queuing that instruction makes it work just fine.

like image 186
Fernando Madruga Avatar answered Nov 14 '22 10:11

Fernando Madruga


I think your image CapInsets is incorrect, please double the example in http://www.raywenderlich.com/4344/user-interface-customization-in-ios-5

here is some codes from the Tutorial for quick reference:

UIImage *segmentSelected = [[UIImage imageNamed:@"segcontrol_sel.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentUnselected = [[UIImage imageNamed:@"segcontrol_uns.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentSelectedUnselected = [UIImage imageNamed:@"segcontrol_sel-uns.png"];
UIImage *segUnselectedSelected = [UIImage imageNamed:@"segcontrol_uns-sel.png"];
UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.png"];

[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected forLeftSegmentState:UIControlStateSelected rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segUnselectedSelected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
like image 42
flypig Avatar answered Nov 14 '22 10:11

flypig


I figured out how to solve the problem after I did a lot of experiments.

Your problem is from the incorrect width setting for the segments.

First point - we need to do UI customization before setting the width of individual segments.

Second point - we need to count the width of the divider(s) and it is very important. When we do customization, the divider(s) is part of the UISegmentedControl elements. The divider is not an overlay. We should count the width of the divider also.

Third point - when we use the set width method for the segments, the segment width does not need to include the divider's width.

If you follow the above rules, you would get a perfect customized UISegmentedControl.

like image 37
user403015 Avatar answered Nov 14 '22 10:11

user403015


Have you tried to set resizable images?

For example:

UIImage *segmentSelected = [[UIImage imageNamed:@"SegmentSelectedImage"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
like image 1
Julien Avatar answered Nov 14 '22 09:11

Julien