J'ai un UIView
et je lui ai défini un shadowPath
comme ceci:
func addShadow() { let cornerRadius: CGFloat = self.containerView.frame.height/2 self.containerView.layer.shadowPath = UIBezierPath(roundedRect: self.containerView.frame, cornerRadius: cornerRadius).cgPath self.containerView.layer.shadowRadius = cornerRadius self.containerView.layer.shadowOffset = .zero self.containerView.layer.shadowOpacity = 0.2 self.containerView.layer.cornerRadius = cornerRadius self.containerView.layer.shadowColor = UIColor(named: "whiteColor")?.cgColor }
Et voici whiteColor :
Et maintenant mon problème est
Lorsque je change l'apparence du téléphone, la couleur du
shadowPath
ne change pas automatiquement. Que dois-je faire pour rendre la couleur dynamique?
3 Réponses :
Toutes les propriétés des calques ne réagissent pas automatiquement aux changements de couleur (en raison de la conversion en CGColor
).
À la place, réagissez aux changements de collection de traits et redéfinissez les propriétés lorsque la couleur apparaît changements:
override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if #available(iOS 13, *), self.traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { // re-set your properties here } }
Ensuite, je devrais remplacer cette méthode dans chaque ViewController
?! J'ai besoin d'une solution plus générique!
Seulement avez-vous défini les propriétés du calque. Mais oui, c'est une douleur. J'ai créé un BaseView
qui fournit des propriétés UIColor
pour toutes ces propriétés de calque et gère les changements d'apparence. Mais maintenant, je me suis retrouvé avec 4 BaseView
différents pour les boutons, les cellules de vue de tableau, etc ... 🙄
Veuillez appeler super.traitCollectionDidChange
ajouter
self.view.layoutIfNeeded ()
dans votre fonction, cela pourrait résoudre votre problème. De manière alternative, vous ajouterez de la couleur dans viewDidLayoutSubviews
.
self.view.layoutIfNeeded ()
n'a pas fonctionné, et je pense que remplacer viewDidLayoutSubViews
n'est pas le meilleur! car je devrais remplacer cette méthode dans chaque ViewController! J'ai besoin d'une solution plus générique!
La meilleure solution générique à laquelle je puisse penser est de créer une classe de vue de base qui gère les changements de trait et qui en dérive pour toutes les vues qui en ont besoin.
Pouvez-vous l'exécuter dans le fil principal? ça pourrait être du travail. Je veux dire en utilisant - func addShadow () {DispatchQueue.main.async {// votre code ici}}
@NahidRaihan rien ne s'est passé!
1. d'où avez-vous appelé cette fonction? 2. Ajoutez la ligne de départ self.view.layoutIfNeeded () dans la méthode et ajoutez à nouveau avant de terminer.
ajoutez-le dans viewWillAppear ()
s'il vous plaît.
C'est donc ce qui a fonctionné pour moi - c'est un mélange entre la réponse de Frank Schlegel et celle de Kurt Revis réponse à la question cgColor
override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { if #available(iOS 13, *), self.traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { SubmissionOptionsMenu.layer.shadowColor = UIColor.label.resolvedColor(with: self.traitCollection).cgColor } }
Faites tout votre travail de couleur dans layoutSubview ou viewDidLayoutSubviews. Ensuite, vous définissez la couleur sur une variable dynamique qui calculera sa valeur en fonction du traitCollection.userInterfaceStyle
@andromedainiative Êtes-vous sûr que c'est le meilleur moyen? J'ai de nombreuses vues qui ont une ombre, est-il juste de les définir toutes dans
layoutSubView
?Je veux dire qu'il n'y a pas de solution générique miracle à ma connaissance. Nous avons fini par déplacer toute notre configuration de couleur de ces méthodes. Vous pouvez en savoir plus ici. À moins que vous n'utilisiez le même contrôleur de vue dans chaque vue que vous avez, vous devrez mettre à jour manuellement les couleurs. developer.apple.com/documentation/appkit/…
@andromedainiative beau document merci