IPhone - полноэкранный экран UIScrollview начинается правильно, но редактирования сама ниже навигационной панели

StackOverflow https://stackoverflow.com/questions/3716620

Вопрос

В настоящее время я пытаюсь внедрить сборщик фотографий, как приложение Photo, но с пользовательским источником изображения. Для детали «Photo Scrolling» я использовал код образца Photoscrolleer Apple и адаптировал его. Одним из главных отличий состоит в том, что он в настоящее время встроен в навигационный контроллер (Wich - это Photopicker Nav Controller, а не один приложение), с навигационной панелью. У меня есть статус и навигационный бар полупрозрачный, и я установил HonefullScreenLayout = yes на весь контроллер просмотра, используемый в фотопаке. Кажется, он работает почти нормально. «Обзор» View (тот, который отображает миниатюры всех фотографий альбома), действительно полно экрана, и мне нужно компенсировать его вручную, поэтому миниатюры отображаются под панелью навигации. Для прокрутки, однако, есть глюк. Для тех, кто не знает код примерного кода Photoscroller, он работает с пользовательским UIViewController (PhotoviewController) с атрибутом uiscrollview (pagingscrollview) и набором пользовательского uiscrollview (zamzcrollview) с uiview и атрибутами индекса nsinteger. Затем добавляются экземпляры ConcreenceCrollView / удалены в виде субпроизводства фотосбролле.

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

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) пикселей (высота строки состояния + навигационная панель, которую я полагаю), когда я сначала загружаю экземпляр фотовивного контроля. Это приводит к интерфейсу запутанного интерфейса, в котором zamescrollview отображается под панелью NAV (начальника (0, 0)) и может затем прокручивать вверх и вниз, даже если его высота меньше, чем экран.

С некоторыми журналами и точками останова я смог определить, что границы PagingsCrollView в начале процесса загрузки. Они меняются, когда я масштабирую изображение изображений ConcrollView, чтобы соответствовать экрану. Это заставляет ViewForzoomingInsinsCrollView, а затем методы ScrollViewDIDScroll. PagingsCrollView компенсируется во время этих звонков.

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

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

Ваше здоровье

Преступник

Это было полезно?

Решение

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

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

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

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

Другие советы

В вашем конкретном случае (то есть PhotoViewController Быть толкнутым на UINavigationController Стек) - навигационные полосы добавляют contentInset к PhotoViewControllerпрокрутки прокрутки. Это все лучше объяснить здесь а также здесь.

Это 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;

    // ...
}

Надеюсь это поможет!

Основные вещи, которые необходимо установить, являются следующими в вашем контроллере просмотра. Используйте флаги AutoRoseize на ваших представлениях контента. Включение следующих флагов расширит размер контроллера вашего представления на полный размер экрана. Я выполняю следующее в 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/coneptual/viewcontrollerCatalog/chapters/navigationControllers.html#//apple_ref/doc/uid/tp40011313-Ch2.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top