Подтвердить что ты не робот

Как сосредоточить UIImageView в полноэкранном UIScrollView?

В моем приложении я хотел бы представить пользователю полноэкранный просмотрщик фотографий, подобный тому, который используется в приложении "Фотографии". Это просто для одной фотографии и, как таковая, должно быть довольно просто. Я просто хочу, чтобы пользователь мог просматривать эту фотографию с возможностью масштабирования и панорамирования.

У меня большая часть работы. И, если я не сосредотачиваю свой UIImageView, все ведет себя отлично. Тем не менее, я действительно хочу, чтобы UIImageView центрировался на экране, когда изображение было достаточно увеличено. Я не хочу, чтобы он застрял в верхнем левом углу прокрутки.

Как только я попытаюсь центрировать это представление, моя вертикальная область с прокруткой окажется больше, чем должна быть. Таким образом, как только я немного увеличусь, я могу прокрутить около 100 пикселей за верхнюю часть изображения. Что я делаю неправильно?

@interface MyPhotoViewController : UIViewController <UIScrollViewDelegate>
{
    UIImage* photo;
    UIImageView *imageView;
}
- (id)initWithPhoto:(UIImage *)aPhoto;
@end

@implementation MyPhotoViewController

- (id)initWithPhoto:(UIImage *)aPhoto
{
    if (self = [super init])
    {
        photo = [aPhoto retain];

        // Some 3.0 SDK code here to ensure this view has a full-screen
        // layout.
    }

    return self;
}

- (void)dealloc
{
    [photo release];
    [imageView release];
    [super dealloc];
}

- (void)loadView
{
    // Set the main view of this UIViewController to be a UIScrollView.
    UIScrollView *scrollView = [[UIScrollView alloc] init];
    [self setView:scrollView];
    [scrollView release];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Initialize the scroll view.
    CGSize photoSize = [photo size];
    UIScrollView *scrollView = (UIScrollView *)[self view];
    [scrollView setDelegate:self];
    [scrollView setBackgroundColor:[UIColor blackColor]];

    // Create the image view. We push the origin to (0, -44) to ensure
    // that this view displays behind the navigation bar.
    imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, -44.0,
        photoSize.width, photoSize.height)];
    [imageView setImage:photo];
    [scrollView addSubview:imageView];

    // Configure zooming.
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    CGFloat widthRatio = screenSize.width / photoSize.width;
    CGFloat heightRatio = screenSize.height / photoSize.height;
    CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
    [scrollView setMaximumZoomScale:3.0];
    [scrollView setMinimumZoomScale:initialZoom];
    [scrollView setZoomScale:initialZoom];
    [scrollView setBouncesZoom:YES];
    [scrollView setContentSize:CGSizeMake(photoSize.width * initialZoom,
        photoSize.height * initialZoom)];

    // Center the photo. Again we push the center point up by 44 pixels
    // to account for the translucent navigation bar.
    CGPoint scrollCenter = [scrollView center];
    [imageView setCenter:CGPointMake(scrollCenter.x,
        scrollCenter.y - 44.0)];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [[[self navigationController] navigationBar] setBarStyle:UIBarStyleBlackTranslucent];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[[self navigationController] navigationBar] setBarStyle:UIBarStyleDefault];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return imageView;
}

@end
4b9b3361

Ответ 1

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

Он основан на Код Apple WWDC для PhotoScroller.

Добавьте ниже к вашему подклассу 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

Вы проверили параметры UIViewAutoresizing?

(из документации)

UIViewAutoresizing
Specifies how a view is automatically resized.

enum {
   UIViewAutoresizingNone                 = 0,
   UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
   UIViewAutoresizingFlexibleWidth        = 1 << 1,
   UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
   UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
   UIViewAutoresizingFlexibleHeight       = 1 << 4,
   UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
typedef NSUInteger UIViewAutoresizing;

Ответ 4

Вы могли решить эту проблему? Я придерживаюсь аналогичной проблемы. Я думаю, что причина этого в том, что zoomScale применяется ко всему contentSize, независимо от фактического размера subview внутри scrollView (в вашем случае это imageView). Высота contentSize всегда всегда равна или превышает высоту кадра scrollView, но не меньше. Поэтому, применяя к нему масштабирование, высота contentSize также умножается на коэффициент масштабирования, поэтому вы получаете дополнительные 100-точные пиксели вертикальной прокрутки.

Ответ 5

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