20 Stimmen

Wie zentriere ich eine UIImageView innerhalb einer bildschirmfüllenden UIScrollView?

In meiner Anwendung möchte ich dem Benutzer einen bildschirmfüllenden Fotobetrachter präsentieren, der dem in der Fotos-App verwendeten ähnelt. Dies ist nur für ein einzelnes Foto und als solche sollte recht einfach sein. Ich möchte nur, dass der Benutzer in der Lage sein, dieses eine Foto mit der Fähigkeit zum Zoomen und Schwenken zu sehen.

Das meiste funktioniert schon. Und, wenn ich meine UIImageView nicht zentrieren, alles verhält sich perfekt. Allerdings möchte ich wirklich die UIImageView auf dem Bildschirm zentriert werden, wenn das Bild ausreichend herausgezoomt ist. Ich möchte nicht, dass es an der oberen linken Ecke der Bildlaufansicht klebt.

Sobald ich versuche, diese Ansicht zu zentrieren, scheint der vertikale Bildlaufbereich größer zu sein, als er sein sollte. Wenn ich ein wenig hineinzoome, kann ich etwa 100 Pixel über den oberen Rand des Bildes hinaus blättern. Was mache ich falsch?

@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

28voto

JosephH Punkte 36576

Dieser Code sollte auf den meisten iOS-Versionen funktionieren (und wurde auf 3.1 aufwärts getestet).

Es basiert auf dem Apple WWDC-Code für PhotoScroller .

Fügen Sie Ihrer Unterklasse von UIScrollView und ersetzen tileContainerView mit der Ansicht, die Ihr Bild oder Ihre Kacheln enthält:

- (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;
}

2voto

Jlam Punkte 1882

Haben Sie sich die UIViewAutoresizing-Optionen angesehen?

(aus der Dokumentation)

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;

1voto

lostInTransit Punkte 69377

Verwenden Sie IB, um die Bildlaufansicht hinzuzufügen? Ändern Sie die Optionen für die automatische Größenanpassung der Bildlaufansicht auf das beigefügte Bild. alt text

0voto

boliva Punkte 5567

Ich denke, der Grund dafür ist, dass die zoomScale auf die gesamte contentSize angewendet wird, unabhängig von der tatsächlichen Größe der Unteransicht innerhalb der scrollView (in Ihrem Fall ist es eine imageView). Die Höhe von contentSize scheint immer gleich oder größer zu sein als die Höhe des scrollView-Rahmens, aber niemals kleiner. Wenn man also einen Zoom darauf anwendet, wird die Höhe von contentSize mit dem zoomScale-Faktor multipliziert, weshalb man zusätzliche 100 Pixel vertikalen Scrollens erhält.

-1voto

Felixyz Punkte 18963

Wahrscheinlich möchten Sie die Grenzen der Bildlaufansicht = Grenzen der Bildansicht festlegen und dann die Bildlaufansicht in der sie enthaltenden Ansicht zentrieren. Wenn Sie eine Ansicht innerhalb einer Bildlaufansicht mit einem Versatz vom oberen Rand platzieren, erhalten Sie den leeren Raum darüber.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X