iPhone - يبدأ UIScrollView بملء الشاشة بشكل صحيح ولكن إعادة تحديد المواطن نفسه أسفل شريط التنقل

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

سؤال

أحاول حاليًا تطبيق منتقي صور تمامًا مثل تطبيق الصور ولكن مع مصدر صورة مخصص. بالنسبة لجزء "تمرير الصور" ، استخدمت رمز Apple Photoscroller وتكييفه. أحد الاختلافات الرئيسية هو أنه مدمج الآن في وحدة تحكم التنقل (Wich هو وحدة تحكم NAV الخاصة بالتصوير ، وليس تطبيق التطبيق) ، مع شريط التنقل. لديّ حالة وشريط التنقل الشفاف وقمت بتعيين wantsfullScreenLayout = نعم على جميع وحدة تحكم العرض المستخدمة في The PhotoPicker. يبدو أنه يعمل بشكل جيد تقريبًا. إن عرض "نظرة عامة" (الرحمة التي تعرض الصور المصغرة لجميع صور الألبوم) هي بالفعل شاشة ملء ، ويجب أن أقدرها يدويًا بحيث يتم عرض الصورة المصغرة تحت شريط التنقل في البداية. بالنسبة للجزء التمرير ولكن هناك خلل. بالنسبة لأولئك الذين لا يعرفون رمز صور Photoscroller ، فإنه يعمل مع UiviewController مخصص (PhotoViewController) مع سمة UisCrollView (PagingScrollView) ، ومجموعة من uiscrollview مخصص (PictureCrollView) مع uiView و index nsinteger. ثم تتم إضافة/إزالة مثيلات PicturalCrollView كآراء فرعية لـ Photoscroller.

فيما يلي بعض التعليمات البرمجية ذات الصلة:

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) بكسل (ارتفاع شريط الحالة + Nav Bar الذي أفترضه) عندما أقوم أولاً بتحميل مثيل PhotoViewController. ينتج عن هذا واجهة عابرة يظهر فيها صور CrollView أسفل شريط NAV (Origin (0 ، 0)) ويمكن بعد ذلك التمرير لأعلى ولأسفل حتى عندما يكون ارتفاعه أصغر من الشاشة.

مع بعض السجلات ونقاط التوقف ، تمكنت من تحديد أن حدود PagingScrollView جيدة في بداية عملية التحميل. يتغيرون عندما أقوم بتقييم صورة الصور CrollView لتناسب الشاشة. هذا يتسبب في ViewForzoomingInscrollView ثم طرق ScrollViewDidsCroll التي سيتم استدعاؤها. يتم تعويض Pagingscrollview خلال تلك المكالمات.

حاولت ضبط الإزاحة يدويًا ، لكن عندما أفعل ذلك في المعالجة ، لم يعد بإمكان Scrollview الارتداد لأعلى ولأسفل ...

سيكون موضع تقدير أي مساعدة !

هتافات

PB

هل كانت مفيدة؟

المحلول

Three20 لديه تطبيق لطيف حقا لها. إذا كنت بحاجة إلى أي ميزة فاخرة ، فهي تتكيف مع الكود فقط لضرورة خاصة بك.

كل العمل الشاق قد تم بالفعل. على الرغم من أنك إذا كنت لا تزال ترغب في تنفيذ نسختك الخاصة ، إلا أن إلقاء نظرة على ثلاثة رمز على الأقل وتحقق من كيفية قيامهم بما تحاول تحقيقه.

كيف يبدو: http://farm4.static.flickr.com/3432/3378117315_3bf905bdb6_o.jpg

مصدر الرمز: http://github.com/facebook/three20

نصائح أخرى

في حالتك الخاصة (أي PhotoViewController يتم دفعها إلى أ UINavigationController مكدس) - أشرطة التنقل أضف أ contentInset إلى PhotoViewControllerعرض التمرير. هذا كله موضح بشكل أفضل هنا و هنا.

هذا هو ، PhotoViewController لا تتناسب View بإحكام مع حدود نافذتك ، وبالتالي ، لديها مساحة يجب تمريرها في جميع الاتجاهات.

لقد وجدت حللين محتملين لمشكلتك.

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;

    // ...
}

أتمنى أن يساعدك هذا!

الأشياء الرئيسية التي يجب تعيينها هي ما يلي في وحدة التحكم في العرض. استخدم أعلام التلقائي على طرق عرض المحتوى الخاصة بك. سيؤدي تمكين الأعلام التالية إلى توسيع حجم وحدة تحكم العرض الخاصة بك إلى الحجم الكامل للشاشة. أقوم بتنفيذ ما يلي في 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/tp4001131313

إذا كنت تقوم بأشياء لتعيين حدود الإطار على طريقة عرض المحتوى ، فسوف أزيل كل هذا الرمز لأن ما سبق يجب أن يعتني به لك.

فقط قم بتعيين إدراج View View Adjust Scroll من View Controller إلى False من القصة المصورة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top