2010-08-18 16 views
10

Ich habe eine Ansicht, die ich skalieren und an einen neuen Ort übersetzen möchte, indem ich sie animiere. Ich versuchte es mit dem folgenden Code zu erreichen:UIVIew Animation - Skalierung + Übersetzung

[UIView beginAnimations:nil context:nil]; 
[UIView setAnimationDuration:kDurationForFullScreenAnimation]; 
[[self animatingView] setFrame:finalRect]; 
[UIView commitAnimations]; 

Die Wirkung dieses Codes ist, der Blick zuerst Größe seines Inhalts des wechselt in die finalRect und dann übersetzt sie in die neuen Position. h. der Skalierungsteil wird niemals animiert. Die Ansicht wird einfach in die neue Größe umgewandelt und dann übersetzt.

Dieses Problem wurde bereits in mehreren anderen Threads diskutiert, aber keiner von ihnen zieht eine Schlussfolgerung. Eine Lösung besteht jedoch darin, einen Zeitgeber zu verwenden und den Rahmen jedes Mal in dem Zeitgeberrückruf festzulegen, aber es hat einen Leistungsnachteil.

Was ist die am besten geeignete Lösung für dieses Problem, auch, warum im ersten Fall dieses Problem auftreten?

Dank

Antwort

33

Einstellung des Rahmens tut weder eine Skala noch eine Übersetzung. Sie verwenden entweder die falsche Terminologie oder Sie verwenden das falsche Tool für den Job. Skalierung und Translation werden mit Core Graphics Affine-Transformationen durchgeführt, wenn Sie die UIView beeinflussen möchten (im Gegensatz zur Ebene, die Core-Animation-Transformationen verwendet).

Um eine Ansicht

// 2x 
[rotationView setTransform:CGAffineTransformMakeScale(2.0, 2.0)]; 

, verwenden Sie skalieren verwenden zu übersetzen

// Move origin by 100 on both axis 
[rotationView setTransform:CGAffineTransformMakeTranslation(100.0, 100.0)]; 

diese zu animieren, so dass sie in einem Animationsblock wickeln. Wenn Sie die Ansicht mit diesen beiden transformieren möchten, müssen Sie sie verketten.

Wenn Sie keine Skalierung und Übersetzung (Transformationen) möchten, dann meinen Sie, dass Sie die Grenzen und die Position der Ansicht ändern möchten. Diese werden geändert durch Aufrufe

[view setBounds:newRect]; 
[view setCenter:newCenter]; 

Wo newRect und newCenter sind ein CGRect und CGPoint jeweils, dass die neue Position auf dem Bildschirm darstellen. Auch diese müssen in einen Animationsblock eingepackt werden. Hier

+0

Die Sache ist, wenn ich so tut, wird der Inhalt der Ansicht und alle Unteransichten übernehmen die newRect sofort . Sie werden nicht auf den neuen Frame animiert. Wie gesagt, Sie haben eine Bildansicht als Unteransicht für die animierende Ansicht, das Bild in Bildansicht wird nicht schrittweise skaliert. Stattdessen wird das Bild zuerst in newRect hochgeblasen und dann werden die Grenzen der Ansicht skaliert + übersetzt.Das Ändern der Mitte funktioniert jedoch im Animationsblock, aber die Grenzen ändern sich nicht wie erwartet. –

15

ist ein Beispiel mit Block Animation:

CGPoint newCenter = CGPointMake(100.0,100.0); 

[UIView animateWithDuration: 1 
         delay: 0 
        options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction) 
       animations:^{object.center = newCenter ; object.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2.0, 2.0);} 
       completion:^(BOOL finished) { } 
]; 
4

Versuchen Sie, diese Lösung:

CGAffineTransform s = CGAffineTransformMakeScale(0.5f,0.5f); 
    CGAffineTransform t = CGAffineTransformMakeTranslation(100, 0); 
    v2.transform = CGAffineTransformConcat(t,s); // not s,t 

dieser Vorgang ist nicht kommutativ. Die Reihenfolge ist das Gegenteil der Reihenfolge bei der Verwendung von Komfortfunktionen zum Anwenden einer Transformation auf eine andere.

Und Sie können diesen Vorgang verwenden: zum Beispiel (die Waage entfernen):

v2.transform = 
    CGAffineTransformConcat(CGAffineTransformInvert(s), v2.transform); 
+2

Große Antwort. Von all meiner Suche hat diese mich genau zu dem gebracht, was ich brauchte, um diese Animation so zu machen, wie ich sie brauche. Ich versuche, die Animation, die auf Android angezeigt wird, zu duplizieren, wenn Sie ein Textfeld auswählen, bei dem die Beschriftung kleiner und höher und links ist. Nur eine Skalierung verwandelt das Etikett, aber nach unten und nach rechts. Die Übersetzungsumwandlung wurde ebenfalls benötigt, aber ich konnte keinen Weg finden, beide zur Arbeit zu bringen. Der CGAffineTransformConcat war der Schlüssel. Vielen Dank! – magnusMTB

Verwandte Themen