UIScrollView με επίκεντρο UIImageView, όπως εφαρμογή Photos

ψήφοι
37

Θα ήθελα να έχω την άποψη κύλισης με θέα το περιεχόμενο της εικόνας. Η εικόνα είναι πραγματικά χάρτη που είναι πολύ μεγαλύτερο από ό, τι στην οθόνη. Ο χάρτης θα πρέπει να είναι αρχικά στο κέντρο της προβολής κύλισης, όπως φωτογραφίες Φωτογραφίες εφαρμογή όταν ενεργοποιείτε το iPhone σε οριζόντιο προσανατολισμό.

alt

Δεν κατάφερα να το χάρτη στο κέντρο με σωστή ζουμ και κύλιση ταυτόχρονα. Υπό την προϋπόθεση ότι η εικόνα χάρτη ξεκινά από την κορυφή της οθόνης (σε κατακόρυφο προσανατολισμό), ο κώδικας μοιάζει κάπως έτσι:

- (void)loadView {
    mapView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@map.jpg]];
    CGFloat mapHeight = MAP_HEIGHT * SCREEN_WIDTH / MAP_WIDTH;
    mapView.frame = CGRectMake(0, 0, SCREEN_WIDTH, mapHeight);
    scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    scrollView.delegate = self;
    scrollView.contentSize = mapView.frame.size;
    scrollView.maximumZoomScale = MAP_WIDTH / SCREEN_WIDTH;
    scrollView.minimumZoomScale = 1;
    [scrollView addSubview:mapView];
    self.view = scrollView;
}

Όταν μετακινήσετε το πλαίσιο της εικόνας στο κέντρο, η εικόνα μεγαλώνει μόνο από την κορυφή του πλαισίου της προς τα κάτω. Προσπάθησα να παίζουν με MapView μετασχηματισμό, με δυναμικά μεταβαλλόμενο πλαίσιο της ImageView. Τίποτα δεν λειτουργεί για μένα μέχρι τώρα.

Δημοσιεύθηκε 12/03/2009 στις 12:56
πηγή χρήστη
Σε άλλες γλώσσες...                            


11 απαντήσεις

ψήφοι
40

Αυτός ο κωδικός θα πρέπει να εργαστούν στις περισσότερες εκδόσεις του iOS (και έχει δοκιμαστεί για να λειτουργήσουν σε 3,1 προς τα πάνω).

Είναι με βάση τον κώδικα της Apple WWDC που αναφέρονται στην απάντηση του Ιωνά.

Προσθέστε το παρακάτω στο υποκατηγορία σας UIScrollView, και αντικαταστήστε tileContainerView με την άποψη που περιέχει την εικόνα ή πλακάκια σας:

- (void)layoutSubviews {
    [super layoutSubviews];

    // center the image as it becomes smaller than the size of the screen
    CGSize boundsSize = self.bounds.size;
    CGRect frameToCenter = tileContainerView.frame;

    // center horizontally
    if (frameToCenter.size.width < boundsSize.width)
        frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
    else
        frameToCenter.origin.x = 0;

    // center vertically
    if (frameToCenter.size.height < boundsSize.height)
        frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
    else
        frameToCenter.origin.y = 0;

    tileContainerView.frame = frameToCenter;
}
Απαντήθηκε 13/08/2010 στις 17:42
πηγή χρήστη

ψήφοι
23

Εδώ είναι αυτό που θα εξετάσει τη λύση και σε αυτό συμπεριφέρεται ακριβώς όπως η φωτογραφία app της Apple. Είχα χρησιμοποιήσει τις λύσεις που χρησιμοποιούνται:

-(void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale

για να κεντράρετε, αλλά δεν μου άρεσε αυτή τη λύση γιατί μετά το ζουμ έγινε, θα ήθελα να αναπηδήσει στη συνέχεια, γρήγορα «άλμα» στο κέντρο το οποίο ήταν πολύ un-sexy. Βγάζει αν λίγο πολύ κάνει το ίδιο ακριβώς λογική, αλλά σε αυτή τη λειτουργία εκπρόσωπος:

-(void)scrollViewDidZoom:(UIScrollView *)pScrollView

είναι τόσο ξεκινά στο κέντρο και όταν σμίκρυνση ότι παραμένει επικεντρωμένη:

-(void)scrollViewDidZoom:(UIScrollView *)pScrollView {
CGRect innerFrame = imageView.frame;
CGRect scrollerBounds = pScrollView.bounds;

if ( ( innerFrame.size.width < scrollerBounds.size.width ) || ( innerFrame.size.height < scrollerBounds.size.height ) )
{
    CGFloat tempx = imageView.center.x - ( scrollerBounds.size.width / 2 );
    CGFloat tempy = imageView.center.y - ( scrollerBounds.size.height / 2 );
    CGPoint myScrollViewOffset = CGPointMake( tempx, tempy);

    pScrollView.contentOffset = myScrollViewOffset;

}

UIEdgeInsets anEdgeInset = { 0, 0, 0, 0};
if ( scrollerBounds.size.width > innerFrame.size.width )
{
    anEdgeInset.left = (scrollerBounds.size.width - innerFrame.size.width) / 2;
    anEdgeInset.right = -anEdgeInset.left;  // I don't know why this needs to be negative, but that's what works
}
if ( scrollerBounds.size.height > innerFrame.size.height )
{
    anEdgeInset.top = (scrollerBounds.size.height - innerFrame.size.height) / 2;
    anEdgeInset.bottom = -anEdgeInset.top;  // I don't know why this needs to be negative, but that's what works
}
pScrollView.contentInset = anEdgeInset;
}

Πού «ImageView» είναι το UIImageViewχρησιμοποιείτε.

Απαντήθηκε 03/02/2010 στις 03:51
πηγή χρήστη

ψήφοι
7

Η Apple έχει κυκλοφορήσει το βίντεο WWDC σύνοδο του 2010 σε όλα τα μέλη του προγράμματος iphone έργου. Ένα από τα θέματα που συζητήθηκαν είναι πως δημιούργησε το app φωτογραφίες !!! Χτίζουν ένα πολύ παρόμοιο βήμα app βήμα και έχουν κάνει όλος ο κώδικας διαθέσιμο για δωρεάν.

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

http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?code=y&source=x&bundleID=20645

Και, εδώ είναι μια σύνδεση με τη σελίδα iTunes WWDC:

http://insideapple.apple.com/redir/cbx-cgi.do?v=2&la=en&lc=&a=kGSol9sgPHP%2BtlWtLp%2BEP%2FnxnZarjWJglPBZRHd3oDbACudP51JNGS8KlsFgxZto9X%2BTsnqSbeUSWX0doe%2Fzv%2FN5XV55%2FomsyfRgFBysOnIVggO%2Fn2p%2BiweDK%2F%2FmsIXj

Απαντήθηκε 20/06/2010 στις 20:48
πηγή χρήστη

ψήφοι
2

Υποψιάζομαι ότι θα πρέπει να ρυθμίσετε το UIScrollView«s contentOffset.

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

ψήφοι
1

Αυτό λειτούργησε για μένα:

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGFloat tempx = view.center.x-160;
CGFloat tempy = view.center.y-160;
myScrollViewOffset = CGPointMake(tempx,tempy);

}

όπου το 160 είναι το ήμισυ του πλάτους / ύψος σας UIScrollView.

Στη συνέχεια, αργότερα που το contentoffset με αυτό που συλλαμβάνονται εδώ.

Απαντήθηκε 31/03/2009 στις 09:15
πηγή χρήστη

ψήφοι
1

Μακάρι να ήταν τόσο απλό. Έκανα κάποια έρευνα στο διαδίκτυο και βρήκε ότι δεν είναι μόνο δικό μου πρόβλημα, αλλά πολλοί άνθρωποι αγωνίζονται με το ίδιο θέμα, όχι μόνο για το iPhone, αλλά στην επιφάνεια εργασίας κακάο της Apple, καθώς και. Δείτε παρακάτω συνδέσμους:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/5740-uiimageview-uiscrollview.html
Η περιγραφόμενη λύση βασίζεται στην UIViewContentModeScaleAspectFit ιδιοκτησία της εικόνας, αλλά δυστυχώς δεν λειτουργεί πολύ καλά .Η εικόνα είναι στο κέντρο και αναπτύσσεται σωστά, αλλά η περιοχή γερός φαίνεται να είναι πολύ μεγαλύτερο από την εικόνα.

Αυτός ο τύπος δεν είχε πάρει την απάντηση είτε:
http://discussions.apple.com/thread.jspa?messageID=8322675

Και τέλος, το ίδιο πρόβλημα στην επιφάνεια εργασίας κακάο της Apple:
http://www.cocoadev.com/index.pl?CenteringInsideNSScrollView
Υποθέτω ότι η λύση αυτή λειτουργεί, αλλά βασίζεται στην NSClipView, η οποία δεν είναι για το iPhone ...

Ο καθένας έχει κάποια λύση που εργάζονται για το iPhone;

Απαντήθηκε 13/03/2009 στις 08:29
πηγή χρήστη

ψήφοι
0

Εδώ είναι μια εναλλακτική λύση, παρόμοια με @ απάντηση JosephH, αλλά αυτό λαμβάνει υπόψη τις πραγματικές διαστάσεις της εικόνας. Έτσι ώστε, όταν τα τηγάνια χρήστης / ζουμ, δεν μπορείτε ποτέ να έχουν περισσότερα κενά στην οθόνη από ό, τι απαιτείται. Αυτό είναι ένα κοινό πρόβλημα, για παράδειγμα, όταν παρουσιάζουν μια εικόνα του τοπίου σε μια οθόνη πορτρέτο. Εκεί πρόκειται να είναι κενά πάνω και κάτω από την εικόνα, όταν ολόκληρη η εικόνα είναι στην οθόνη (διαστάσεων Fit). Στη συνέχεια, όταν κάνετε ζουμ, οι άλλες λύσεις που θεωρούν ότι κενά ως μέρος της εικόνας, επειδή είναι στην ImageView. Θα σας αφήσει να μετακινήσετε το μεγαλύτερο μέρος της εικόνας από την οθόνη, αφήνοντας μόνο το κενό ορατό. Αυτό φαίνεται κακό για το χρήστη.

Με αυτή την κατηγορία, χρειάζεται να περάσει το ImageView ότι λειτουργεί με. Μπήκα στον πειρασμό να έχουν αυτόματη ανίχνευση, αλλά αυτό είναι ταχύτερη και θέλετε όλη την ταχύτητα που μπορείτε να πάρετε στην layoutSubviewsμέθοδο.

Σημείωση: Όπως είναι, αυτό απαιτεί αυτόματη διάταξη δεν είναι ενεργοποιημένη για την scrollView.

//
//  CentringScrollView.swift
//  Cerebral Gardens
//
//  Created by Dave Wood
//  Copyright © 2016 Cerebral Gardens Inc. All rights reserved.
//

import UIKit

class CentringScrollView: UIScrollView {

    var imageView: UIImageView?

    override func layoutSubviews() {
        super.layoutSubviews()

        guard let superview = superview else { return }
        guard let imageView = imageView else { return }
        guard let image = imageView.image else { return }

        var frameToCentre = imageView.frame

        let imageWidth = image.size.width
        let imageHeight = image.size.height

        let widthRatio = superview.bounds.size.width / imageWidth
        let heightRatio = superview.bounds.size.height / imageHeight

        let minRatio = min(widthRatio, heightRatio, 1.0)

        let effectiveImageWidth = minRatio * imageWidth * zoomScale
        let effectiveImageHeight = minRatio * imageHeight * zoomScale

        contentSize = CGSize(width: max(effectiveImageWidth, bounds.size.width), height: max(effectiveImageHeight, bounds.size.height))

        frameToCentre.origin.x = (contentSize.width - frameToCentre.size.width) / 2
        frameToCentre.origin.y = (contentSize.height - frameToCentre.size.height) / 2

        imageView.frame = frameToCentre
    }
}
Απαντήθηκε 05/05/2016 στις 09:56
πηγή χρήστη

ψήφοι
0

Σε MonoTouch που λειτούργησε για μένα.

this._scroll.ScrollRectToVisible(new RectangleF(_scroll.ContentSize.Width/2, _scroll.ContentSize.Height/2,1,1),false);
Απαντήθηκε 08/08/2012 στις 15:45
πηγή χρήστη

ψήφοι
0

Ένας κομψός τρόπος για να κεντράρετε το περιεχόμενο UISCrollViewείναι αυτό.

Προσθέστε έναν παρατηρητή στο contentSize του σας UIScrollView, έτσι ώστε αυτή η μέθοδος θα καλείται κάθε φορά η αλλαγή του περιεχομένου ...

[myScrollView addObserver:delegate 
               forKeyPath:@"contentSize"
                  options:(NSKeyValueObservingOptionNew) 
                  context:NULL];

Τώρα, με τη μέθοδο του παρατηρητή σας:

- (void)observeValueForKeyPath:(NSString *)keyPath   ofObject:(id)object   change:(NSDictionary *)change   context:(void *)context { 

    // Correct Object Class.
    UIScrollView *pointer = object;

    // Calculate Center.
    CGFloat topCorrect = ([pointer bounds].size.height - [pointer viewWithTag:100].bounds.size.height * [pointer zoomScale])  / 2.0 ;
            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );

    topCorrect = topCorrect - (  pointer.frame.origin.y - imageGallery.frame.origin.y );

    // Apply Correct Center.
    pointer.center = CGPointMake(pointer.center.x,
                                 pointer.center.y + topCorrect ); }
  • Θα πρέπει να αλλάξετε το [pointer viewWithTag:100]. Αντικαταστήστε από την άποψη του περιεχομένου σας UIView.

    • Επίσης αλλάζουν imageGalleryδείχνοντας το μέγεθος του παραθύρου σας.

Αυτό θα διορθώσει το κέντρο του κάθε φορά το περιεχόμενο της αλλαγής του μεγέθους του.

ΣΗΜΕΙΩΣΗ: Ο μόνος τρόπος για αυτό το περιεχόμενο δεν λειτουργεί πολύ καλά είναι με το πρότυπο λειτουργικότητα ζουμ του UIScrollView.

Απαντήθηκε 03/11/2009 στις 18:14
πηγή χρήστη

ψήφοι
0

Εντάξει, νομίζω ότι έχω βρει μια πολύ καλή λύση σε αυτό το πρόβλημα. Το κόλπο είναι να αναπροσαρμόσουμε συνεχώς το πλαίσιο του ImageView του. Θεωρώ ότι αυτό λειτουργεί πολύ καλύτερα από ό, τι την συνεχή προσαρμογή των contentInsets ή contentOffSets. Έπρεπε να προσθέσετε λίγη επιπλέον κώδικα για να φιλοξενήσει τις δύο εικόνες πορτρέτο και το τοπίο.

Εδώ είναι ο κώδικας:

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {

CGSize screenSize = [[self view] bounds].size;

if (myScrollView.zoomScale <= initialZoom +0.01) //This resolves a problem with the code not working correctly when zooming all the way out.
{
    imageView.frame = [[self view] bounds];
    [myScrollView setZoomScale:myScrollView.zoomScale +0.01];
}

if (myScrollView.zoomScale > initialZoom)
{
    if (CGImageGetWidth(temporaryImage.CGImage) > CGImageGetHeight(temporaryImage.CGImage)) //If the image is wider than tall, do the following...
    {
            if (screenSize.height >= CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is greater than the zoomed height of the image do the following...
            {
                    imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), 368);
            }
            if (screenSize.height < CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is less than the zoomed height of the image do the following...
            {
                    imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]);
            }
    }
    if (CGImageGetWidth(temporaryImage.CGImage) < CGImageGetHeight(temporaryImage.CGImage)) //If the image is taller than wide, do the following...
    {
            CGFloat portraitHeight;
            if (CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale] < 368)
            { portraitHeight = 368;}
            else {portraitHeight = CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale];}

            if (screenSize.width >= CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is greater than the zoomed width of the image do the following...
            {
                    imageView.frame = CGRectMake(0, 0, 320, portraitHeight);
            }
            if (screenSize.width < CGImageGetWidth (temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is less than the zoomed width of the image do the following...
            {
                    imageView.frame = CGRectMake(0, 0, CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale], portraitHeight);
            }
    }
    [myScrollView setZoomScale:myScrollView.zoomScale -0.01];
}
Απαντήθηκε 04/10/2009 στις 03:16
πηγή χρήστη

ψήφοι
0

Σημείωση: αυτή τη μέθοδο ταξινόμησης των έργων. αν η εικόνα είναι μικρότερο από το ImageView, θα μετακινηθείτε εν μέρει από την οθόνη. Δεν είναι μια μεγάλη υπόθεση, αλλά δεν είναι τόσο ωραίο όσο το app φωτογραφίες.

Κατ 'αρχάς, είναι σημαντικό να καταλάβουμε ότι έχουμε να κάνουμε με 2 εμφανίσεις, την ImageView με την εικόνα σε αυτό, και το scrollview με την ImageView σε αυτό. Έτσι, πρώτα να ορίσετε το ImageView στο μέγεθος της οθόνης:

 [myImageView setFrame:self.view.frame];

Στη συνέχεια, το κέντρο της εικόνας σας στο ImageView:

 myImageView.contentMode = UIViewContentModeCenter;

Εδώ είναι ολόκληρο το κωδικό μου:

- (void)viewDidLoad {
AppDelegate *appDelegate = (pAppDelegate *)[[UIApplication sharedApplication] delegate];
 [super viewDidLoad];
 NSString *Path = [[NSBundle mainBundle] bundlePath];
 NSString *ImagePath = [Path stringByAppendingPathComponent:(@"data: %@", appDelegate.MainImageName)];
 UIImage *tempImg = [[UIImage alloc] initWithContentsOfFile:ImagePath];
 [imgView setImage:tempImg];

 myScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
 [myScrollView addSubview:myImageView];

//Set ScrollView Appearance
 [myScrollView setBackgroundColor:[UIColor blackColor]];
 myScrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;

//Set Scrolling Prefs
 myScrollView.bounces = YES;
 myScrollView.delegate = self;
 myScrollView.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
 [myScrollView setCanCancelContentTouches:NO];
 [myScrollView setScrollEnabled:YES];


//Set Zooming Prefs
 myScrollView.maximumZoomScale = 3.0;
 myScrollView.minimumZoomScale = CGImageGetWidth(tempImg.CGImage)/320;
 myScrollView.zoomScale = 1.01; //Added the .01 to enable scrolling immediately upon view load.
 myScrollView.bouncesZoom = YES;


 [myImageView setFrame:self.view.frame];//rect];// .frame.size.height = imageHeight;
 myImageView.contentMode = UIViewContentModeCenter;
 self.view = myScrollView;
 [tempImg release];
 }
Απαντήθηκε 08/09/2009 στις 03:14
πηγή χρήστη

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