2010-09-15 5 views
4

В настоящее время я пытаюсь реализовать сборщик фотографий, как и приложение для фотографий, но с настраиваемым источником изображения. Для части «прокрутки фотографий» я использовал образец кода Apple PhotoScroller и адаптировал его. Одно из главных отличий заключается в том, что он теперь встроен в контроллер навигации (который является собственным навигационным контроллером photoPicker, а не одним из приложений), с навигационной панелью. У меня есть статус и панель навигации полупрозрачная, и я установил wantFullScreenLayout = YES на всем контроллере представления, используемом в photoPicker. Кажется, он работает почти нормально. «Обзор» (тот, который отображает миниатюры всех фотографий альбома) действительно полноэкранный, и мне приходится смещать его вручную, чтобы миниатюры сначала отображались под навигационной панелью. Для прокручиваемой части, однако, есть сбой. Для тех, кто не знает пример кода photoScroller, он работает с пользовательским UIViewController (PhotoViewController) с атрибутом UIScrollView (pagingScrollView) и набором пользовательских UIScrollView (ImageScrollView) с атрибутами индекса UIView и NSInteger. Затем экземпляры ImageScrollView добавляются/удаляются в виде подсмотров PhotoScroller.IPhone - полноэкранный UIScrollView запускается вправо, но репозиционирует себя под навигационной панелью

Ниже некоторые из них связаны код:

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 
} 

Моя проблема заключается в том, что pagingScrollView будет смещена к происхождения (0, -64) пикселей (высота строки состояния + навигационный бар, я полагаю), когда я первый загрузить экземпляр PhotoViewController. Это приводит к испорченному интерфейсу, в котором ImageScrollView появляется под навигационной панелью (начало (0, 0)), а затем может прокручиваться вверх и вниз, даже когда его высота меньше экрана.

С некоторыми журналами и точками останова я смог определить, что границы pagingScrollView хороши в начале процесса загрузки. Они меняются, когда я масштабирую изображение ImageScrollView, чтобы соответствовать экрану. Это вызывает viewForZoomingInScrollView, а затем вызовы методов scrollViewDidScroll. Во время этих вызовов pagingScrollView смещается.

Я попытался установить смещение вручную, но когда я делаю это в processPages Scrollview больше не может подпрыгивать вверх и вниз ...

Любая помощь будет оценен по достоинству!

Приветствия

PB

ответ

-2

Three20 имеет очень хорошую реализацию этого. Если вам нужна какая-нибудь причудливая функция, она только адаптирует код для вашей собственной необходимости.

Вся тяжелая работа уже выполнена. Хотя, если вы все еще хотите реализовать свою версию, по крайней мере, посмотрите на код Three20 и проверьте, как они делают то, что вы пытаетесь достичь.

Как это выглядит: http://farm4.static.flickr.com/3432/3378117315_3bf905bdb6_o.jpg

Исходный код: http://github.com/facebook/three20

+0

Thx, я попробую это как можно скорее –

+0

Wonderfull library, THX для показа мне! –

+0

Three20 на самом деле не является решением для этого, если вы только хотите выполнить этот экран. Это не так настраиваемо, как если бы вы сами это сделали, и вам нужно включить HUGE-библиотеку только для этого ... –

6

В вашем конкретном случае (т.е. PhotoViewController толкает на UINavigationController стеков) - панель навигации добавить contentInset к PhotoViewController «s вида прокрутки. Все это лучше объяснено here и here.

То есть, вид PhotoViewController не подходит к вашим окнам и, следовательно, имеет место для прокрутки во всех направлениях.

Я нашел 2 возможных решения вашей проблемы.

1 - Вам необходимо вручную настроить contentInset вашего pagingScrollView, чтобы компенсировать высоту панели навигации и строки состояния. Добавьте к этому 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); 
} 

ИЛИ

2 - Поскольку только прокручивать виды имеют contentInset, оберните pagingScrollView в простом 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; 

    // ... 
} 

Надеется, что это помогает!

+0

Thx, это было более или менее то, что я пытался сделать, но не знал правильный путь. Тем не менее, я не тестировал его, я переключился на приложение Three20, которое мне точно было нужно, и больше :) –

0

Основные функции, которые необходимо установить, следующие в вашем контроллере. Используйте флаги автосохранения в своих представлениях контента. Включение следующих флагов позволит увеличить размер вашего контроллера просмотра до полного размера экрана. Я выполняю следующее в 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. 
} 

Более подробную информацию можно найти здесь в документации Apple:

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

если вы делаете вещи, чтобы установить кадр оценки на представлении содержимого Я хотел бы удалить весь код, потому что выше должен позаботьтесь о нем для вас.

0

Просто установите в настройках Scroll View вставки контроллера просмотра в false из раскадровки.