2010-07-22 20 views
5

Ich habe eine UIView innerhalb einer UIScrollView. Immer wenn sich der UIScrollView Zoom ändert, möchte ich die gesamte UIView auf der neuen Zoomstufe neu zeichnen.UIScrollView Inhalt nach jedem Zoom neu zeichnen

In iOS < 3.2, ich tat dies, indem Sie die UIView im UIScrollView Ändern der Größe die neue Größe zu machen und dann die zurück zur Identität Einstellung verwandeln, so dass sie es nicht versuchen würden, weiter zu ändern. Mit iOS> = 3.2 verändert die Änderung der Identität jedoch auch die Eigenschaft zoomScale des UIScrollView.

Das Ergebnis ist, dass, wenn ich zoome (sagen 2x), ich die eingebettete UIView auf die geeignete Größe anpassen und neu zeichnen. Jetzt aber (seit ich die Transformation auf Identität zurücksetze), denkt die UIScrollView an zoomScale 1, anstatt an zoomScale 2. Also wenn ich meine maxZoomScale auf 2 gesetzt habe, wird sie immer noch weiter zoomen, was falsch ist.

Ich dachte über die Verwendung der CATiledLayer, aber ich denke nicht, dass dies für mich ausreicht, da ich nach jedem Zoom neu zeichnen möchte, nicht nur bei bestimmten Zoom-Schwellen wie es versucht.

Kann jemand das richtige Neuzeichnen der UIView auf einem Zoom tun?

Antwort

15

Tom,

Ihre Frage ist ein bisschen alt, aber ich kam mit einer Lösung für diese, so dass ich dachte, ich in einer Antwort gesetzt hatte, falls es Sie oder jemand anderes hilft. Der grundlegende Trick besteht darin, die Ansicht zoomScale der Bildlaufansicht auf 1 zurückzusetzen und dann die Werte und maximumZoomScale so anzupassen, dass der Benutzer wie erwartet weiter ein- und auszoomen kann.

In meiner Implementierung habe ich UIScrollView unterklassifiziert und es als seinen eigenen Delegaten festgelegt. In meiner Unterklasse implementiere ich die zwei Delegate-Methoden, die Sie zum Zoomen benötigen (siehe unten). contentView ist eine Eigenschaft, die ich meiner Unterklasse UIScrollView hinzugefügt habe, um ihr die Ansicht zu geben, die den Inhalt tatsächlich anzeigt.

Also, meine Init-Methode sieht wie folgt aus etwas (kMinimumZoomScale und kMaximumZoomScale sind #define ‚s an der Spitze der Klasse):

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     self.autoresizesSubviews = YES; 
     self.showsVerticalScrollIndicator = YES; 
     self.showsHorizontalScrollIndicator = NO; 
     self.bouncesZoom = YES; 
     self.alwaysBounceVertical = YES; 
     self.delegate = self; 

     self.minimumZoomScale = kMinimumZoomScale; 
     self.maximumZoomScale = kMaximumZoomScale; 
    } 

    return self; 
} 

Dann implementiere ich die Standard UIScrollView Delegatmethoden zum Zoomen. Meine Klasse ContentView hat eine Eigenschaft namens zoomScale, die angibt, welche Skalierung für die Anzeige des Inhalts verwendet werden soll. Es verwendet das in seiner drawRect Methode, um den Inhalt wie geeignet zu ändern.

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView { 
    return contentView; 
} 


- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)scale { 
    CGFloat oldZoomScale = contentView.zoomScale; 
    CGSize size = self.bounds.size; 

    // Figure out where the scroll view was centered so that we can 
    // fix up its offset after adjusting the scaling 
    CGPoint contentCenter = self.contentOffset; 
    contentCenter.x += size.width/(oldZoomScale * scale)/2; 
    contentCenter.y += size.height/(oldZoomScale * scale)/2; 

    CGFloat newZoomScale = scale * oldZoomScale; 
    newZoomScale = MAX(newZoomScale, kMinimumZoomscale); 
    newZoomScale = MIN(newZoomScale, kMaximumZoomscale); 

    // Set the scroll view's zoom scale back to 1 and adjust its minimum and maximum 
    // to allow the expected amount of zooming. 
    self.zoomScale = 1.0; 
    self.minimumZoomScale = kMinimumZoomScale/newZoomScale; 
    self.maximumZoomScale = kMaximumZoomScale/newZoomScale; 

    // Tell the contentView about its new scale. My contentView.zoomScale setter method 
    // calls setNeedsDisplay, but you could also call it here 
    contentView.zoomScale = newZoomScale; 

    // My ContentView class overrides sizeThatFits to give its expected size with 
    // zoomScale taken into account 
    CGRect newContentSize = [contentView sizeThatFits]; 

    // update the content view's frame and the scroll view's contentSize with the new size 
    contentView.frame = CGRectMake(0, 0, newContentSize.width, newContentSize.height); 
    self.contentSize = newContentSize; 

    // Figure out the new contentOffset so that the contentView doesn't appear to move 
    CGPoint newContentOffset = CGPointMake(contentCenter.x - size.width/newZoomScale/2, 
              contentCenter.y - size.height/newZoomScale/2); 
    newContentOffset.x = MIN(newContentOffset.x, newContentSize.width - size.width); 
    newContentOffset.x = MAX(0, newContentOffset.x); 
    newContentOffset.y = MIN(newContentOffset.y, newContentSize.height - .size.height); 
    newContentOffset.y = MAX(0, newContentOffset.y); 
    [self setContentOffset:newContentOffset animated:NO]; 
} 
+0

Vielen Dank für Ihre Lösung! Das löst [meine Frage] (http://stackoverflow.com/questions/3970988/how-to-draw-on-a-non-transformed-context-while-zoomed-in-a-catiledlayer). Könnten Sie hier einen Link zu Ihrer Antwort hinterlassen, damit ich Ihnen die richtige Antwort geben kann? – TinkerTank

+0

Wenn diese Methode zum Zoomen eines CATiledLayers verwendet wird, muss der Kachelcache vor dem Aufruf von setNeedsDisplay gelöscht werden. Eine Lösung zum Löschen des CATiledLayerCache finden Sie [hier] (http: // stackoverflow.com/questions/1274680/clear-catiledlayers-cache-wenn-changed-images) – TinkerTank

+0

können Sie bitte erklären, die Eigenschaft der contentSize und wie es gesetzt wird und was es tatsächlich ist. Danke – BDGapps

0

In meinem Fall habe ich eine Bildansicht und oben auf der Bildansicht habe ich mehrere andere Bildansichten. Dies ist die Implementierung, die ich kam und funktioniert gut:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(double)scale{ 
    NSLog(@"finished zooming"); 

    NSLog(@"position x :%f",pin1.frame.origin.x); 
    NSLog(@"position y :%f",pin1.frame.origin.y); 


    CGRect frame = pin1.frame; 
    frame.origin.x = pin1.frame.origin.x * scale; 
    frame.origin.y = pin1.frame.origin.y * scale; 
    pin1.frame = frame; 

    NSLog(@"position x new :%f",pin1.frame.origin.x); 
    NSLog(@"position y new:%f",pin1.frame.origin.y); 

} 
Verwandte Themen