Domanda

Attualmente sto cercando di attuare una foto raccoglitrice proprio come il Photo App, ma con una fonte di un'immagine personalizzata. Per la "foto scrolling" parte ho usato il codice di esempio di Apple PhotoScroller e adattato esso. Una delle differenze principali è che è ora incorporato in un controller di navigazione (goduto è il controller proprio nav photoPicker, non uno dell'applicazione), con una barra di navigazione. Ho lo stato e la barra di navigazione traslucida e ho impostato wantsFullScreenLayout = YES su tutto il controller della vista utilizzata nel photoPicker. Sembra funzionare quasi bene. Il punto di vista "Overview" (quello che visualizza le miniature di tutte le foto dell'album) è infatti a schermo intero, e ho così le anteprime sono visualizzate sotto la barra di navigazione in un primo momento per compensare manualmente. Per la parte di scorrimento tuttavia c'è un problema tecnico. Per coloro che non conoscono il codice di esempio photoScroller, funziona con un costume UIViewController (PhotoViewController) con un attributo UIScrollView (pagingScrollView), e una serie di costume UIScrollView (ImageScrollView) con un UIView e un indice attributi NSInteger. vengono quindi aggiunti i casi ImageScrollView / rimossi come subviews del PhotoScroller.

Di seguito è riportato un codice correlato:

PhotoViewController.h

@interface PhotoViewController : UIViewController <UIScrollViewDelegate> {
    UIScrollView *pagingScrollView;

    NSMutableSet *recycledPages;
    NSMutableSet *visiblePages;

    IBOutlet UIToolbar *toolbar;
    IBOutlet UIBarButtonItem *previousButtonItem;
    IBOutlet UIBarButtonItem *nextButtonItem;

    id<PhotoViewDataSource> dataSource;
}

@property(nonatomic, retain) UIScrollView *pagingScrollView;
@property(nonatomic, retain) NSMutableSet *recylcledPages;
@property(nonatomic, retain) NSMutableSet *visiblePages;

@property(nonatomic, retain) UIToolbar *toolbar;
@property(nonatomic, retain) UIBarButtonItem *previousButtonItem;
@property(nonatomic, retain) UIBarButtonItem *nextButtonItem;

@property(nonatomic, retain) id<PhotoViewDataSource> dataSource;

PhotoViewController.m

- (void)loadView 
{
    self.wantsFullScreenLayout = YES;

    // Configure the scrollView
    CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
    pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
    pagingScrollView.pagingEnabled = YES;
    pagingScrollView.backgroundColor = [UIColor redColor];
    pagingScrollView.showsVerticalScrollIndicator = NO;
    pagingScrollView.showsHorizontalScrollIndicator = NO;
    pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [self.dataSource imageCount],
                                              pagingScrollViewFrame.size.height);
    //pagingScrollView.contentOffset = CGPointMake(0, 0);

    pagingScrollView.delegate = self;
    self.view = pagingScrollView;

    // TODO ? Prepare to tile content
    recycledPages = [[NSMutableSet alloc] init];
    visiblePages  = [[NSMutableSet alloc] init];
    [self processPages];
}


- (void)processPages {

    // Calculate which pages are visible
    CGRect visibleBounds = pagingScrollView.bounds;
    NSLog(@"PhotoViewController - processPages : frame = %@", NSStringFromCGRect(pagingScrollView.frame));
    NSLog(@"pagingScrollView bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
    NSLog(@"and contentSize = %@", NSStringFromCGSize(pagingScrollView.contentSize));

    int firstNeededPageIndex = floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds));
    int lastNeededPageIndex  = floorf((CGRectGetMaxX(visibleBounds)-1) / CGRectGetWidth(visibleBounds));
    firstNeededPageIndex = MAX(firstNeededPageIndex, 0);
    lastNeededPageIndex  = MIN(lastNeededPageIndex, [dataSource imageCount] - 1);

    if (lastNeededPageIndex >= 0) {

        // Recycle no-longer-visible pages 
        for (ImageScrollView *page in visiblePages) {
            if (page.index < firstNeededPageIndex || page.index > lastNeededPageIndex) {
                [recycledPages addObject:page];
                [page removeFromSuperview];
            }
        }
        [visiblePages minusSet:recycledPages];

        // add missing pages
        for (int index = firstNeededPageIndex; index <= lastNeededPageIndex; index++) {
            if (![self isDisplayingPageForIndex:index]) {
                ImageScrollView *page = [self dequeueRecycledPage];
                if (page == nil) {
                    page = [[[ImageScrollView alloc] init] autorelease];
                }
                [self configurePage:page forIndex:index];
                NSLog(@"PhotoViewController - processPage 2 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
                [pagingScrollView addSubview:page];
                NSLog(@"PhotoViewController - processPage 3 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
                [visiblePages addObject:page];
            }
        }
    }
}

- (ImageScrollView *)dequeueRecycledPage {
    ImageScrollView *page = [recycledPages anyObject];
    if (page) {
        [[page retain] autorelease];
        [recycledPages removeObject:page];
    }
    return page;
}

- (BOOL)isDisplayingPageForIndex:(NSUInteger)index {
    BOOL foundPage = NO;
    for (ImageScrollView *page in visiblePages) {
        if (page.index == index) {
            foundPage = YES;
            break;
        }
    }
    return foundPage;
}

- (void)configurePage:(ImageScrollView *)page forIndex:(NSUInteger)index {
    page.index = index;
    page.frame = [self frameForPageAtIndex:index];

    NSLog(@"PhotoViewController - configurePage : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));

    [page displayImage:[dataSource imageForImageId:index]];

    NSLog(@"PhotoViewController - configurePage 2 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
}


#pragma mark -
#pragma mark ScrollView delegate methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self processPages];
}


#pragma mark -
#pragma mark  Frame calculations
#define PADDING  10

- (CGRect)frameForPagingScrollView {
    CGRect frame = [[UIScreen mainScreen] bounds];
    frame.origin.x -= PADDING;
    frame.size.width += (2*PADDING);
    return frame;
}

- (CGRect)frameForPageAtIndex:(NSUInteger)index {
    CGRect pagingScrollViewFrame = [self frameForPagingScrollView];

    CGRect pageFrame = pagingScrollViewFrame;
    pageFrame.size.width -= (2 * PADDING);
    pageFrame.origin.x = (pagingScrollViewFrame.size.width * index) + PADDING;
    //pageFrame.origin.x = (pagingScrollViewFrame.size.width * index) - (PADDING*index*2);
    return pageFrame;
}

ImageScrollView.h

@interface ImageScrollView : UIScrollView <UIScrollViewDelegate> {
    UIView        *imageView;
    NSUInteger     index;
}
@property (assign) NSUInteger index;

- (void)displayImage:(UIImage *)image;
//- (void)displayTiledImageNamed:(NSString *)imageName size:(CGSize)imageSize;
- (void)configureForImageSize:(CGSize)imageSize;

ImageScrollView.m

- (void)layoutSubviews 
{
    [super layoutSubviews];

    imageView.backgroundColor = [UIColor greenColor];
    self.backgroundColor = [UIColor blueColor];

    // center the image as it becomes smaller than the size of the screen

    CGSize boundsSize = self.bounds.size;
    CGRect frameToCenter = imageView.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;

    imageView.frame = frameToCenter;
    NSLog(@"imageView frame = %@", NSStringFromCGRect(frameToCenter));

    if ([imageView isKindOfClass:[TilingView class]]) {
        // to handle the interaction between CATiledLayer and high resolution screens, we need to manually set the
        // tiling view's contentScaleFactor to 1.0. (If we omitted this, it would be 2.0 on high resolution screens,
        // which would cause the CATiledLayer to ask us for tiles of the wrong scales.)
        imageView.contentScaleFactor = 1.0;
    }
}

#pragma mark -
#pragma mark UIScrollView delegate methods

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

#pragma mark -
#pragma mark Configure scrollView to display new image (tiled or not)

- (void)displayImage:(UIImage *)image
{
    // clear the previous imageView
    [imageView removeFromSuperview];
    [imageView release];
    imageView = nil;

    // reset our zoomScale to 1.0 before doing any further calculations
    self.zoomScale = 1.0;

    // make a new UIImageView for the new image
    imageView = [[UIImageView alloc] initWithImage:image];
    [self addSubview:imageView];

    [self configureForImageSize:[image size]];
}

- (void)configureForImageSize:(CGSize)imageSize 
{
    CGSize boundsSize = [self bounds].size;

    // set up our content size and min/max zoomscale
    CGFloat xScale = boundsSize.width / imageSize.width;    // the scale needed to perfectly fit the image width-wise
    CGFloat yScale = boundsSize.height / imageSize.height;  // the scale needed to perfectly fit the image height-wise
    CGFloat minScale = MIN(xScale, yScale);                 // use minimum of these to allow the image to become fully visible

    // on high resolution screens we have double the pixel density, so we will be seeing every pixel if we limit the
    // maximum zoom scale to 0.5.
    CGFloat maxScale = /*1.0 / */[[UIScreen mainScreen] scale];

    // don't let minScale exceed maxScale. (If the image is smaller than the screen, we don't want to force it to be zoomed.) 
    if (minScale > maxScale) {
        minScale = maxScale;
    }

    self.contentSize = imageSize;
    self.maximumZoomScale = maxScale;
    self.minimumZoomScale = minScale;
    self.zoomScale = minScale;  // start out with the content fully visible
}

Il mio problema è che il pagingScrollView viene compensato ad un'origine di (0, -64) pixel (altezza della barra di stato + barra di navigazione suppongo), quando ho primo carico l'istanza PhotoViewController. Ciò comporta un'interfaccia incasinata in cui l'ImageScrollView appare sotto la barra di navigazione (origine (0, 0)) e può quindi essere fatta scorrere su e giù anche quando la sua altezza è minore della schermata.

Con alcuni tronchi e punti di interruzione sono stato in grado di determinare che i limiti pagingScrollView vanno bene all'inizio del processo di caricamento. Essi cambiano quando mi scala l'immagine del ImageScrollView per adattarsi allo schermo. Questo fa sì che il viewForZoomingInScrollView e poi i metodi scrollViewDidScroll da chiamare. Il pagingScrollView viene compensato durante le chiamate.

ho provato lo spostamento del punto manualmente, ma quando lo faccio nel processPages la ScrollView non può rimbalzare su e giù ...

Ogni aiuto sarà apprezzato!

Saluti

PB

È stato utile?

Soluzione

Three20 ha una bella realizzazione di esso. Se avete bisogno di qualsiasi funzione di fantasia, è adatta solo il codice per la propria necessità.

Tutto il duro lavoro è già fatto. Anche se ancora desidera implementare la propria versione, almeno dare un'occhiata al codice Three20 e controllare il modo in cui fare quello che stai cercando di raggiungere.

Come appare come: http://farm4.static.flickr.com/ 3432 / 3378117315_3bf905bdb6_o.jpg

Codice sorgente: http://github.com/facebook/three20

Altri suggerimenti

Nel vostro caso particolare (vale a dire la PhotoViewController essere spinto su una pila UINavigationController) - barre di navigazione aggiungere un contentInset alla vista di scorrimento di PhotoViewController. Tutto questo è meglio spiegato qui e qui .

Questa è, la vista PhotoViewController non si adatta perfettamente ai vostri limiti della finestra e, quindi, ha spazio da scorrere in tutte le direzioni.

Ho trovato 2 possibili soluzioni al problema.

1 - È necessario regolare manualmente la contentInset del pagingScrollView per compensare l'altezza della barra di navigazione e la barra di stato. Aggiungi questo a PhotoViewController:

- (void)viewDidLoad {
    [super viewDidLoad];

    CGFloat topOffset = self.navigationController.navigationBar.frame.size.height + [[UIApplication sharedApplication] statusBarFrame].size.height;
    pagingScrollView.contentInset = UIEdgeInsetsMake(-topOffset, 0.0, 0.0, 0.0);
}

o

2 - Dal momento che solo una vista di scorrimento hanno una contentInset, avvolgere il pagingScrollView in un UIView pianura:

- (void)loadView {    
    [self setWantsFullScreenLayout:YES];

    CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
    photoView = [[UIView alloc] initWithFrame:pagingScrollViewFrame];
    pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];

    // ... configure the pagingScrollView

    [photoView addSubview:pagingScrollView];
    self.view = photoView;

    // ...
}

Spero che questo aiuti!

Le cose principali che devono essere insieme sono i seguenti nel vostro controller della vista. Utilizzare AutoResize bandiere sui vostri punti di vista dei contenuti. L'attivazione i seguenti flag amplierà le dimensioni del vostro controller della vista fino alla dimensione dello schermo. Eseguo quanto segue in viewWillAppear.

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    [self setWantsFullScreenLayout:YES]; // if you want to underlap status
    self.navigationController.navigationBar.translucent = YES; // underlap nav controller
    self.toolbar.translucent = YES; // if you have a toolbar.
}

maggiori dettagli si possono trovare qui nei documenti di Apple:

http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html#//apple_ref/doc/uid/TP40011313-CH2

Se avete fatto le cose per impostare i limiti del telaio sulla vista dei contenuti che eliminerebbe tutto ciò che il codice perché quanto sopra dovrebbe prendersi cura di esso per voi.

Basta impostare il Regola Scorrere Guarda inserti di controller della vista su false da storyboard.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top