ios - bottom - uiimageview set image swift




UIScrollView mit zentrierter UIImageView, wie Fotos-App (8)

Ich möchte eine Bildlaufansicht mit einer Bildinhaltsansicht haben. Das Bild ist eigentlich eine Karte, die viel größer als der Bildschirm ist. Die Karte sollte sich anfänglich in der Mitte der Bildlaufansicht befinden, z. B. Fotos in der Foto-App, wenn Sie das iPhone in Querformat ausrichten.

Ich habe es nicht geschafft, die Karte in der Mitte mit korrektem Zoomen und Scrollen gleichzeitig zu haben. Vorausgesetzt, das Kartenbild beginnt am oberen Rand des Bildschirms (in Hochformat), sieht der Code etwa so aus:

- (void)loadView {
    mapView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"map.jpg"]];
    CGFloat mapHeight = MAP_HEIGHT * SCREEN_WIDTH / MAP_WIDTH;
    mapView.frame = CGRectMake(0, 0, SCREEN_WIDTH, mapHeight);
    scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    scrollView.delegate = self;
    scrollView.contentSize = mapView.frame.size;
    scrollView.maximumZoomScale = MAP_WIDTH / SCREEN_WIDTH;
    scrollView.minimumZoomScale = 1;
    [scrollView addSubview:mapView];
    self.view = scrollView;
}

Wenn ich den Bildrahmen in die Mitte bewege, wird das Bild nur vom oberen Rand des Bildrahmens nach unten angezeigt. Ich habe versucht, mit mapView transform herumzuspielen, wobei sich der Frame des imageView dynamisch ändert. Für mich funktioniert bisher nichts.


Apple hat die Videos der WWDC-Sitzung 2010 für alle Mitglieder des iPhone-Entwicklerprogramms veröffentlicht. Eines der behandelten Themen ist, wie sie die Foto-App erstellt haben !!! Sie bauen eine sehr ähnliche App Schritt für Schritt auf und haben den gesamten Code kostenlos zur Verfügung gestellt.

Es verwendet auch keine private API. Ich kann den Code wegen der Geheimhaltungsvereinbarung hier nicht einfügen, aber hier ist ein Link zum Beispielcode-Download. Sie müssen sich wahrscheinlich anmelden, um Zugriff zu erhalten.

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

Und hier ist ein Link zur iTunes WWDC-Seite:

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


Das hat für mich funktioniert:

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGFloat tempx = view.center.x-160;
CGFloat tempy = view.center.y-160;
myScrollViewOffset = CGPointMake(tempx,tempy);

}

Dabei ist 160 die Hälfte der Breite / Höhe Ihres UIScrollView .

Später habe ich den Contentoffset auf den hier erfassten gesetzt.


Eine elegante Möglichkeit, den Inhalt von UISCrollView ist die folgende.

Fügen Sie der contentSize Ihres UIScrollView einen Beobachter UIScrollView , so dass diese Methode bei jeder Inhaltsänderung aufgerufen wird.

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

Nun zu Ihrer Beobachtermethode:

- (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 ); }
  • Sie sollten den [pointer viewWithTag:100] ändern. Ersetzen Sie UIView durch Ihre Inhaltsansicht.

    • Ändern imageGallery auch die imageGallery die auf Ihre Fenstergröße verweist.

Dadurch wird die Mitte des Inhalts bei jeder Größenänderung korrigiert.

HINWEIS: Diese Inhalte funktionieren nur mit der Standard-Zoom-Funktion von UIScrollView .


Hier ist eine alternative Lösung, ähnlich der Antwort von @ JosephH, die jedoch die tatsächlichen Abmessungen des Bildes berücksichtigt. Wenn der Benutzer schwenkt / zoomt, haben Sie niemals mehr Leerzeichen auf dem Bildschirm als erforderlich. Dies ist ein häufiges Problem, wenn Sie beispielsweise ein Querformat auf einem Hochformatbildschirm anzeigen. Es wird Leerzeichen über und unter dem Bild angezeigt, wenn das gesamte Bild auf dem Bildschirm angezeigt wird (Aspect Fit). Beim Vergrößern wird der Whitespace dann für andere Lösungen als Teil des Bildes betrachtet, da er sich in der imageView befindet. Damit können Sie den Großteil des Bildes außerhalb des Bildschirms schwenken und nur den Leerraum sichtbar lassen. Das sieht für den Benutzer schlecht aus.

Bei dieser Klasse müssen Sie das ImageView übergeben, mit dem es arbeitet. Ich war versucht, es automatisch erkennen zu lassen, aber dies ist schneller und Sie möchten alle Geschwindigkeit, die Sie mit der layoutSubviews Methode erreichen können.

Hinweis: Dies setzt voraus, dass AutoLayout für die Bildlaufansicht nicht aktiviert ist.

//
//  CentringScrollView.swift
//  Cerebral Gardens
//
//  Created by Dave Wood
//  Copyright © 2016 Cerebral Gardens Inc. All rights reserved.
//

import UIKit

class CentringScrollView: UIScrollView {

    var imageView: UIImageView?

    override func layoutSubviews() {
        super.layoutSubviews()

        guard let superview = superview else { return }
        guard let imageView = imageView else { return }
        guard let image = imageView.image else { return }

        var frameToCentre = imageView.frame

        let imageWidth = image.size.width
        let imageHeight = image.size.height

        let widthRatio = superview.bounds.size.width / imageWidth
        let heightRatio = superview.bounds.size.height / imageHeight

        let minRatio = min(widthRatio, heightRatio, 1.0)

        let effectiveImageWidth = minRatio * imageWidth * zoomScale
        let effectiveImageHeight = minRatio * imageHeight * zoomScale

        contentSize = CGSize(width: max(effectiveImageWidth, bounds.size.width), height: max(effectiveImageHeight, bounds.size.height))

        frameToCentre.origin.x = (contentSize.width - frameToCentre.size.width) / 2
        frameToCentre.origin.y = (contentSize.height - frameToCentre.size.height) / 2

        imageView.frame = frameToCentre
    }
}

Hinweis: Diese Methode funktioniert. Wenn das Bild kleiner ist als die Bildansicht, wird es teilweise vom Bildschirm verschoben. Keine große Sache, aber auch nicht so schön wie die Foto-App.

Zunächst ist es wichtig zu verstehen, dass es sich um 2 Ansichten handelt, die Bildansicht mit dem Bild darin und die Bildlaufansicht mit der Bildansicht darin. Stellen Sie zunächst die Bildansicht auf die Größe des Bildschirms ein:

 [myImageView setFrame:self.view.frame];

Dann zentrieren Sie Ihr Bild in der Bildansicht:

 myImageView.contentMode = UIViewContentModeCenter;

Hier ist mein gesamter Code:

- (void)viewDidLoad {
AppDelegate *appDelegate = (pAppDelegate *)[[UIApplication sharedApplication] delegate];
 [super viewDidLoad];
 NSString *Path = [[NSBundle mainBundle] bundlePath];
 NSString *ImagePath = [Path stringByAppendingPathComponent:(@"data: %@", appDelegate.MainImageName)];
 UIImage *tempImg = [[UIImage alloc] initWithContentsOfFile:ImagePath];
 [imgView setImage:tempImg];

 myScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
 [myScrollView addSubview:myImageView];

//Set ScrollView Appearance
 [myScrollView setBackgroundColor:[UIColor blackColor]];
 myScrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;

//Set Scrolling Prefs
 myScrollView.bounces = YES;
 myScrollView.delegate = self;
 myScrollView.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
 [myScrollView setCanCancelContentTouches:NO];
 [myScrollView setScrollEnabled:YES];


//Set Zooming Prefs
 myScrollView.maximumZoomScale = 3.0;
 myScrollView.minimumZoomScale = CGImageGetWidth(tempImg.CGImage)/320;
 myScrollView.zoomScale = 1.01; //Added the .01 to enable scrolling immediately upon view load.
 myScrollView.bouncesZoom = YES;


 [myImageView setFrame:self.view.frame];//rect];// .frame.size.height = imageHeight;
 myImageView.contentMode = UIViewContentModeCenter;
 self.view = myScrollView;
 [tempImg release];
 }

Ich vermute, dass Sie das UIScrollView der UIScrollView contentOffset .


In Monotouch hat das für mich funktioniert.

this._scroll.ScrollRectToVisible(new RectangleF(_scroll.ContentSize.Width/2, _scroll.ContentSize.Height/2,1,1),false);

Okay, ich glaube, ich habe eine ziemlich gute Lösung für dieses Problem gefunden. Der Trick besteht darin, den Frame der imageView ständig neu anzupassen. Ich finde, dass dies viel besser funktioniert, als die contentInsets oder contentOffSets ständig anzupassen. Ich musste ein wenig zusätzlichen Code hinzufügen, um sowohl Hoch- als auch Landschaftsbilder aufnehmen zu können.

Hier ist der Code:

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