I dont want my buttons on my keyboard to change colors if I globally update all buttons to have the same color. How can I control this manually to reset to the original color?
[[UIApplication sharedApplication] delegate].window.tintColor = [Helper getColor:color];
[[UIButton appearance] setBackgroundColor:[Helper getColor:color]];
AppDelegate
@interface ExposureDelegate : NSObject <UIApplicationDelegate> {
}
@property (nonatomic, strong) IBOutlet ExposureWindow *window;
@property (nonatomic, strong) EventsViewController *eventsViewController;
@end
@implementation ExposureDelegate
@synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[ExposureWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window setRootViewController:menuViewController];
NSArray *windows = [[UIApplication sharedApplication] windows];
for(ExposureWindow *w in windows) {
NSLog(@"window: %@",window.description);
if(w.rootViewController == nil){
UIViewController* vc = [[UIViewController alloc]initWithNibName:nil bundle:nil];
w.rootViewController = vc;
}
}
[self.window makeKeyAndVisible];
You can define which views/classes should respect a UIAppearance
rule using:
+ (instancetype)appearanceWhenContainedInInstancesOfClasses:(NSArray<Class<UIAppearanceContainer>> *)containerTypes;
Now there are possibly a few ways to do this, this is just one. You can skip to the end if you want your answer, but I included more information to understand why and how if curious.
Keep in mind that the array you pass is NOT a list of all the places you want the appearance proxy to work, if you pass in multiple in the same list it will be evaluated as a hierarchy where the first element is the most nested and the last element is the outermost.
AKA
[UIButton appearanceWhenContainedInInstancesOfClasses:@[[MyView class], [UITableView class]]]
means to ONLY apply the rule to buttons that are inside MyView
's that are inside UITableView
's.
Another good thing to understand is how the rules are evaluated. UIKit
will always check the longest hierarchies first. And it will always start checking on the outermost object (in most cases something like UIViewController
).
The appearance will be applied to the first hierarchy that matches.
AKA
UILabel.appearance(whenContainedInInstancesOf: [CustomView.self]).textColor = red;
UILabel.appearance(whenContainedInInstancesOf: [UIViewController.self]).textColor = UIColor.gray;
would mean that all your labels would show up gray since it starts checking on the outermost object, UIViewController
and since thats a match it stops checking further.
But because longer hierarchies are evaluated first:
UILabel.appearance(whenContainedInInstancesOf: [CustomView.self, UIViewController.self]).textColor = red;
UILabel.appearance(whenContainedInInstancesOf: [UIViewController.self]).textColor = UIColor.gray;
Means labels will show up as red on CustomView
as expected since the first line has two elements in its hierarchy, which means it will be checked before all the one element hierarchies like the second line.
So all we have to do is find a parent view or view controller somewhere in the stack of the keyboard window - and set a background color of clear on that...
Except, having inspected the full hierarchy of the keyboard window every single controller and view leading up to those buttons are private: (I checked the class hierarchy, visible on the right, of every single view starting at the UIRemoteKeyboardWindow. They are all private)
Since we can't touch the system classes that leaves us with less options - we have to set rules that only apply to the UIWindow
or UIViewControllers
of our main app window.
I can imagine a solution where I have a custom UIViewController
class called BaseController
that ALL my VC's inherit from.. but that seems annoying. Why don't we just create a custom UIWindow
class thats used in our own app instead:
(this is in Swift because it was easier for me)
// internal and final just included for compiler optimizations, not necessary
internal final class AppWindow: UIWindow {}
@UIApplicationMain
internal final class AppDelegate: UIResponder, UIApplicationDelegate {
lazy var appWindow: AppWindow = {
return AppWindow(frame: UIScreen.main.bounds)
}()
...
// then wherever you're setting the key window make sure you use your custom one
appWindow.rootViewController = vc
appWindow.makeKeyAndVisible()
Now you can just apply the rules to AppWindow
:
[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[AppWindow class]]]
setBackgroundColor:[Helper getColor:color]];
(you should be fine with the tint stuff as you have it written bc that already only affects the window being used the application)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.