UIView de mise à l'échelle lors de l'animation
J'ai un custom UIView pour afficher une image en mosaïque.
- (void)drawRect:(CGRect)rect
{
...
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToRect(context,
CGRectMake(0.0, 0.0, rect.size.width, rect.size.height));
CGContextDrawTiledImage(context, imageRect, imageRef);
...
}
Maintenant, je suis en train d'animer le redimensionnement de ce point de vue.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
//change frame of view
[UIView commitAnimations];
Ce que je m'attends est pour la surface carrelée juste pour se développer, laissant sur le carreau les tailles constante. Ce qui se passe au lieu de cela est que, bien que la région se développe le contenu d'origine de l'affichage est adapté à la nouvelle taille. Au moins au cours de l'animation. De sorte que le au début et à la fin de l'animation, tout est bon. Au cours de l'animation, les tuiles sont déformées.
Pourquoi CA essayant à l'échelle? Comment puis-je l'empêcher de le faire? Qu'ai-je manqué?
- Elle semble liée à l'affichage de contentMode. Mais la mise à UIViewContentModeLeft ne résout pas vraiment non plus. Il n'est alors pas plus à l'échelle, mais les pop à la nouvelle taille de l'image tout de suite. Le paramètre UIViewContentModeRedraw ne semble pas être l'appel à drawRect à tous les cours de l'animation.
Vous devez vous connecter pour publier un commentaire.
Si Core Animation avait pour rappeler à votre code pour chaque image d'animation, il ne sera jamais aussi rapide comme il est, et de l'animation de propriétés personnalisées a été long, demande de fonctionnalité et une FAQ pour CA sur le Mac.
À l'aide de
UIViewContentModeRedraw
est sur la bonne voie, et est également le meilleur que vous aurez à partir de CA. Le problème, c'est de la UIKit point de vue, le cadre n'a que deux valeurs: la valeur au début de la transition et de la valeur à la fin de la transition, et c'est ce que vous voyez. Si vous regardez au Cœur de l'Animation de documents d'architecture, vous allez voir comment CA a privé de la représentation de toutes les propriétés de la couche et de leur évolution des valeurs au cours du temps. C'est là que l'interpolation d'images qui se passe, et vous ne pouvez pas être informé des changements à mesure qu'ils se produisent.Donc le seul moyen est d'utiliser un
NSTimer
(ouperformSelector:withObject:afterDelay:
) pour changer le point de vue image au fil du temps, à l'ancienne.drawRect
, vous devriez appelersetNeedsDisplay
.setNeedsDisplay
appelleradrawRect
! Et C'est aussi ce que je voulais dire.setNeedsDisplay
ne pas faire appeldrawRect
, mais les causesdrawRect
être appelé la prochaine fois que l'INTERFACE utilisateur obtient une chance d'être redessiné.Vous pouvez avoir un coup d'oeil à
http://www.nomadplanet.fr/2010/11/animate-calayer-custom-properties-with-coreanimation/
J'ai été confronté à un problème similaire dans un contexte différent, je suis tombé sur ce thread et trouvé Duncan suggestion de réglage de l'image dans NSTimer. J'ai mis en place ce code pour obtenir le même:
J'ai trouvé qu'il prend beaucoup de temps à définir le cadre et la minuterie pour valider son fonctionnement. Probablement qu'elle dépend de la profondeur de la vue de la hiérarchie est sur lequel vous appelez -setFrame à l'aide de cette approche. Et c'est probablement la raison pour laquelle le point de vue est d'abord re-dimensionné et puis d'animation à l'origine dans le sdk. Ou peut-être, est-il un problème dans le mécanisme de minuterie dans mon code en raison de laquelle la prestation a entravé?
Cela fonctionne, mais il est très lent, peut-être parce que mon point de vue de la hiérarchie est trop profonde.
Comme Duncan indique, Core Animation ne pas redessiner votre UIView du contenu du calque à chaque image lors du redimensionnement. Vous devez le faire vous-même à l'aide d'une minuterie.
Les mecs de chez Omni posté un bel exemple de la façon de faire des animations sur la base de vos propres propriétés qui pourraient être applicables à votre cas. Cet exemple, avec une explication de comment cela fonctionne, peut être trouvé ici.
Si ce n'est pas un grand de l'animation ou de la performance n'est pas un problème pour l'animation de la durée, vous pouvez utiliser un CADisplayLink. Il n'lisser l'animation de la mise à l'échelle d'une coutume UIView dessin UIBezierPaths par exemple. Ci-dessous est un exemple de code, vous pouvez l'adapter à votre image.
La ivars de ma vue personnalisée contient displayLink comme un CADisplayLink, et deux CGRects: toFrame et fromFrame, ainsi que la durée et startTime.
Remarque que je n'ai pas testé ses performances, mais il fonctionne bien.
Je suis tombé sur cette question lors de la tentative pour animer un changement de taille sur une UIView avec une bordure. J'espère que d'autres personnes de même arriver ici, pourraient bénéficier de cette réponse. A l'origine, j'étais en train de créer un personnalisé sous-classe UIView et en remplaçant la méthode drawRect comme suit:
Cela a conduit à la mise à l'échelle des problèmes lors de la combinaison avec des animations comme d'autres l'ont mentionné. Le haut et le bas de la frontière serait pousser trop épais ou deux minces et apparaissent à l'échelle. Cet effet est facilement perceptible lors du basculement sur la Lenteur des Animations.
La solution a été d'abandonner la sous-classe personnalisée et d'utiliser cette approche:
Cette correction du problème avec la mise à l'échelle d'une frontière sur une UIView lors des animations.