J'ai une vue qui contient des rangées et des colonnes de vues d'image.
Si cette vue est redimensionnée, je dois réorganiser les positions des images vues.
Cette vue est une sous-vue d'une autre vue redimensionnée.
Existe-t-il un moyen de détecter le redimensionnement de cette vue?
Comme Uli a commenté ci-dessous, la bonne façon de le faire est de remplacer layoutSubviews
et d'y placer l'imageViews.
Si, pour une raison quelconque, vous ne pouvez pas sous-classer ni remplacer layoutSubviews
, observer bounds
devrait fonctionner, même s'il est en quelque sorte sale. Pire encore, le fait d’observer - Apple ne garantit pas le fonctionnement de KVO sur les classes UIKit. Lisez la discussion avec Apple ingénieur ici: Quand un objet associé est-il libéré?
réponse originale:
Vous pouvez utiliser l'observation clé-valeur:
[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];
et mettre en œuvre:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
// do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
}
}
Dans une sous-classe UIView
, observateurs de propriétés peut être utilisé:
override var bounds: CGRect {
didSet {
// ...
}
}
Sans sous-classement, observation clé-valeur avec chemins-clés intelligents fera:
var boundsObservation: NSKeyValueObservation?
func beginObservingBounds() {
boundsObservation = observe(\.bounds) { capturedSelf, _ in
// ...
}
}
Créer une sous-classe d'UIView et substituer layoutSubviews
Assez vieux mais reste une bonne question. Dans l'exemple de code d'Apple et dans certaines de leurs sous-classes privées UIView, ils surchargent setBounds en gros comme ceci:
-(void)setBounds:(CGRect)newBounds {
BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves
[super setBounds:newBounds];
if (isResize) [self recoverFromResizing];
}
Remplacement setFrame:
n'est PAS une bonne idée. frame
est dérivé de center
, bounds
et transform
, de sorte que iOS n'appellera pas nécessairement setFrame:
.
Swift 4 keypath KVO - C’est ainsi que je détecte l’autorotation et le déplacement vers le panneau latéral de l’iPad. Devrait travailler travailler n'importe quelle vue. J'ai dû observer la couche d'UIView.
private var observer: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observer = view.layer.observe(\.bounds) { object, _ in
print(object.bounds)
}
// ...
}
override func viewWillDisappear(_ animated: Bool) {
observer?.invalidate()
//...
}
Vous pouvez créer une sous-classe d’UIView et remplacer le
setFrame: cadre (CGRect)
méthode. C'est la méthode appelée lorsque le cadre (c'est-à-dire la taille) de la vue est modifié. Faites quelque chose comme ça:
- (void) setFrame:(CGRect)frame
{
// Call the parent class to move the view
[super setFrame:frame];
// Do your custom code here.
}