UIScrollView cu UIImageView centrat, cum ar fi fotografii app

voturi
37

Aș dori să aibă vedere de parcurgere cu o vedere conținutul imaginii. Imaginea este de fapt harta, care este mult mai mare decât ecranul. Harta trebuie să fie inițial în centrul vizualizării de defilare, cum ar fi fotografii în Fotografii aplicație atunci când iPhone rândul său, la orientarea peisaj.

alt

Nu am reușit să aibă harta în centru, cu zoom corectă și defilare în același timp. Cu condiția ca imaginea hartă pornește din partea de sus a ecranului (în orientarea portret), codul arata ceva de genul:

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

Când am muta cadrul de imagine la centru, imaginea creste doar din partea de sus a cadrului său în jos. Am încercat să se joace în jurul cu mapView transforma, cu schimbarea dinamic cadru al ImageView. Nimic nu funcționează pentru mine până acum.

Întrebat 12/03/2009 la 12:56
sursa de către utilizator
În alte limbi...                            


11 răspunsuri

voturi
40

Acest cod ar trebui să funcționeze pe cele mai multe versiuni ale iOS (și a fost testat pentru a lucra la 3.1 in sus).

Este bazat pe codul Apple a WWDC menționat în răspunsul lui Iona.

Se adaugă mai jos pentru a subclasă dvs. de UIScrollView, și înlocuiți tileContainerView cu vizualizarea care conține imaginea sau dale:

- (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;
}
Publicat 13/08/2010 la 17:42
sursa de către utilizator

voturi
23

Iată ce mi-ar lua în considerare, soluția ca și în ea se comportă exact ca app fotografie Apple. Am fost folosind soluții care au utilizat:

-(void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale

la recentra dar nu am făcut ca această soluție pentru că, după zoomingul a fost făcut, ar sări apoi „sari“ rapid în centru, care a fost foarte ne-sexy. Se pare că, dacă ai face destul de mult aceeași logică, dar exact în această funcție delegat:

-(void)scrollViewDidZoom:(UIScrollView *)pScrollView

ea atât începe centrat și atunci când zoom out acesta rămâne centrat:

-(void)scrollViewDidZoom:(UIScrollView *)pScrollView {
CGRect innerFrame = imageView.frame;
CGRect scrollerBounds = pScrollView.bounds;

if ( ( innerFrame.size.width < scrollerBounds.size.width ) || ( innerFrame.size.height < scrollerBounds.size.height ) )
{
    CGFloat tempx = imageView.center.x - ( scrollerBounds.size.width / 2 );
    CGFloat tempy = imageView.center.y - ( scrollerBounds.size.height / 2 );
    CGPoint myScrollViewOffset = CGPointMake( tempx, tempy);

    pScrollView.contentOffset = myScrollViewOffset;

}

UIEdgeInsets anEdgeInset = { 0, 0, 0, 0};
if ( scrollerBounds.size.width > innerFrame.size.width )
{
    anEdgeInset.left = (scrollerBounds.size.width - innerFrame.size.width) / 2;
    anEdgeInset.right = -anEdgeInset.left;  // I don't know why this needs to be negative, but that's what works
}
if ( scrollerBounds.size.height > innerFrame.size.height )
{
    anEdgeInset.top = (scrollerBounds.size.height - innerFrame.size.height) / 2;
    anEdgeInset.bottom = -anEdgeInset.top;  // I don't know why this needs to be negative, but that's what works
}
pScrollView.contentInset = anEdgeInset;
}

În cazul în care „ImageView“ este UIImageViewpe care îl utilizați.

Publicat 03/02/2010 la 03:51
sursa de către utilizator

voturi
7

Apple a lansat 2010 videoclipuri sesiune WWDC tuturor membrilor programului iPhone Developer. Unul dintre subiectele discutate este modul în care au creat aplicația fotografii !!! Ei construiesc un pas aplicație foarte asemănătoare cu pas și au făcut toate cod disponibil gratuit.

Ea nu folosește API-ul privat, fie. Nu pot pune oricare din codul de aici, din cauza acordului nedivulgarea, dar aici este un link la codul de probă descărcare. Veți avea nevoie, probabil, să te autentifici pentru a avea acces.

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

Și, aici este un link către pagina de iTunes WWDC:

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

Publicat 20/06/2010 la 20:48
sursa de către utilizator

voturi
2

Bănuiesc că trebuie să setați UIScrollView„s contentOffset.

Publicat 12/03/2009 la 20:16
sursa de către utilizator

voturi
1

Aceasta a lucrat pentru mine:

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

}

în cazul în care 160 este jumătate din lățimea / înălțimea dumneavoastră UIScrollView.

Apoi, mai târziu, am setat contentoffset la cel capturat aici.

Publicat 31/03/2009 la 09:15
sursa de către utilizator

voturi
1

Aș vrea să fie atât de simplu a fost. Am făcut unele cercetări pe net și a constatat că aceasta nu este doar problema mea, dar mulți oameni se luptă cu aceeași problemă nu doar pe iPhone, dar pe desktop-ul Apple cacao, de asemenea. A se vedea următoarele link-uri:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/5740-uiimageview-uiscrollview.html
Soluția descrisă se bazează pe proprietatea UIViewContentModeScaleAspectFit a imaginii, dar , din păcate , nu funcționează foarte bine .ca imagine este centrat și crește în mod corespunzător, dar zona de viguros pare a fi mult mai mare decât imaginea.

Acest tip nu a primit răspunsul , fie:
http://discussions.apple.com/thread.jspa?messageID=8322675

Și , în sfârșit, aceeași problemă pe ecranul de cacao Apple:
http://www.cocoadev.com/index.pl?CenteringInsideNSScrollView
Presupun functioneaza solutia, dar se bazează pe NSClipView, care nu este pe iPhone ...

Oricine are ceva soluție de lucru pe iPhone?

Publicat 13/03/2009 la 08:29
sursa de către utilizator

voturi
0

Iată o soluție alternativă, similar cu @ răspunsul JosephH lui, dar aceasta ia în considerare dimensiunile reale ale imaginii. Așa că, atunci când Oalele de utilizator / zoom-uri, nu aveți mai mult spațiu pe ecran decât este necesar. Aceasta este o problemă comună, de exemplu, atunci când prezintă o imagine de peisaj pe un ecran portret. Acolo va fi deasupra și sub spațiile albe imaginea atunci când întreaga imagine este pe ecran (Aspect Fit). Apoi, atunci când zoom, celelalte soluții consideră că spațiile libere ca parte a imaginii, deoarece este în ImageView. Ei vor permite să panoramare majoritatea imaginii de pe ecran, lăsând doar spații albe vizibile. Acest lucru arată rău pentru utilizator.

Cu această clasă, aveți nevoie să - l treacă ImageView cu care lucreaza. Am fost tentat să - l detecta automat, dar acest lucru este mai rapid și doriți ca toate viteza puteți obține în layoutSubviewsmetoda.

Notă: Așa cum este, acest lucru necesită ca AutoLayout nu este activat pentru scrollView.

//
//  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
    }
}
Publicat 05/05/2016 la 09:56
sursa de către utilizator

voturi
0

În MonoTouch care a lucrat pentru mine.

this._scroll.ScrollRectToVisible(new RectangleF(_scroll.ContentSize.Width/2, _scroll.ContentSize.Height/2,1,1),false);
Publicat 08/08/2012 la 15:45
sursa de către utilizator

voturi
0

Un mod elegant de a centra conținutul UISCrollVieweste aceasta.

Adăugați un observator la contentSize dvs. UIScrollView, astfel încât această metodă va fi numit de fiecare schimbare de conținut ...

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

Acum, pe metoda de observator:

- (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 ); }
  • Tu ar trebui să schimbe [pointer viewWithTag:100]. Înlocuiți prin afișarea de conținut UIView.

    • De asemenea , modificați imageGalleryindicând dimensiunea ferestrei.

Acest lucru va corecta centrul Everytime conținut schimbarea lui dimensiune.

NOTĂ: Singurul modul în care acest conținut nu funcționează foarte bine este cu funcționalitate zoom standard ale UIScrollView.

Publicat 03/11/2009 la 18:14
sursa de către utilizator

voturi
0

Bine, cred că am găsit o soluție destul de bună pentru această problemă. Trucul este să readapteze în mod constant Încadrați ImageView lui. Mi se pare acest lucru funcționează mult mai bine decât în ​​mod constant ajustarea contentInsets sau contentOffSets. A trebuit să adăugați un pic de cod suplimentar pentru a se potrivi atât portret și peisaj imagini.

Iată codul:

- (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];
}
Publicat 04/10/2009 la 03:16
sursa de către utilizator

voturi
0

Notă: această metodă tip de lucrări. în cazul în care imaginea este mai mică decât ImageView, se va derula parțial în afara ecranului. Nu este o afacere mare, dar, de asemenea, nu la fel de frumos ca aplicație fotografii.

În primul rând, este important să înțelegem că avem de-a face cu 2 perspective, ImageView cu imaginea în ea, și scrollview cu ImageView în ea. Deci, setați mai întâi ImageView la dimensiunea ecranului:

 [myImageView setFrame:self.view.frame];

Apoi, centrul imaginii dumneavoastră în ImageView:

 myImageView.contentMode = UIViewContentModeCenter;

Iată tot codul meu:

- (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];
 }
Publicat 08/09/2009 la 03:14
sursa de către utilizator

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more