Можно ли сосредоточиться на контенте в приложении uiscrollview, как Apple Photos?

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

Вопрос

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

Я хочу показать фото в UIScrollView это сосредоточено на экране (изображение может быть в портретной или ландшафтной ориентации).

Я хочу иметь возможность увеличить и пятно изображения только к краю изображения, как в приложении Photo.

Я попытался изменить contentInset в viewDidEndZooming Метод и этот вид справляются, но есть несколько сбоев.

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

Я нашел здесь похожий пост и дал лучший обходной путь, но не было найдено реального ответа:

Uiscrollview с центром uiimageview, как приложение Photos

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

Решение 3

Вот лучшее решение, которое я мог бы придумать для этой проблемы. Хитрость заключается в том, чтобы постоянно перенастроить кадр ImageView. Я считаю, что это работает намного лучше, чем постоянно настройка контент -энзионов или 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];
}

Вот как я рассчитываю шкалу масштабирования MIN в методе ViewDidload.

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

CGFloat widthRatio = screenSize.width / photoSize.width;
CGFloat heightRatio = screenSize.height / photoSize.height;
initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[myScrollView setMinimumZoomScale:initialZoom];
[myScrollView setZoomScale:initialZoom];
[myScrollView setMaximumZoomScale:3.0];

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

Один элегантный способ сосредоточиться на содержании UISCrollView это.

Добавить одного наблюдателя в Содержание вашей 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.

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

Он основан на коде Apple WWDC для приложения PhotoScroll.

Добавьте приведенное ниже в подкласс 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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top