Центральное содержимое UIScrollView при меньшем

У меня есть UIImageView внутри UIScrollView который я использую для масштабирования и прокрутки. Если изображение/содержимое представления прокрутки больше, чем представление прокрутки, все работает нормально. Однако когда изображение становится меньше, чем представление с прокруткой, оно прикрепляется к верхнему левому углу представления с прокруткой. Я бы хотел, чтобы он был в центре, как приложение "Фотографии".

Какие-нибудь идеи или примеры о том, как держать содержимое UIScrollView центру, когда оно меньше?

Я работаю с iPhone 3.0.

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

- (void)loadView {
    [super loadView];

    // set up main scroll view
    imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
    [imageScrollView setBackgroundColor:[UIColor blackColor]];
    [imageScrollView setDelegate:self];
    [imageScrollView setBouncesZoom:YES];
    [[self view] addSubview:imageScrollView];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"WeCanDoIt.png"]];
    [imageView setTag:ZOOM_VIEW_TAG];
    [imageScrollView setContentSize:[imageView frame].size];
    [imageScrollView addSubview:imageView];

    CGSize imageSize = imageView.image.size;
    [imageView release];

    CGSize maxSize = imageScrollView.frame.size;
    CGFloat widthRatio = maxSize.width / imageSize.width;
    CGFloat heightRatio = maxSize.height / imageSize.height;
    CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;

    [imageScrollView setMinimumZoomScale:initialZoom];
    [imageScrollView setZoomScale:1];

    float topInset = (maxSize.height - imageSize.height) / 2.0;
    float sideInset = (maxSize.width - imageSize.width) / 2.0;
    if (topInset < 0.0) topInset = 0.0;
    if (sideInset < 0.0) sideInset = 0.0;
    [imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}

/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary      */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    [scrollView setZoomScale:scale+0.01 animated:NO];
    [scrollView setZoomScale:scale animated:NO];
    // END Bug workaround

    CGSize maxSize = imageScrollView.frame.size;
    CGSize viewSize = view.frame.size;
    float topInset = (maxSize.height - viewSize.height) / 2.0;
    float sideInset = (maxSize.width - viewSize.width) / 2.0;
    if (topInset < 0.0) topInset = 0.0;
    if (sideInset < 0.0) sideInset = 0.0;
    [imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}
+135
22 авг. '09 в 16:55
источник поделиться
25 ответов

В настоящее время я подклассифицирую UIScrollView и переопределяя setContentOffset:, чтобы настроить смещение на основе contentSize. Он работает как с щепоткой, так и с программным масштабированием.

@implementation HPCenteringScrollView

- (void)setContentOffset:(CGPoint)contentOffset
{
    const CGSize contentSize = self.contentSize;
    const CGSize scrollViewSize = self.bounds.size;

    if (contentSize.width < scrollViewSize.width)
    {
        contentOffset.x = -(scrollViewSize.width - contentSize.width) / 2.0;
    }

    if (contentSize.height < scrollViewSize.height)
    {
        contentOffset.y = -(scrollViewSize.height - contentSize.height) / 2.0;
    }

    [super setContentOffset:contentOffset];
}

@end

Помимо короткого и сладкого, этот код обеспечивает гораздо более плавное масштабирование, чем решение @Erdemus. Вы можете увидеть его в действии в демонстрации RMGallery.

+20
21 мар. '14 в 12:06
источник

У меня очень простое решение! Все, что вам нужно, - это обновить центр вашего подвью (просмотр изображения) при масштабировании ScrollViewDelegate. Если увеличенное изображение меньше прокрутки, настройте subview.center else center (0,0).

- (void)scrollViewDidZoom:(UIScrollView *)scrollView 
{
    UIView *subView = [scrollView.subviews objectAtIndex:0];

    CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
    CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);

    subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, 
                                 scrollView.contentSize.height * 0.5 + offsetY);
}
+227
22 мая '10 в 7:25
источник
другие ответы

Связанные вопросы


Похожие вопросы

Ответ @EvelynCordner был лучшим в моем приложении. Гораздо меньше кода, чем другие варианты тоже.

Вот версия Swift, если кому-то это нужно:

func scrollViewDidZoom(_ scrollView: UIScrollView) {
    let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
    let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
    scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0, 0)
}
+39
23 мар. '16 в 5:57
источник

Хорошо, я боролся с этим в течение последних двух дней, и, наконец, пришел к довольно надежному (до сих пор...) решению. Я думал, что должен поделиться им и сохранить другие боли.:) Если вы нашли проблему с этим решением, пожалуйста, кричите!

Я в основном пережил все, что у всех: поиск StackOverflow, Форумы разработчиков Apple, рассмотрел код для трех20, ScrollingMadness, ScrollTestSuite и т.д. Я попытался расширить кадр UIImageView, играя с смещением UIScrollView и/или вставки из ViewController и т.д., но ничего не работало отлично (как выяснили все остальные).

После сна, я попробовал пару альтернативных углов:

  • Подклассификация UIImageView, так что динамически изменяет ее собственный размер динамически - это совсем не сработало.
  • Подклассификация UIScrollView, поэтому она динамически изменяет свой собственный контентОбновление - это тот, который кажется мне победителем.

С помощью этого подкласса метода UIScrollView я переопределяю мутатор contentOffset, поэтому он не устанавливает {0,0}, когда изображение масштабируется меньше, чем область просмотра, вместо этого оно устанавливает смещение таким образом, чтобы изображение сохранялось в центре в окне просмотра. Пока это работает. Я проверил его с широкими, высокими, крошечными и крупными изображениями и не имел "работы, но щепотку при минимальном разрыве".

Я загрузил пример проекта в github, который использует это решение, вы можете найти его здесь: http://github.com/nyoron/NYOBetterZoom

+25
14 апр. '10 в 14:28
источник

Этот код должен работать в большинстве версий iOS (и был протестирован для работы над 3.1 вверх).

Он основан на коде Apple WWDC для фотоколлектора.

Добавьте ниже в свой подкласс UIScrollView и замените tileContainerView на представление, содержащее ваше изображение или фрагменты:

- (void)layoutSubviews {
    [super layoutSubviews];

    // center the image as it becomes smaller than the size of the screen
    CGSize boundsSize = self.bounds.size;
    CGRect frameToCenter = tileContainerView.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;

    tileContainerView.frame = frameToCenter;
}
+23
13 авг. '10 в 16:56
источник

Для решения, более подходящего для прокрутки, использующего автозапуск, используйте вставки содержимого прокрутки, а не обновление фреймов в виде просмотра прокрутки.

- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
    CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
    CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);

    self.scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0.f, 0.f);
}
+20
15 июл. '15 в 4:45
источник

Я провел день, борясь с этой проблемой, и закончил реализацию scrollViewDidEndZooming: withView: atScale: следующим образом:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
    CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
    CGFloat viewWidth = view.frame.size.width;
    CGFloat viewHeight = view.frame.size.height;

    CGFloat x = 0;
    CGFloat y = 0;

    if(viewWidth < screenWidth) {
        x = screenWidth / 2;
    }
    if(viewHeight < screenHeight) {
        y = screenHeight / 2 ;
    }

    self.scrollView.contentInset = UIEdgeInsetsMake(y, x, y, x);
}

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

(предполагая, что ваш UIScrollView содержит UIImageView для хранения изображения)

По сути, это означает, что ширина/высота изображения меньше, чем ширина/высота экрана, и если да, создайте вставку с половиной ширины/высоты экрана (возможно, вы можете сделать это больше, если хотите изображение выходит за пределы экрана).

Обратите внимание, что поскольку это метод UIScrollViewDelegate, не забудьте добавить его в объявление контроллера вашего вида, чтобы избежать возникновения проблемы с сборкой.

+12
25 янв. '11 в 11:31
источник

Apple выпустила видеозапись сессии WWDC 2010 года всем участникам программы разработки iphone. Одна из обсуждаемых тем - как они создали приложение для фотографий!!! Они создают очень похожее приложение шаг за шагом и сделали весь код доступным бесплатно.

Он также не использует private api. Я не могу указать какой-либо код здесь из-за соглашения о неразглашении, но вот ссылка на загрузку кода примера. Вам, вероятно, потребуется войти в систему, чтобы получить доступ.

http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?code=y&source=x&bundleID=20645

И вот ссылка на страницу WWDC iTunes:

http://insideapple.apple.com/redir/cbx-cgi.do?v=2&la=en&lc=&a=kGSol9sgPHP%2BtlWtLp%2BEP%2FnxnZarjWJglPBZRHd3oDbACudP51JNGS8KlsFgxZto9X%2BTsnqSbeUSWX0doe%2Fzv%2FN5XV55%2FomsyfRgFBysOnIVggO%2Fn2p%2BiweDK%2F%2FmsIXj

+7
20 июн. '10 в 19:51
источник

Хорошо, это решение работает для меня. У меня есть подкласс UIScrollView со ссылкой на отображаемый UIImageView. Всякий раз, когда масштабируется UIScrollView, изменяется свойство contentSize. В настройщике я соответствующим образом масштабирую UIImageView, а также отрегулирую его центральное положение.

-(void) setContentSize:(CGSize) size{
CGSize lSelfSize = self.frame.size;
CGPoint mid;
if(self.zoomScale >= self.minimumZoomScale){
    CGSize lImageSize = cachedImageView.initialSize;
    float newHeight = lImageSize.height * self.zoomScale;

    if (newHeight < lSelfSize.height ) {
        newHeight = lSelfSize.height;
    }
    size.height = newHeight;

    float newWidth = lImageSize.width * self.zoomScale;
    if (newWidth < lSelfSize.width ) {
        newWidth = lSelfSize.width;
    }
    size.width = newWidth;
    mid = CGPointMake(size.width/2, size.height/2);

}
else {
    mid = CGPointMake(lSelfSize.width/2, lSelfSize.height/2);
}

cachedImageView.center = mid;
[super  setContentSize:size];
[self printLocations];
NSLog(@"zoom %f setting size %f x %f",self.zoomScale,size.width,size.height);
}

Evertime Я установил изображение на UIScrollView, я изменил его размер. UIScrollView в scrollview также является настраиваемым классом, который я создал.

-(void) resetSize{
    if (!scrollView){//scroll view is view containing imageview
        return;
    }

    CGSize lSize = scrollView.frame.size;

    CGSize lSelfSize = self.image.size; 
    float lWidth = lSize.width/lSelfSize.width;
    float lHeight = lSize.height/lSelfSize.height;

    // choose minimum scale so image width fits screen
    float factor  = (lWidth<lHeight)?lWidth:lHeight;

    initialSize.height = lSelfSize.height  * factor;
    initialSize.width = lSelfSize.width  * factor;

    [scrollView setContentSize:lSize];
    [scrollView setContentOffset:CGPointZero];
    scrollView.userInteractionEnabled = YES;
}

С помощью этих двух методов я могу иметь представление, которое ведет себя так же, как приложение для фотографий.

+2
16 мар. '10 в 5:08
источник

Вы можете посмотреть свойство contentSize UIScrollView (используя наблюдение за ключом или подобное) и автоматически отрегулировать contentInset, когда изменения contentSize будут меньше, чем размер прокрутки.

+1
22 авг. '09 в 17:17
источник

То, как я это сделал, - добавить дополнительный вид в иерархию:

UIScrollView -> UIView -> UIImageView

Придайте UIView те же пропорции, что и ваш UIScrollView, и центрируйте свой UIImageView в этом.

+1
24 авг. '09 в 19:05
источник

Один из элегантных способов сосредоточиться на содержании UISCrollView заключается в этом.

Добавьте одного наблюдателя в contentSize вашего UISCrollView, поэтому этот метод будет вызываться каждый раз при изменении содержимого...

[myScrollView addObserver:delegate 
               forKeyPath:@"contentSize"
                  options:(NSKeyValueObservingOptionNew) 
                  context:NULL];

Теперь по вашему методу наблюдателя:

- (void)observeValueForKeyPath:(NSString *)keyPath   ofObject:(id)object   change:(NSDictionary *)change   context:(void *)context { 

    // Correct Object Class.
    UIScrollView *pointer = object;

    // Calculate Center.
    CGFloat topCorrect = ([pointer bounds].size.height - [pointer viewWithTag:100].bounds.size.height * [pointer zoomScale])  / 2.0 ;
            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );

    topCorrect = topCorrect - (  pointer.frame.origin.y - imageGallery.frame.origin.y );

    // Apply Correct Center.
    pointer.center = CGPointMake(pointer.center.x,
                                 pointer.center.y + topCorrect ); }
  • Вы должны изменить [pointer viewWithTag:100]. Замените просмотр содержимого UIView.

    • Также измените imageGallery на ваш размер окна.

Это будет корректировать центр содержимого каждый раз при изменении его размера.

ПРИМЕЧАНИЕ. Единственный способ, которым этот контент не работает очень хорошо, - это стандартная функция масштабирования UISCrollView.

+1
03 нояб. '09 в 17:09
источник

Вы обнаружите, что решение, размещенное Erdemus, действительно работает, но... Есть случаи, когда метод scrollViewDidZoom не запускается, и ваше изображение застревает в верхнем левом углу. Простое решение заключается в явном вызове метода при первоначальном отображении изображения, например:

[self scrollViewDidZoom: scrollView];

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

+1
07 сент. '11 в 1:13
источник

Это мое решение этой проблемы, которая отлично работает для любого вида внутри прокрутки.

-(void)scrollViewDidZoom:(__unused UIScrollView *)scrollView 
    {
    CGFloat top;
    CGFloat left;
    CGFloat bottom;
    CGFloat right;

    if (_scrollView.contentSize.width < scrollView.bounds.size.width) {
        DDLogInfo(@"contentSize %@",NSStringFromCGSize(_scrollView.contentSize));

        CGFloat width = (_scrollView.bounds.size.width-_scrollView.contentSize.width)/2.0;

        left = width;
        right = width;


    }else {
        left = kInset;
        right = kInset;
    }

    if (_scrollView.contentSize.height < scrollView.bounds.size.height) {

        CGFloat height = (_scrollView.bounds.size.height-_scrollView.contentSize.height)/2.0;

        top = height;
        bottom = height;

    }else {
        top = kInset;
        right = kInset;
    }

    _scrollView.contentInset = UIEdgeInsetsMake(top, left, bottom, right);



  if ([self.tiledScrollViewDelegate respondsToSelector:@selector(tiledScrollViewDidZoom:)])
  {
        [self.tiledScrollViewDelegate tiledScrollViewDidZoom:self];
  }
}
+1
07 янв. '13 в 0:13
источник

Здесь есть много решений, но я бы рискнул поставить здесь свое. Это полезно по двум причинам: это не пугает масштабирование, так же как и обновление рамки просмотра изображений, а также уважает оригинальные вставки прокрутки (скажем, определенные в xib или раскадровке для изящной обработки полупрозрачных панелей инструментов и т.д.),

Сначала определите небольшой помощник:

CGSize CGSizeWithAspectFit(CGSize containerSize, CGSize contentSize) {
    CGFloat containerAspect = containerSize.width / containerSize.height,
            contentAspect = contentSize.width / contentSize.height;

    CGFloat scale = containerAspect > contentAspect
                    ? containerSize.height / contentSize.height
                    : containerSize.width / contentSize.width;

    return CGSizeMake(contentSize.width * scale, contentSize.height * scale);
}

Чтобы сохранить оригинальные вставки, заданное поле:

UIEdgeInsets originalScrollViewInsets;

И где-то в viewDidLoad залейте его:

originalScrollViewInsets = self.scrollView.contentInset;

Поместить UIImageView в UIScrollView (при условии, что сам UIImage находится в loadImage var):

CGSize containerSize = self.scrollView.bounds.size;
containerSize.height -= originalScrollViewInsets.top + originalScrollViewInsets.bottom;
containerSize.width -= originalScrollViewInsets.left + originalScrollViewInsets.right;

CGSize contentSize = CGSizeWithAspectFit(containerSize, loadedImage.size);

UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRect) { CGPointZero, contentSize }];
imageView.autoresizingMask = UIViewAutoresizingNone;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = loadedImage;

[self.scrollView addSubview:imageView];
self.scrollView.contentSize = contentSize;

[self centerImageViewInScrollView];

scrollViewDidZoom: из UIScrollViewDelegate для этого прокрутки:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    if (scrollView == self.scrollView) {
        [self centerImageViewInScrollView];
    }
}

Наконец, центрируя себя:

- (void)centerImageViewInScrollView {
    CGFloat excessiveWidth = MAX(0.0, self.scrollView.bounds.size.width - self.scrollView.contentSize.width),
            excessiveHeight = MAX(0.0, self.scrollView.bounds.size.height - self.scrollView.contentSize.height),
            insetX = excessiveWidth / 2.0,
            insetY = excessiveHeight / 2.0;

    self.scrollView.contentInset = UIEdgeInsetsMake(
            MAX(insetY, originalScrollViewInsets.top),
            MAX(insetX, originalScrollViewInsets.left),
            MAX(insetY, originalScrollViewInsets.bottom),
            MAX(insetX, originalScrollViewInsets.right)
    );
}

Я еще не тестировал изменение ориентации (т.е. правильная реакция на изменение размера самого UIScrollView), но исправление для этого должно быть относительно простым.

+1
20 мар. '13 в 19:40
источник

Apple Photo Scroller Пример делает именно то, что вы ищете. Поместите это в свой подкласс UIScrollView и измените _zoomView как ваш UIImageView.

-(void)layoutSubviews{
  [super layoutSubviews];
  // center the zoom view as it becomes smaller than the size of the screen
  CGSize boundsSize = self.bounds.size;
  CGRect frameToCenter = self.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;
  }
  self.imageView.frame = frameToCenter; 
}

Пример кода прокрутки Apple Photo

+1
01 мая '13 в 17:35
источник

Чтобы сделать поток анимации приятным, установите

self.scrollview.bouncesZoom = NO;

и использовать эту функцию (найти центр, используя метод этот ответ)

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
    [UIView animateWithDuration:0.2 animations:^{
        float offsetX = MAX((scrollView.bounds.size.width-scrollView.contentSize.width)/2, 0);
        float offsetY = MAX((scrollView.bounds.size.height-scrollView.contentSize.height)/2, 0);
        self.imageCoverView.center = CGPointMake(scrollView.contentSize.width*0.5+offsetX, scrollView.contentSize.height*0.5+offsetY);
    }];
}

Это создает эффект подпрыгивания, но не предполагает каких-либо внезапных движений заранее.

+1
18 мар. '15 в 3:40
источник

Только одобренный ответ в быстром, но без подкласса с использованием делегата

func centerScrollViewContents(scrollView: UIScrollView) {
    let contentSize = scrollView.contentSize
    let scrollViewSize = scrollView.frame.size;
    var contentOffset = scrollView.contentOffset;

    if (contentSize.width < scrollViewSize.width) {
        contentOffset.x = -(scrollViewSize.width - contentSize.width) / 2.0
    }

    if (contentSize.height < scrollViewSize.height) {
        contentOffset.y = -(scrollViewSize.height - contentSize.height) / 2.0
    }

    scrollView.setContentOffset(contentOffset, animated: false)
}

// UIScrollViewDelegate    
func scrollViewDidZoom(scrollView: UIScrollView) {
    centerScrollViewContents(scrollView)
}
+1
12 февр. '16 в 10:25
источник

Если ваш внутренний imageView имеет начальную определенную ширину (например, 300), и вы просто хотите центрировать его ширину только при масштабировании, меньшем, чем его начальная ширина, это также может помочь вам.

 func scrollViewDidZoom(scrollView: UIScrollView){
    if imageView.frame.size.width < 300{
        imageView.center.x = self.view.frame.width/2
    }
  }
+1
26 сент. '16 в 14:06
источник

Хорошо, я думаю, что нашел довольно хорошее решение этой проблемы. Хитрость заключается в постоянном изменении кадра imageView's. Я считаю, что это работает намного лучше, чем постоянная настройка contentInsets или contentOffSets. Мне пришлось добавить немного дополнительного кода для размещения как портретных, так и пейзажных изображений.

Здесь код:

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {

CGSize screenSize = [[self view] bounds].size;

if (myScrollView.zoomScale <= initialZoom +0.01) //This resolves a problem with the code not working correctly when zooming all the way out.
{
    imageView.frame = [[self view] bounds];
    [myScrollView setZoomScale:myScrollView.zoomScale +0.01];
}

if (myScrollView.zoomScale > initialZoom)
{
    if (CGImageGetWidth(temporaryImage.CGImage) > CGImageGetHeight(temporaryImage.CGImage)) //If the image is wider than tall, do the following...
    {
        if (screenSize.height >= CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is greater than the zoomed height of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), 368);
        }
        if (screenSize.height < CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is less than the zoomed height of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]);
        }
    }
    if (CGImageGetWidth(temporaryImage.CGImage) < CGImageGetHeight(temporaryImage.CGImage)) //If the image is taller than wide, do the following...
    {
        CGFloat portraitHeight;
        if (CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale] < 368)
        { portraitHeight = 368;}
        else {portraitHeight = CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale];}

        if (screenSize.width >= CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is greater than the zoomed width of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, 320, portraitHeight);
        }
        if (screenSize.width < CGImageGetWidth (temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is less than the zoomed width of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale], portraitHeight);
        }
    }
    [myScrollView setZoomScale:myScrollView.zoomScale -0.01];
}
0
04 окт. '09 в 1:50
источник

Вот так я и делаю эту работу. Это лучше, но все же не идеально. Попробуйте установить:

 myScrollView.bouncesZoom = YES; 

чтобы устранить проблему, если представление не центрируется, когда на minZoomScale.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGSize screenSize = [[self view] bounds].size;//[[UIScreen mainScreen] bounds].size;//
CGSize photoSize = [yourImage size];
CGFloat topInset = (screenSize.height - photoSize.height * [myScrollView zoomScale]) / 2.0;
CGFloat sideInset = (screenSize.width - photoSize.width * [myScrollView zoomScale]) / 2.0;

if (topInset < 0.0)
{ topInset = 0.0; }
if (sideInset < 0.0)
{ sideInset = 0.0; } 
[myScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
ApplicationDelegate *appDelegate = (ApplicationDelegate *)[[UIApplication sharedApplication] delegate];

CGFloat scrollViewHeight; //Used later to calculate the height of the scrollView
if (appDelegate.navigationController.navigationBar.hidden == YES) //If the NavBar is Hidden, set scrollViewHeight to 480
{ scrollViewHeight = 480; }
if (appDelegate.navigationController.navigationBar.hidden == NO) //If the NavBar not Hidden, set scrollViewHeight to 360
{ scrollViewHeight = 368; }

imageView.frame = CGRectMake(0, 0, CGImageGetWidth(yourImage)* [myScrollView zoomScale], CGImageGetHeight(yourImage)* [myScrollView zoomScale]);

[imageView setContentMode:UIViewContentModeCenter];
}

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

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
myScrollView.frame = CGRectMake(0, 0, 320, 420);
 //put the correct parameters for your scroll view width and height above
}
0
05 янв. '10 в 5:19
источник

Просто отключите разбиение на страницы, чтобы он работал нормально:

scrollview.pagingEnabled = NO;
0
21 мар. '14 в 5:26
источник

У меня была такая же проблема. Вот как я решил

Этот код должен вызываться как результат scrollView:DidScroll:

CGFloat imageHeight = self.imageView.frame.size.width * self.imageView.image.size.height / self.imageView.image.size.width;
BOOL imageSmallerThanContent = (imageHeight < self.scrollview.frame.size.height) ? YES : NO;
CGFloat topOffset = (self.imageView.frame.size.height - imageHeight) / 2;

// If image is not large enough setup content offset in a way that image is centered and not vertically scrollable
if (imageSmallerThanContent) {
     topOffset = topOffset - ((self.scrollview.frame.size.height - imageHeight)/2);
}

self.scrollview.contentInset = UIEdgeInsetsMake(topOffset * -1, 0, topOffset * -1, 0);
0
03 февр. '15 в 2:31
источник

Хотя вопрос еще немного, но проблема все еще существует. Я решил это в Xcode 7, установив ограничение вертикального пространства самого верхнего элемента (в данном случае topLabel) на superViews (scrollView) вверх a IBOutlet, а затем пересчитав его постоянный каждый раз, когда содержимое изменяется в зависимости от высоты подсмотра scrollView (topLabel и bottomLabel).

class MyViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var topLabel: UILabel!
    @IBOutlet weak var bottomLabel: UILabel!
    @IBOutlet weak var toTopConstraint: NSLayoutConstraint!

    override func viewDidLayoutSubviews() {
        let heightOfScrollViewContents = (topLabel.frame.origin.y + topLabel.frame.size.height - bottomLabel.frame.origin.y)
        // In my case abs() delivers the perfect result, but you could also check if the heightOfScrollViewContents is greater than 0.
        toTopConstraint.constant = abs((scrollView.frame.height - heightOfScrollViewContents) / 2)
    }

    func refreshContents() {
        // Set the label text …

        self.view.layoutIfNeeded()
    }
}
0
05 окт. '15 в 10:20
источник

Я знаю, что некоторые ответы выше верны, но я просто хочу дать свой ответ с некоторыми пояснениями, комментарии помогут вам понять, почему мы так поступаем.

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

    scrollView.maximumZoomScale = 8
    scrollView.minimumZoomScale = 1

    // set vContent frame
    vContent.frame = CGRect(x: 0,
                            y: 0  ,
                            width: vContentWidth,
                            height: vContentWidth)
    // set scrollView.contentSize
    scrollView.contentSize = vContent.frame.size

    //on the X direction, if contentSize.width > scrollView.bounds.with, move scrollView from 0 to offsetX to make it center(using 'scrollView.contentOffset')
    // if not, don't need to set offset, but we need to set contentInset to make it center.(using 'scrollView.contentInset')
    // so does the Y direction.
    let offsetX = max((scrollView.contentSize.width - scrollView.bounds.width) * 0.5, 0)
    let offsetY = max((scrollView.contentSize.height - scrollView.bounds.height) * 0.5, 0)
    scrollView.contentOffset = CGPoint(x: offsetX, y: offsetY)

    let topX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
    let topY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
    scrollView.contentInset = UIEdgeInsets(top: topY, left: topX, bottom: 0, right: 0)

Затем, когда я зажимаю vContent, я пишу следующий код, чтобы сделать его центром.

func scrollViewDidZoom(_ scrollView: UIScrollView) {
    //we just need to ensure that the content is in the center when the contentSize is less than scrollView.size.
    let topX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
    let topY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
    scrollView.contentInset = UIEdgeInsets(top: topY, left: topX, bottom: 0, right: 0)
}
0
01 июл. '19 в 8:25
источник

Посмотрите другие вопросы по меткам или Задайте вопрос