Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - Prevent UIAppearance settings from changing UIWebView input accessory view

I have a UIWebView in my app, and the problem is that I have a UIAppearance that modifies the appearance of segmented controls, so it modifies the segmented control in the input accessory view for UIWebView textfields, I'd like for it to look properly, or to not attempt to modify it. This is what it currently looks like:

enter image description here

like image 367
8vius Avatar asked Jun 26 '12 19:06

8vius


2 Answers

I just solved this problem for myself by using [UIAppearance appearanceWhenContainedIn:] instead of [UIAppearance appearance].

Use it by sending the selector a nil-terminated list of all your custom ViewController classes that contain the elements you want to customize. So instead of

[[UISegmentedControl appearance] setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

use

[[UISegmentedControl appearanceWhenContainedIn:[MyViewController class], [MyOtherViewController class], nil] setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

You don't need to list all the ViewControllers, just your top-level ones. This also makes the following trick possible: Create an 'empty' subclass CustomizedViewController of UIViewController that does nothing else than being a subclass - and then subclass from there throughout your code instead from UIViewController (basically replace all occurences of 'UIViewController' with 'CustomizedViewController' - except where CustomizedViewController actually declared UIViewController as its superclass.

Then use

[[UISegmentedControl appearanceWhenContainedIn:[CustomizedViewController class], nil] setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
like image 182
Stefan Avatar answered Apr 20 '23 00:04

Stefan


Ok, so I was finally able to figure out a workaround for this. See my comment on the current answer that explains why that answer doesn't work for me.

To re-iterate, from what I can tell the iOS code that is creating the keyboard accessory is explicitly setting the UIToolbar background, so you won't get your UIAppearance background setting, but you will get your UIBarButtonItem styling. The result is a half-styled view, which can look pretty bad. Fortunately, my designer was fine with falling back to default styling for this particular case.

So, the trick was really to figure out how to get that view to NOT get styled via UIAppearance. The way I did this was to replace this:

id barButtonAppearanceProxy = [UIBarButtonItem appearance];

With this:

// wtf: Style any UIBarButtonItem associated with a UIViewController
id barButtonAppearanceProxy = [UIBarButtonItem appearanceWhenContainedIn:[UIViewController class], nil];

This seemed weird to me at first because I was thinking of containment in terms of a view-heirarchy... But, this is just saying that we'll only style UIBarButtonItems that are associated with UIViewController's. The reason why this doesn't effect the keyboard accessory is because it's added directly the parent view's window and is not associated with a UIViewController.

This is still not a perfect solution in that ideally we would just style the keyboard accessory with UIAppearance. Also, it assumes that all of your toolbars are associated with UIViewControllers. Fortunately for me (and probably most of you) this is typically the case.

like image 25
tyler Avatar answered Apr 20 '23 01:04

tyler