I've set a global tintColor in my app by calling:
UIView.appearance().tintColor = myColor
However, the same color applies to the UIImagePickerController and only some of the UI elements are colored: For example, the sun icon has a custom tintColor while the focus frame has the default one.
How is it possible not to apply a global appearance configuration to the UIImagePickerController
?
My proposed solution doesn't fully address the issue, since the inputAccessoryView still has its own tintColor:
window?.tintColor = myColor
Update:
I configure the application-wide tintcolor on launch:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
configureWindowAndInitialViewController()
UIView.appearance().tintColor = .cyan // Setting a global tintColor
return true
}
Then, I show an UIImagePickerController:
func presentPhotoPicker(sourceType: UIImagePickerController.SourceType) {
if let mediaTypes = UIImagePickerController.availableMediaTypes(for: sourceType)?
.filter({$0 == kUTTypeImage as String}),
!mediaTypes.isEmpty {
let picker = UIImagePickerController()
picker.delegate = self
picker.mediaTypes = mediaTypes
picker.sourceType = sourceType
picker.allowsEditing = true
controller?.present(picker, animated: true, completion: nil)
}
}
Input accessory view:
To add an input accessory view, first of all, a textField should be created. Then it is possible to just attach a toolbar to the Textfield:
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: sefl.view, action: #selector(UIView.endEditing))
items.append(contentsOf: [spacer, doneButton])
toolbar.setItems(items, animated: false)
textField.inputAccessoryView = toolbar
After you change window?.tintColor
, inputAccessoryView.tintColor
isn't changed because inputAccessoryView
isn't a subview of current window (they don't have same view’s hierarchy) so window.tintColor
won't affect inputAccessoryView
.
To resolve problem, I suggest to use NotificationCenter
to observe and change window.tintColor
each time a new UIWindow
becomes visible. You can put the code inside AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
NotificationCenter.default.addObserver(self, selector: #selector(self.windowDidBecomeVisible), name: .UIWindowDidBecomeVisible, object: nil)
return true
}
@objc func windowDidBecomeVisible(notification: NSNotification) {
// Each time an `UIWindow` becomes visible, change its |tintColor|
let visibleWindow = notification.object as! UIWindow
visibleWindow.tintColor = .red
}
If you want to change tintColor
only for the UIImagePickerController
, you need to change tintColor
for every view which is displayed on UIImagePickerController
.
Define an extension to change all subview's tintColor
.
extension UIView {
func changeTintColor(color: UIColor) -> Void {
for view in subviews{
view.tintColor = color
view.changeTintColor(color: color);
}
}
}
Use UINavigationControllerDelegate
to get UIViewController
which is displayed on UIImagePickerView
. Change view's tintColor
inside this controller
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.view.changeTintColor(color: .red)
}
Don't forget to set UIImagePickerController
's delegate
to self
.