iOS - Prevent UIAppearance settings from changing UIWebView input accessory view
Asked Answered
S

2

7

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

Sesquioxide answered 26/6, 2012 at 19:51 Comment(8)
I have this same problem. It's driving me nuts.Boyt
It doesn't seem to be the appearance settings for the UISegmentedControl, but the appearance for the UIToolbar, I'm not quite sure, but I can't seem to fix it without removing my appearances. Also seems like there is no easy and safe way to simply remove the toolbar from UIWebViewSesquioxide
Yeah, it seems as if the issue is that it's changing the alpha of the unselected area of the segmented controller. I wonder if it has to do with the the UIToolbar itself having transparency.Boyt
So I talked to my local chapter of Cocoaheads, and got some ideas. One of them wrote this blogpost on how to remove the accessory view bjhomer.blogspot.com/2012/03/… and others suggested using appearanceWhenContainedIn: somehow.Boyt
I've thought of the appearance when contained in, but contained in what?Sesquioxide
I'm not sure. Maybe if you can get the input accessory view somehow you can change the appearance of items when contained in it?Boyt
I've searched for that solution and there doesn't seem to be that option in the API, the inputAccessoryView doesn't seem to have any class per se.Sesquioxide
I think I'm going to try using the method explained in the blog post to remove the default input accessory view and then insert my own. Maybe if you inject some javascript you can catch when the keyboard is coming up—or maybe there's a NSNotification to listen for?— similar to how you can customize the contexual menu icab.de/blog/2010/07/11/…Boyt
M
5

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];
Millan answered 23/11, 2012 at 21:2 Comment(3)
I had lost faith of this ever getting answered, I'll give a shot later, Stefan. Thank you.Sesquioxide
Unfortunately the project I'm working on has hundreds of classes spanned across multiple teams using code that I don't have control over. The beauty of UIAppearance is that (in theory) I don't have to mess with the classes that I'm trying to skin. I can't go through every class I want to skin and give them a common superclass just to get UIAppearance to work. Perhaps if apple had included an appearanceWhenNotContainedIn method I could at least suppress styling for UIToolbars within a UIWebView...Centiare
For me it doesnt work... When I presented the view controller with web view, toolbar was with default appearance, but keyboard toolbar customizedPhellem
C
2

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.

Centiare answered 25/3, 2013 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.