- (void)drawRect:(CGRect)rect
, il suffit juste de définir [_chartView setContentMode:UIViewContentModeRedraw]
et cette méthode sera appelée lorsque l'appareil change, c'est son changement et il est possible de calculer f.e. nouveau point central pour ma carte.- (id)initWithFrame:(CGRect)frame
, puis l'ajoute dans le contrôleur de vue comme [self.view addSubview:chartView];
. Comment dans ce cas je peux gérer la rotation pour redessiner mon graphique?Pour rendre votre graphique correctement rendu lorsque l'orientation du périphérique change, vous devez mettre à jour la présentation du graphique. Voici le code que vous devez ajouter à votre contrôleur de vue:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_chartView.frame = self.view.bounds;
[_chartView strokeChart];
}
Utilisation de .Redraw
L'appel par programme myView.contentMode = .Redraw
lors de la création de la vue personnalisée devrait suffire. Il s’agit d’un indicateur unique dans IB et, en tant que tel, des lignes de code 0 préférées. Voir Stack Overflow Comment déclencher drawRect sur la sous-classe UIView .
Utilisation de setNeedsDisplay()
Si vous devez déclencher un rafraîchissement, faites-le dans setNeedsDisplay
, qui à son tour appelle drawRect
.
Pas besoin d'écouter les notifications ni de refactoriser le code.
Rapide
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
Objectif c
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
Remarque:layoutSubviews
est une méthode UIView
, pas une méthode UIViewController
.
Allez ici pour savoir comment recevoir des notifications lorsque l'orientation de l'appareil change. Lorsque l'orientation change, appelez simplement [chartView setNeedsDisplay];
pour que drawRect:
soit appelé afin de pouvoir mettre à jour votre vue. J'espère que cela t'aides!
Le code que vous allez ajouter à votre contrôleur de vue:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
Malheureusement, certaines réponses suggèrent de remplacer les méthodes du contrôleur, mais certaines personnalités UITableViewCells
avec une ombre entourant et faisant pivoter le périphérique étirent les cellules mais ne redessinent pas l'ombre. Donc, je ne veux pas mettre mon code dans un contrôleur pour (re) dessiner une sous-vue . La solution pour moi consiste à écouter une notification UIDeviceOrientationDidChange
dans ma coutume UITableViewCell
et ensuite appeler setNeedsDisplay()
comme suggéré.
Exemple de code Swift 4.0 dans l'un de mes UITableViewCells personnalisés
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChangeNotification), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
@objc func deviceOrientationDidChangeNotification(_ notification: Any) {
Logger.info("Orientation changed: \(notification)")
setNeedsLayout()
}
BTW: Logger
est une typealias
à SwiftyBeaver
. Merci à @Aderis de me diriger dans la bonne direction.
J'ai essayé «setNeedsDisplay» de différentes manières et cela ne fonctionnait pas pour ajuster l'ombre d'une vue animée à une nouvelle position.
J'ai cependant résolu mon problème avec cela. Si votre ombre ne semble pas vouloir coopérer/mettre à jour, vous pouvez simplement définir l'ombre sur nil, puis la redéfinir:
UIView.animateKeyframes(withDuration: 0.2 /*Total*/, delay: 0.0, options: UIViewKeyframeAnimationOptions(), animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 10/10, animations:{
// Other things to animate
//Set shadow to nil
self.viewWithShadow.layer.shadowPath = nil
})
}, completion: { finished in
if (!finished) { return }
// When the view is moved, set the shadow again
self.viewWithShadow.layer.shadowPath = UIBezierPath(rect: self.descTextView.bounds).cgPath
})
Si vous n'avez même pas encore d'ombre et avez besoin de ce code, voici ce qui suit:
func addShadowTo (view: UIView) {
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.gray.cgColor
view.layer.shadowOffset = CGSize( width: 1.0, height: 1.0)
view.layer.shadowOpacity = 0.5
view.layer.shadowRadius = 6.0
view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
view.layer.shouldRasterize = true
}
Merci Keenle, pour la solution ObjC ci-dessus. Je m'amusais à créer des contraintes programmées toute la matinée, à tuer mon cerveau, sans comprendre pourquoi ils ne recompileraient/réaligneraient pas la vue. Je suppose que parce que j'avais créé UIView par programme en utilisant CGRect ... cela prenait le dessus.
Cependant, voici ma solution à Swift:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))
}
Tellement soulagé! :)