15

Is it possible to have a segmented control on an iOS 7 device show up as the iOS 6 version of the control?

We really aren't ready for an interface redesign and the new flat control doesn't jive with the rest of our UI. It would definitely be best to keep the iOS 6 style for now, if possible.

To clarify, I am compiling using the iOS 6.1 Base SDK. I am aware that this is the "obvious" answer to my question, but it does not work. Most other UI elements will show up with iOS 6 styling by doing this, but like the UIAlertView and UIActionSheet, the UISegmentedControl does not. However, unlike the UIAlertView and UIActionSheet, UISegmentedControls do not feel like a "system" item; they should be able to display in iOS 6 mode.

Edit: I thought it would be helpful if I finally included a picture with this (probably should have done this from the start). However, the answer I provided did fix the issue. Also, in retrospect, it looks like this might be the iOS 6 style after all, it's just displaying so wrong that it appears like iOS 7 style.

enter image description here

KlimczakM
  • 11,178
  • 10
  • 55
  • 76
MikeS
  • 3,853
  • 6
  • 31
  • 50
  • Can't you just compile with iOS 6 SDK? – David Rönnqvist Sep 19 '13 at 16:21
  • 2
    You would think so, but that doesn't work... This DOES fix other iOS 7 UI type issues, but not the segmented control. No idea why it doesn't work. – MikeS Sep 19 '13 at 16:21
  • Sounds like a bug. You should get the iOS 6 appearance on almost everything—alert views are one exception, but segmented controls shouldn’t be. http://bugreport.apple.com – Noah Witherspoon Sep 19 '13 at 16:22
  • You could be right. I'll go ahead and report it as a bug. It definitely seems like a UI element that should retain its iOS 6 style. – MikeS Sep 19 '13 at 16:24

9 Answers9

20

I manage to do a pretty good job of solving this problem by setting all the attributes manually, but it is not quite perfect.

This is what I ended up doing:

- (void)fixSegmentedControlForiOS7
{
    NSInteger deviceVersion = [[UIDevice currentDevice] systemVersion].integerValue;
    if(deviceVersion < 7) // If this is not an iOS 7 device, we do not need to perform these customizations.
        return;

    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                [UIFont boldSystemFontOfSize:12], UITextAttributeFont,
                                [UIColor whiteColor], UITextAttributeTextColor,
                                nil];
    [self.segmentedControl setTitleTextAttributes:attributes forState:UIControlStateNormal];
    NSDictionary *highlightedAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:UITextAttributeTextColor];
    [self.segmentedControl setTitleTextAttributes:highlightedAttributes forState:UIControlStateHighlighted];

    self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
    self.segmentedControl.tintColor = [UIColor colorWithRed:49.0 / 256.0 green:148.0 / 256.0 blue:208.0 / 256.0 alpha:1];
}
MikeS
  • 3,853
  • 6
  • 31
  • 50
  • That is officially brilliant. My segmented controller looks just like iOS6 now. – Ben Clayton Sep 24 '13 at 09:48
  • Haha thanks. I updated my original post to include a picture of the problem I was having just for reference.... – MikeS Sep 24 '13 at 16:13
  • 1
    Was looking for this the other day and couldn't get it to work. Found this today and "wham bam thank you ma'am". It works like a charm. – Totumus Maximus Sep 26 '13 at 08:36
  • This is a workaround for the attributes disappearing with certain 6.x SDKs. On SDK 7, all that happens is that the blue is a slightly different shade. – Henrik Erlandsson Dec 12 '13 at 07:37
  • That (although nice) does not fix the problem! You just get a (better) segmentedControl, but nothing like the (beautiful) iOS6 segmentedControl with its nice grey and blue images. At least is there a way to change the -not selected- segments background to another color (like the grey of iOS6)? – Gik Apr 11 '14 at 09:49
  • Thanks, was able to play with the text attributes and color settings using this approach to get something I like, although I do have a couple of comments ... – GRW Jan 30 '15 at 07:01
  • I found that UIControlStateSelected gave me what I wanted instead of UIControlStateHighlighted. In fact I didn't even notice what the Highlighted state was. The two states I see are Normal and Selected. – GRW Jan 30 '15 at 07:04
  • backgroundColor and tintColor allowed me to set the colors for both the Normal and Selected states, although the tint for iOS 6 didn't seem to do anything. And I believe your UIColor should divide by 255, not 256. Color values go from 0 to 1, and in order to get a 1.0 with an 8 bit value, divide by 255. – GRW Jan 30 '15 at 07:11
  • Also improved the display if I included a border. self.segmentedControl.layer.borderColor = [UIColor blackColor].CGColor; self.segmentedControl.layer.borderWidth = 0.5f; self.segmentedControl.layer.cornerRadius = 4.0f; – GRW Jan 30 '15 at 07:15
13

To fix images assigned with InterfaceBuilder use this code:

- (void)fixImagesOfSegmentedControlForiOS7
{
    NSInteger deviceVersion = [[UIDevice currentDevice] systemVersion].integerValue;
    if(deviceVersion < 7) // If this is not an iOS 7 device, we do not need to perform these customizations.
        return;

    for(int i=0;i<toSegmentedControl.numberOfSegments;i++)
    {
        UIImage* img = [toSegmentedControl imageForSegmentAtIndex:i];
        UIImage* goodImg = [img imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        // clone image with different rendering mode
        [toSegmentedControl setImage:goodImg forSegmentAtIndex:i];
    }
}
cat
  • 2,721
  • 1
  • 21
  • 28
  • 1
    Nice fix... works like a charm. Also used this to change the size of our segmented control – MobileVet Oct 07 '13 at 21:31
  • Could you please share your code how you achieved to resize the segment control? When I try this in `- (void)viewDidLoad` nothing changes. I tried to do it also in `initWithNibName` without any luck. – Houman Oct 08 '13 at 18:09
  • The new segmented control has a reduced height. I did not fix the height, though this might be possible. As a permanent fix I replaced the control completely with bootstrap buttons http://github.com/katzlbt/iOSBootstrapButton – cat Oct 22 '13 at 10:33
  • This just removes the text labels on XCode 5/SDK 7. – Henrik Erlandsson Dec 12 '13 at 07:42
5

I just ran into this problem today myself. The app I'm working on updating is quite old, and still uses xib files, so I do not know if this works on storyboards or not. As others suggested above, you still need to use the iOS 6.1 SDK, but this alone is not enough. After performing the following steps, I was able to get the old UISegmentedControl appearance back:

  1. Open the interface builder document in question
  2. Go to the file inspector (first inspector tab; has a document icon)
  3. Under the "Interface Builder Document" section, change "Opens in" to Xcode 4.6

I do believe this is a bug, and I would not be surprised if there isn't a workaround for UISegmentedControl instances created in code. I'm guessing this is somewhat related to the deprecation of the segmentedControlStyle property in iOS 7 (see https://developer.apple.com/library/ios/documentation/uikit/reference/UISegmentedControl_Class/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/occ/instp/UISegmentedControl/segmentedControlStyle).

Hope this helps someone out there.

ianthetechie
  • 555
  • 6
  • 11
2

If you save the iPhoneOS6.1.sdk file from the previous version of XCode and add it to Xcode 5 in the same path you can then build an app against the 6.1 SDK so that when it runs on 7 everything is like 6. Linking against iOS7 SDK tells iOS to make everything look like iOS7 if possible. Essentially then you have an iOS6 app but building it with XCode 5.

ahwulf
  • 2,564
  • 12
  • 27
2

If you use images on any of your UISegmentedControl segments, you'll need to add some code to set those properly on iOS 7, otherwise they'll be used as a template image and the selected segment will be a cutout of the segment's background.

UISegmentedControl under iOS 7 interprets its images as being in rendering mode UIImageRenderingModeAlwaysTemplate unless otherwise specified. I had to use -[UIImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] on each segment's image for iOS 7 to achieve the previous behavior.

Ryan
  • 358
  • 2
  • 8
0

Either you could:

  • Not update your app at all for iOS7 until you're ready to make some UI changes. Apps compiled against the iOS6 SDK will run in iOS6 Compatibility mode on iOS7 and will look exactly the same as they did in iOS6.
  • Apply custom background, separator, etc images to your segmented controls that mimic the look they had in iOS6.
Jonathan Arbogast
  • 9,530
  • 4
  • 31
  • 47
  • 3
    See the comments on the question—apparently the segmented control is an exception to the compatibility-mode thing. Custom images might be the only solution for now. – Noah Witherspoon Sep 19 '13 at 16:25
  • Yes, I am compiling for iOS 6, but for whatever reason, the UISegmentedControl still shows up in iOS 7 styling. – MikeS Sep 19 '13 at 16:31
0

Yes, it is possible if you recreate the control by your own. Create a fake segmented control that looks like and work like one.

Duck
  • 32,792
  • 46
  • 221
  • 426
0

In my app, I have set the Segmented control to "Bar" style. It renders in ios6 style on my ios7 iphone5 (whoa, 5,6,7). However, the text inside the segments are cut and have the three dots "..." added, no matter how wide the view is. So the ios6 segmented control rendering in ios7 seems really buggy

user1169629
  • 361
  • 1
  • 11
  • I think this was the issue all along: it was so buggy/discolored, I thought it was the 7 control... – MikeS Sep 23 '13 at 15:37
  • I have several "bar" segmented controls in our app, and we have the same problem - the colours are fine, but the labels are being truncated as D... for Day and L... for List even though there is plenty of width in the segment. Have tried reassigning the text each time the selection changes, but that doesn't fix it. – Bill Oct 15 '13 at 08:48
-1

Is it possible? Not really...

You could make your own custom segmented control.

Or you could use the UIAppearance proxy to customise your segmented control with images but then it's your responsibility to make it look like it was on iOS 6.

Daniel
  • 22,521
  • 12
  • 107
  • 150
  • This is just speculation then I suppose, but would you classify this as a bug or a feature? To my knowledge, all other non-system UI elements can be displayed in iOS 6 mode, where as the UISegmentedControl apparently cannot be... Seems strange. – MikeS Sep 19 '13 at 16:36
  • It's the way it is. Standard UI elements appear as they are intended by Apple on each system version. As soon as you compile your app with Xcode 5, then those system elements become either iOS 7 or 6 depending on the system they are run on. Using Xcode 4, you can compile with iOS 6 SDK and install on an iOS 7 device, then the standard UI elements will stay as they are on 6. But Apple will soon refuse apps submitted with old Xcode versions, as they always do. – Daniel Sep 19 '13 at 18:17
  • You can compile apps with iOS 6.1 Base SDK on Xcode 5 as well, however. You just have to follow these instructions: http://stackoverflow.com/questions/18423896/is-it-possible-to-install-ios-6-sdk-on-xcode-5. What I'm complaining about is that UISegmentedControl is not displaying properly on iOS 7, even when compiled with the iOS 6.1 Base SDK. However, all other UI elements display just fine. – MikeS Sep 19 '13 at 18:22
  • Maybe then put some kind of screenshot of why it's not appearing ok for you. – Daniel Sep 19 '13 at 19:34