Πώς μπορώ να επαναφέρω μετά από ζουμ UIScrollView;

ψήφοι
15

Έχω ένα γράφημα στο στάδιο της επεξεργασίας μέσα σε ένα UIScrollView. Είναι ένα μεγάλο UIViewχρησιμοποιώντας μια προσαρμοσμένη υποκατηγορία της CATiledLayerως στρώμα του.

Όταν κάνετε ζουμ μέσα και έξω από το UIScrollView, θέλω το γράφημα για να αλλάξετε το μέγεθος δυναμικά, όπως το κάνει όταν επιστρέψει το γράφημα από το viewForZoomingInScrollView. Ωστόσο, η Γράφημα ίδια επανασχεδιάζει σε νέο επίπεδο ζουμ, και θέλω να επαναφέρετε την κλίμακα μετατρέψει σε 1x1, έτσι ώστε την επόμενη φορά που ο χρήστης μεγεθύνει, η ξεκινά μετατραπεί από την τρέχουσα προβολή. Αν μπορώ να επαναφέρω το μετατρέψει σε ταυτότητας σε scrollViewDidEndZooming, λειτουργεί στον προσομοιωτή, αλλά ρίχνει ένα EXC_BAD_ACCSESστη συσκευή.

Αυτό δεν ακόμη και να λύσει το πρόβλημα εξ ολοκλήρου από τον προσομοιωτή, είτε, γιατί την επόμενη φορά που ο χρήστης μεγεθύνει, το μετασχηματισμό επαναφέρει το ίδιο σε ό, τι επίπεδο μεγέθυνσης ήταν σε, και έτσι μοιάζει, αν ήμουν μεγεθυνθεί και 2 φορές, για παράδειγμα, είναι ξαφνικά σε 4x. Όταν τελειώσει το ζουμ, καταλήγει στη σωστή κλίμακα, αλλά η πραγματική πράξη του ζουμ φαίνεται κακό.

Έτσι, η πρώτη: πώς μπορώ να επιτρέψω το γράφημα στο ίδιο αναδιατυπώσει στην τυπική κλίμακα 1x1 μετά από ζουμ, και πώς μπορώ να έχουν μια ομαλή ζουμ σε όλη;

Επεξεργασία: Νέα ευρήματα Το σφάλμα φαίνεται να είναι « [CALayer retainCount]: message sent to deallocated instance»

Είμαι ποτέ αποδεσμεύοντας όλα τα στρώματα εαυτό μου. Πριν, δεν ήμουν καν τη διαγραφή τυχόν απόψεις ή οτιδήποτε άλλο. Αυτό το σφάλμα που ρίχνονται σε zoom και επίσης σε περιστροφή. Αν μπορώ να διαγράψω το αντικείμενο πριν την περιστροφή και προσθέστε ξανά αργότερα, δεν ρίξει την εξαίρεση. Αυτό δεν είναι μια επιλογή για ζουμ.

Δημοσιεύθηκε 15/01/2009 στις 21:16
πηγή χρήστη
Σε άλλες γλώσσες...                            


7 απαντήσεις

ψήφοι
41

Δεν μπορώ να σας βοηθήσει με την συντριβή, εκτός από σας πω για να ελέγξετε και να βεβαιωθείτε ότι δεν είναι autoreleasing ακούσια μια άποψη ή στρώμα κάπου στον κωδικό σας. Έχω δει ο προσομοιωτής χειριστεί το χρονοδιάγραμμα των autoreleases με διαφορετικό τρόπο από ό, τι στη συσκευή (τις περισσότερες φορές, όταν πρόκειται για θέματα).

Η κλιμάκωση άποψη είναι ένα ζήτημα με UIScrollViewέχω συναντήσει, όμως. Κατά τη διάρκεια μιας εκδήλωσης τσίμπημα-ζουμ, UIScrollViewθα λάβει την προβολή που ορίζεται στην viewForZoomingInScrollView:μέθοδο εκπρόσωπο και να εφαρμόσει μια μετατρέψει σε αυτό. Αυτός ο μετασχηματισμός παρέχει μια ομαλή κλιμάκωση της άποψης, χωρίς να χρειάζεται να το αναδιατυπώσει κάθε καρέ. Στο τέλος της λειτουργίας ζουμ, η μέθοδος εκπρόσωπος σας scrollViewDidEndZooming:withView:atScale:θα κληθεί και θα σας δώσει την ευκαιρία να κάνει μια πιο ποιοτική απόδοση του άποψη σας στο νέο συντελεστή κλίμακας. Σε γενικές γραμμές, σας προτείνω να επαναφέρετε το μετατρέψει σε άποψή σας να είναι CGAffineTransformIdentityκαι στη συνέχεια να έχουν την άποψή σας αναδιατυπώσει το ίδιο με το χέρι στη νέα κλίμακα μεγέθους.

Ωστόσο, αυτό προκαλεί ένα πρόβλημα, διότι UIScrollViewδεν φαίνεται να παρακολουθεί η άποψη περιεχομένου μετασχηματισμό, έτσι για την επόμενη λειτουργία ζουμ θέτει το μετασχηματισμό της προβολής περιεχομένου σε ό, τι ο γενικός συντελεστής κλίμακας είναι. Από τη στιγμή που έχετε επανασχεδιαστεί με μη αυτόματο τρόπο την άποψή σας, κατά την τελευταία συντελεστή κλίμακας, ενώσεις την κλιμάκωση, το οποίο είναι αυτό που βλέπετε.

Ως λύση, μπορώ να χρησιμοποιήσω μια υποκατηγορία UIView για την προβολή του περιεχομένου μου με τους ακόλουθους τρόπους που ορίζονται:

- (void)setTransformWithoutScaling:(CGAffineTransform)newTransform;
{
    [super setTransform:newTransform];
}

- (void)setTransform:(CGAffineTransform)newValue;
{
    [super setTransform:CGAffineTransformScale(newValue, 1.0f / previousScale, 1.0f / previousScale)];
}

όπου previousScale είναι ένα πλωτήρα παράδειγμα μεταβλητή της άποψης. Στη συνέχεια την εφαρμογή της μεθόδου ζουμ εκπρόσωπο ως εξής:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
    [contentView setTransformWithoutScaling:CGAffineTransformIdentity];
// Code to manually redraw view at new scale here
    contentView.previousScale = scale;
    scrollView.contentSize = contentView.frame.size;
}

Με τον τρόπο αυτό, οι μετασχηματισμοί που αποστέλλονται με την άποψη του περιεχομένου ρυθμίζονται με βάση την κλίμακα στην οποία η θέα ήταν τελευταία επανασχεδιάζεται. Όταν το τσίμπημα-ζουμ γίνεται, ο μετασχηματισμός επαναφορά σε κλίμακα από 1,0 παρακάμπτοντας την προσαρμογή στην κανονική setTransform:μέθοδο. Αυτό φαίνεται να παρέχει τη σωστή συμπεριφορά κλιμάκωσης ενώ θα αφήσουμε να σχεδιάσετε μια τραγανή θέα στην ολοκλήρωση ενός ζουμ.

UPDATE (23/7/2010): iPhone OS 3.2 και άνω έχουν αλλάξει τη συμπεριφορά των απόψεων κύλισης σε σχέση με ζουμ. Τώρα, ένας UIScrollViewθα σέβεται την ταυτότητα μετασχηματισμό που εφαρμόζεται σε μια προβολή περιεχομένου και παρέχει μόνο τη σχετική συντελεστή κλίμακας σε -scrollViewDidEndZooming:withView:atScale:. Ως εκ τούτου, η παραπάνω κώδικα για μια UIViewυποκατηγορία είναι απαραίτητη μόνο για συσκευές που εκτελούν εκδόσεις του iPhone OS ηλικίας άνω των 3.2.

Απαντήθηκε 16/01/2009 στις 20:29
πηγή χρήστη

ψήφοι
12

Χάρη σε όλες τις προηγούμενες απαντήσεις, και εδώ είναι η λύση μου.
Εφαρμογή UIScrollViewDelegate μεθόδους:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return tmv;
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    CGPoint contentOffset = [tmvScrollView contentOffset];   
    CGSize  contentSize   = [tmvScrollView contentSize];
     CGSize  containerSize = [tmv frame].size;

    tmvScrollView.maximumZoomScale = tmvScrollView.maximumZoomScale / scale;
    tmvScrollView.minimumZoomScale = tmvScrollView.minimumZoomScale / scale;

    previousScale *= scale;

    [tmvScrollView setZoomScale:1.0f];

    [tmvScrollView setContentOffset:contentOffset];
    [tmvScrollView setContentSize:contentSize];
    [tmv setFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];  

    [tmv reloadData];
}
  • TMV είναι υποκατηγορία μου UIView
  • tmvScrollView - πρίζα για να UIScrollView
  • που maximumZoomScale και minimumZoomScale πριν
  • δημιουργούν previousScale παράδειγμα μεταβλητή και ορίστε την τιμή σε 1.0f

Έργα για μένα τέλεια.

BR, Eugene.

Απαντήθηκε 02/08/2011 στις 17:33
πηγή χρήστη

ψήφοι
5

Έχω μια λεπτομερή συζήτηση για το πώς (και γιατί) λειτουργεί UIScrollView ζουμ σε github.com/andreyvit/ScrollingMadness/ .

(Ο σύνδεσμος περιέχει επίσης μια περιγραφή του τρόπου προγραμματισμού μεγέθυνση UIScrollView, πώς να μιμηθούν Photo Library στυλ τηλεειδοποίησης + ζουμ + κύλιση, ένα παράδειγμα έργου και ZoomScrollView κατηγορία που ενσωματώνει μερικά από τα ζουμ μαγείας.)

Παραθέτω, αναφορά:

UIScrollView δεν έχει έννοια της «τρέχον επίπεδο ζουμ», επειδή κάθε δευτερεύουσας προβολής περιέχει μπορεί να έχει τη δική τρέχον επίπεδο ζουμ. Σημειώστε ότι δεν υπάρχει πεδίο UIScrollView να διατηρηθεί το τρέχον επίπεδο ζουμ. Ωστόσο γνωρίζουμε ότι κάποιος αποθηκεύει αυτό το επίπεδο ζουμ, γιατί αν τσίμπημα-zoom μια δευτερεύουσας προβολής, στη συνέχεια επαναφορά του μετασχηματισμού για CGAffineTransformIdentity, και στη συνέχεια, πρέζα και πάλι, θα παρατηρήσετε ότι το προηγούμενο επίπεδο ζουμ της δευτερεύουσας προβολής έχει αποκατασταθεί.

Πράγματι, αν δει κανείς την αποσυναρμολόγηση, είναι UIView που αποθηκεύει το δικό του επίπεδο μεγέθυνσης του (εντός αντικείμενο UIGestureInfo που υποδεικνύεται από τον τομέα _gestureInfo). Έχει, επίσης, μια σειρά από ωραία παράνομων μεθόδων, όπως zoomScaleκαι setZoomScale:animated:. (Μυαλό σας, έχει επίσης ένα σωρό μεθόδους περιστροφής που σχετίζονται, ίσως παίρνουμε την περιστροφή χειρονομία υποστηρίξει κάποια μέρα σύντομα.)

Ωστόσο, αν δημιουργήσουμε μια νέα UIView μόνο για τη μεγέθυνση και προσθέστε πραγματικό zoomable την άποψή μας, ως παιδί του, θα αρχίσει πάντα με το επίπεδο ζουμ 1.0. εφαρμογή μου της προγραμματικής ζουμ βασίζεται σε αυτό το τέχνασμα.

Απαντήθηκε 08/05/2009 στις 00:04
πηγή χρήστη

ψήφοι
4

Ήμουν απλά ψάχνουν για να επαναφέρετε το φορτίο στην προεπιλογή κλίμακα ζουμ, γιατί όταν το zoom, scrollview έχει ίδια κλίμακα ζουμ για την επόμενη φορά, μέχρι να παίρνει deallocated.

-(void) viewWillAppear:(BOOL)animated {
      [self.scrollView setZoomScale:1.0f];
}

Άλλαξε το παιχνίδι.

Απαντήθηκε 03/06/2015 στις 06:53
πηγή χρήστη

ψήφοι
3

Μια αρκετά αξιόπιστη προσέγγιση, κατάλληλη για iOS 3.2 και 4.0 και αργότερα, είναι ως εξής. Πρέπει να είστε προετοιμασμένοι να παρέχει κλιμακούμενη την άποψή σας (ο επικεφαλής δευτερεύουσας προβολής της προβολής κύλισης) σε οποιαδήποτε ζήτησε κλίμακα. Στη συνέχεια, scrollViewDidEndZooming:θα αφαιρέσει τη θολή κλίμακας μετατραπεί έκδοση αυτής της άποψης και να την αντικαταστήσει με μια νέα άποψη που με τη νέα κλίμακα.

Θα χρειαστείτε:

  • Μια Ivar για τη διατήρηση του προηγούμενου κλίμακα? ας το ονομάσουμε oldScale

  • Ένας τρόπος προσδιορισμού της επεκτάσιμη άποψη, τόσο για viewForZoomingInScrollView:και για scrollViewDidEndZooming:? Εδώ, θα πάω να εφαρμόσει μια ετικέτα (999)

  • Μια μέθοδος που δημιουργεί την κλιμακούμενη άποψη, ετικέτες αυτό, και εισάγει στην προβολή κύλισης (εδώ θα το ονομάσουμε addNewScalableViewAtScale:). Να θυμάστε, ότι πρέπει να κάνουμε τα πάντα σύμφωνα με την κλίμακα - το μέγεθος της γνώμης και subviews ή σχέδιο του, και τα μεγέθη contentSize του άποψη κύλισης για να ταιριάζει.

  • Σταθερές για την minimumZoomScale και maximumZoomScale. Αυτά είναι αναγκαία, επειδή όταν αντικαθιστούμε την κλίμακα άποψη από την λεπτομερή μεγαλύτερη εκδοχή, το σύστημα πρόκειται να πιστεύω ότι η σημερινή κλίμακα είναι 1, γι 'αυτό πρέπει να ξεγελάσουν να επιτρέπει στο χρήστη να αναβαθμίσουν τη θέα πίσω.

Πολυ καλα λοιπον. Όταν δημιουργήσετε την προβολή κύλισης, βάλε εσύ την κλιμακούμενη θέα σε κλίμακα 1.0. Αυτό μπορεί να είναι σε σας viewDidLoad, για παράδειγμα, ( svείναι η άποψη κύλισης):

[self addNewScalableViewAtScale: 1.0];
sv.minimumZoomScale = MIN;
sv.maximumZoomScale = MAX;
self->oldScale = 1.0;
sv.delegate = self;

Στη συνέχεια, σας scrollViewDidEndZooming:μπορείτε να κάνετε το ίδιο πράγμα, αλλά αντισταθμίζεται η αλλαγή στην κλίμακα:

UIView* v = [sv viewWithTag:999];
[v removeFromSuperview];
CGFloat newscale = scale * self->oldScale;
self->oldScale = newscale;
[self addNewScalableViewAtScale:newscale];
sv.minimumZoomScale = MIN / newscale;
sv.maximumZoomScale = MAX / newscale;
Απαντήθηκε 12/11/2010 στις 06:33
πηγή χρήστη

ψήφοι
2

Σημειώστε ότι η λύση που παρέχεται από τον Brad έχει ένα πρόβλημα όμως: αν έχετε κρατήσει προγραμματισμού μεγέθυνση (ας πούμε για τη διπλή εκδήλωση βρύση) και αφήστε το χρήστη χειροκίνητα (τσίμπημα-out) zoom out, μετά από κάποιο χρονικό διάστημα η διαφορά μεταξύ της πραγματικής κλίμακας και την κλίμακα UIScrollView είναι η παρακολούθηση θα αυξηθεί πάρα πολύ μεγάλο, έτσι η previousScaleθέληση σε κάποιο σημείο πτώση από την ακρίβεια πλωτήρα, η οποία θα οδηγήσει τελικά σε μια απρόβλεπτη συμπεριφορά

Απαντήθηκε 28/07/2009 στις 04:43
πηγή χρήστη

ψήφοι
0

Swift 4. * και Xcode 9.3

Ρύθμιση κλίμακας ζουμ scrollView στο 0 θα επαναφέρει scrollView σας να είναι αρχική του κατάσταση.

self.scrollView.setZoomScale(0.0, animated: true)
Απαντήθηκε 29/06/2018 στις 05:21
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more