Frage

Ich versuche zur Zeit einen Foto-Picker genau wie das Foto-App zu implementieren, aber mit einer benutzerdefinierten Bildquelle. Für die „Foto-Scrolling“ Teil benutzte ich den Beispielcode von Apple PhotoScroller und angepasst es. Einer des Hauptunterschied ist, dass es jetzt in einer Navigationssteuerung eingebettet ist (Weicht den photoPicker eigenen nav-Controller ist, nicht die Anwendung), mit einer Navigationsleiste. Ich habe den Status und die Navigationsleiste durchscheinend und ich habe eingestellt wantsFullScreenLayout = YES auf all View-Controller in dem photoPicker verwendet. Es scheint fast zu funktionieren. Die „Übersicht“ -Ansicht (derjenige, der zeigt Miniaturansichten aller Fotos des Albums) ist in der Tat größer anzeigen, und ich habe es zum Ausgleich manuell so die Thumbnails sind unter der Navigationsleiste auf dem ersten angezeigt. Für das Scrollen Teil ist jedoch eine Panne. Für diejenigen, die nicht über die photoScroller Beispielcode kennen, funktioniert es mit einem benutzerdefinierten UIViewController (PhotoViewController) mit einem UIScrollView Attribut (pagingScrollView) und eine Reihe von benutzerdefinierten UIScrollView (ImageScrollView) mit einem UIView und ein NSInteger Index Attribute. Die ImageScrollView Instanzen werden dann als Subviews des PhotoScroller hinzugefügt / entfernt.

Im Folgenden finden Sie einig zugehöriger Code:

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
}

Mein Problem ist, dass der pagingScrollView auf einen Ursprung des Versatzes wird (0, -64) Pixel (Höhe der Statusleiste + nav bar nehme ich an), wenn ich zuerst die PhotoViewController Instanz laden. Dies führt zu einer verkorksten Oberfläche, in der die ImageScrollView unterhalb der Navigationsleiste angezeigt wird (Ursprung (0, 0)) und kann dann nach oben gescrollt wird und nach unten, auch wenn seine Höhe kleiner als der Bildschirm ist.

Bei einigen Protokollen und Haltepunkten konnte ich feststellen, dass die pagingScrollView Grenzen sind in Ordnung zu Beginn des Ladevorganges. Sie ändern, wenn ich das Bild des ImageScrollView skaliert auf den Bildschirm passen. Dies bewirkt, dass die viewForZoomingInScrollView und dann die scrollViewDidScroll Methoden aufgerufen werden. Die pagingScrollView wird während dieser Anrufe versetzt sind.

Ich habe versucht, die manuell Offset-Einstellung, aber wenn ich es in processPages tun kann die Scrollview nicht mehr hüpfen auf und ab ...

Jede Hilfe wird geschätzt!

Prost

PB

War es hilfreich?

Lösung

hat Three20 eine wirklich schöne Umsetzung davon. Wenn Sie irgendeine Phantasie-Funktion benötigen, ist es nur den Code für Ihre eigene Notwendigkeit anzupassen.

Die ganze harte Arbeit ist bereits getan. Obwohl, wenn Sie wollen immer noch Ihre eigene Version implementieren, zumindest einen Blick auf Three20 Code und überprüft, wie sie das tun, was Sie erreichen wollen.

Wie es aussieht: http://farm4.static.flickr.com/ 3432 / 3378117315_3bf905bdb6_o.jpg

Der Quellcode: http://github.com/facebook/three20

Andere Tipps

In Ihrem speziellen Fall (das heißt die PhotoViewController auf einen UINavigationController Stapel geschoben) - Navigationsleisten hinzufügen contentInset zu PhotoViewController der Ansicht blättern. Das ist alles besser erklärt hier und hier .

Das heißt, die PhotoViewController Ansicht paßt nicht fest an Ihrem Fenstergrenzen und somit hat Raum in alle Richtungen gescrollt werden.

Ich fand 2 mögliche Lösungen für Ihr Problem.

1 - Sie müssen manuell den contentInset Ihrer pagingScrollView einzustellen, um die Höhe der Navigationsleiste und die Statusleiste zu kompensieren. Fügen Sie diese auf 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);
}

oder

2 - Da nur Scroll-Ansichten, die eine contentInset haben, wickeln Sie das pagingScrollView in einer Ebene UIView:

- (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;

    // ...
}

Hope, das hilft!

Die wichtigsten Dinge, die eingestellt werden müssen, sind die folgenden in Ihrem View-Controller. Verwenden Sie AUTORESIZE Flaggen auf Ihre Inhalte Ansichten. Aktivieren der folgenden Flags wird die Größe Ihrer View-Controller auf die volle Größe des Bildschirms erweitern. Ich führe die folgende 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.
}

Weitere Informationen finden Sie hier in docs Apfel zu finden:

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

Wenn Sie die Dinge Satz Rahmen Schranken für den Inhalt Ansicht getan haben, würde ich das alles Code entfernen, da die oben sollte für Sie darum kümmern.

Just stellen Sie die Adjust Scroll Ansicht Einfügungen der View-Controller auf false aus Storyboard.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top