Change look of Segmented Control in IOS 6 and 7 - ios

Our large IOS app has a bunch of Segmented controls.
The new IOS 7 B&W look - looks like crap in our app.
I can change the background color (and set the corner radius) so we have colored buttons again - BUT it then looks like crap when run on an IOS 6 phone.
For IOS 6 I have to change the Tint color and NOT change the background color.
Adding conditional code to do this for each individual control would be a royal pain. Creating a subclass to do this - and modifying all the XIB's to use it - would also be a pain.
Is there any way to modify the look of a control for the entire app? Can a class extension do this?

you have to set the apparence of the UISegmentedControl class
something like
[[UISegmentedControl appearance] setTintColor:[UIColor blueColor]];
set your layout in application didFinishLaunchingWithOptions, using the standard ugly iOS version test to set the different layouts according to the current version
API's reference:
https://developer.apple.com/library/ios/documentation/uikit/reference/UIAppearance_Protocol/Reference/Reference.html
You can find in UISegmentedControl's API the specific appearence fields
https://developer.apple.com/library/iOs/documentation/UIKit/Reference/UISegmentedControl_Class/Reference/UISegmentedControl.html#//apple_ref/doc/uid/TP40006807-CH3-SW33

Related

iOS - Override UIActivityIndicatorView's default color for the entire application

I am developing an hybrid application in javascript for iOS. And I don't have access to the underlying framework, which shows the UIActivityIndicatorView. I want to change the colour of the indicator either programmatically or setting some properties.
PS: I could do this in Android by setting themes. Hoping for a similar way, as I am new to iOS development.
You may set the colors globally via UIAppearance, e. g.:
[[UIActivityIndicatorView appearance] setColor:[UIColor red]];
or the same in Swift 4:
UIActivityIndicatorView.appearance().color = .red

setTitleTextAttributes not working after view on screen. iOS 11

I've spent a whole day trying to change the colour of a UIBarButtonItem and now i'm thinking it is an iOS 11 bug unless someone can tell me it's by design.
I can change the colour of the text by using this code
[self.refreshButton setTitleTextAttributes:#{NSForegroundColorAttributeName: [UIColor orangeColor]} forState:UIControlStateNormal];
If I add the code to the viewWillAppear:animated function it works fine, however if you add it to viewDidAppear:animated it does not work.
It seems to work on the iOS 9 simulator, but not iOS 11.
Has something changed in this regard in iOS 11?
If all you want to do is change the title color of your UIBarButtonItem you can set the tintColor property instead of setTitleTextAttributes:. If you want all of your UIBarButtonItems to have the same title color you can set the tintColor of your tool/navigation bar.
I had the same issue on iOS11 but needed to set the font by setTitleTextAttributes. Unfortunately this does also not work by appearance. The only solution I found was to create new BarButtonItems as copy of the old ones and then set them as navigationItem.rightBarButtonItems.
For reference for other users having the same issue.
This Stack Overflow answer may explain why the method doesn't work.
An improper setting of UIControlState() may be the problem.

iOS app that change whole app color theme (background, uibutton, icons color...) base on user selection

I have a requirement to make application that has color theme base on user selection
User selects an color at begining (in 8 available colors), that color will be applied for the whole app (background color, buttons, icons ....)
If I create images for each color, the app will have lots of images and can be heavy in size, and that approach not seem to be good one.
I tried to import images with 1 color and then change images color according to user-selected color, but got problem with some controls like slider, and also the image that is changed does not look good as photoshop one
Would u plz help me with good approach for this?
Make all the images one color (black probably), then let the user pick a color and save it to user defaults. Link all items that need to get the theme to the color from the user defaults. Then use the tintColor property of the UIImageView to themefy your app.
Method to tint any UIImageView:
- (void)tintImageView:(UIImageView *)imageView withTint:(UIColor *)tintColor
{
imageView.image = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[imageView setTintColor:tintColor];
}
Example use to tint Button:
[self tintImageView:self.button.imageView withTint:[UIColor blueColor]];
Example use to tint UIImageView:
[self tintImageView:self.imageView withTint:[UIColor blueColor]];
If you're using iOS7 you can take advantage of the tintColor property.
For images you need to be sure they are created using template option.
Please checkout this clear tutorial that will guide you to apply themes to different kind of controls in your app: Theming iOS Applications
You could probably be interested in trying Pixate Freestyle too, which basically allow you to apply styles like css does to your iOS app, that a pretty cool tool and I've found it very easy to use too.

Use iOS 6 Style Segmented Control in iOS 7?

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.
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];
}
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];
}
}
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:
Open the interface builder document in question
Go to the file inspector (first inspector tab; has a document icon)
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.
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.
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.
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.
Yes, it is possible if you recreate the control by your own. Create a fake segmented control that looks like and work like one.
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
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.

How to create a theme based application?

I know similar question is already asked, but didn't get a satisfactory answer. So i am adding this question again .
Based on user selection in iphone application , i need to change the look and feel of the application (color font background images etc ). Is there any standard way to achieve this ?
one possible solution can be duplicating xib files for each theme and loading it based on selection. Is this a good approach? mainly because wiring the outlets and actions for xib copies sounds to be a redundant task.
I would like to see expert suggestion for this doubt.
Thanks for any help in advance.
-mia
For the non-XIB route
Color: iOS 5 exposes the new appearance APIs. Most UI elements have the option if setting a tintColor or a backgroundColor. Rarely, even a background image.
Font: Was always able to change, but you couldn't animate it.
Background image: Your main UIView should have the option for a background image, or if that fails, a background color with a pattern image.
As CodaFI said, if you are using iOS 5 or greater, you already have a theming feature. It works like this:
Add the protocol <IAppearanceContainer> to the class.
Decorate the property you intend to change with UI_APPEARANCE_SELECTOR. Example:
#interface UINavigationBar : ... <IAppearanceContainer>
#property(nonatomic,retain) UIColor *tintColor UI_APPEARANCE_SELECTOR;
#end
Change the color for all instances of the class:
[[UINavigationBar appearance] setTintColor:[UIColor redColor]];
The example above is the UINavigationBar, but it would work with any custom class. To see the objects already supported in iOS 6.1, check the documentation or run the following commands:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/UIKit.framework/Headers
grep -H UI_APPEARANCE_SELECTOR ./* | sed 's/ __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0) UI_APPEARANCE_SELECTOR;//'
Let's say you want modular themes:
Write a big plist file with all the fonts, colors, music, and what not. Each of these files will be a theme.
Read the file through a singleton and set the values with lines like [x appearance] setWhatever:<plist value>] for each theme-able element.
If you have instances of the same element that need to display different elements, get those images through the singleton.
That is more or less the tip from Amit Vyawahare. I said plist instead xml because they are easier to read. Don't duplicate the NIBs unless you really have to.
Best way to implement theme based application IOS application (not using ~xib route). you should create a build.xml file which will content all the pieces of themes. You should keep your layout same and you can change images, style, fonts, lang, views, in that layout according to users pref. By doing this you are not duplicating any code and you will achieve best performances from your application.

Resources