是否可以在UIScrollView中居中内容,如Apple的照片应用程序?

时间:2009-09-30 03:41:01

标签: iphone uiview uiscrollview center

我一直在努力解决这个问题,似乎没有明确的答案。如果有人想出来,请告诉我。

我想在UIScrollView中以屏幕为中心显示照片(图像可能是纵向或横向)。

我希望能够像在照片应用中一样将图像缩放和平移到图像的边缘。

我已尝试更改contentInset方法中的viewDidEndZooming,但这种方法很有效,但有几个小故障。

我也尝试将imageView设为与scrollView相同的尺寸,并将图像居中。问题是当你缩放时,你可以滚动整个imageView,部分图像可能会滚动视图。

我在这里发现了一篇类似的帖子并给出了我最好的解决方法,但没有找到真正的答案:

UIScrollView with centered UIImageView, like Photos app

3 个答案:

答案 0 :(得分:2)

UISCrollView的内容集中在一起的一种优雅方式就是这个。

将一位观察者添加到UIScrollView contentSize 中,因此每次内容更改时都会调用此方法...

[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 :(得分:2)

此代码适用于大多数iOS版本(已经过测试,可以在3.1版本上运行)。

它基于PhotoScroll应用程序的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;
}

答案 2 :(得分:1)

这是我能解决这个问题的最佳解决方案。诀窍是不断重新调整imageView的框架。我发现这比不断调整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];
}

以下是我在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];