UIScrollView med sentrert UIImageView, som bilder app

stemmer
37

Jeg vil gjerne ha bla visning med et bildeinnhold utsikt. Bildet er faktisk kartet som er mye større enn skjermen. Kartet skal være først i midten av bla syn, som bilder i Bilder-programmet når du slår iPhone til liggende retning.

alt

Jeg klarte ikke å ha kartet i sentrum med riktig zooming og rulling på samme tid. Forutsatt at kartbildet starter fra toppen av skjermen (i stående retning), ser koden noe sånt som:

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

Når jeg flytter bilderammen til sentrum, vokser bildet bare fra toppen av rammen ned. I forsøkt å leke med mapView transform, med dynamisk endring rammen i bildeVis. Ingenting fungerer for meg så langt.

Publisert på 12/03/2009 klokken 11:56
kilden bruker
På andre språk...                            


11 svar

stemmer
40

Denne koden skal fungere på de fleste versjoner av iOS (og har blitt testet for å fungere på 3,1 oppover).

Det er basert på Apples WWDC koden nevnt i Jonas 'svar.

Tilsett nedenfor til underklasse av UIScrollView, og erstatte tileContainerView med utsikt inneholder bildet eller fliser:

- (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;
}
Svarte 13/08/2010 kl. 16:42
kilden bruker

stemmer
23

Her er hva jeg ville vurdere, løsningen som i den oppfører seg akkurat som eple bildeprogram. Jeg hadde vært å bruke løsninger som brukes:

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

å sentrere men jeg gjorde ikke sånn løsning fordi etter zooming ble gjort, ville den sprette så rask 'hoppe' i midten, som var svært un-sexy. Det viser seg at hvis du stort sett gjøre nøyaktig samme logikk, men i dette delegere funksjon:

-(void)scrollViewDidZoom:(UIScrollView *)pScrollView

det både starter sentrert og når du zoomer ut det forblir sentrert:

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

Hvor bildeVis 'er UIImageViewdu bruker.

Svarte 03/02/2010 kl. 02:51
kilden bruker

stemmer
7

Apple har gitt ut i 2010 WWDC økt videoer til alle medlemmer av iPhone Developer Program. Ett av temaene er hvordan de skapte bilder app !!! De bygger en svært lik app trinnvis og har gjort all koden tilgjengelig gratis.

Det bruker ikke privat api heller. Jeg kan ikke sette noen av koden her på grunn av Non Disclosure Agreement, men her er en link til eksempelkoden nedlasting. Du vil sannsynligvis må logge inn for å få tilgang.

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

Og her er en link til iTunes WWDC siden:

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

Svarte 20/06/2010 kl. 19:48
kilden bruker

stemmer
2

Jeg mistenker at du trenger å sette UIScrollView's contentOffset.

Svarte 12/03/2009 kl. 19:16
kilden bruker

stemmer
1

Dette fungerte for meg:

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

}

hvor 160 er halvparten av den bredde / høyde på UIScrollView.

Senere jeg sette contentoffset til en fanget her.

Svarte 31/03/2009 kl. 08:15
kilden bruker

stemmer
1

Jeg skulle ønske det var så enkelt. Jeg gjorde noen undersøkelser på nettet og funnet ut at det er ikke bare mitt problem, men mange sliter med det samme problemet ikke bare på iPhone, men på Apples stasjonære Cocoa også. Se følgende linker:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/5740-uiimageview-uiscrollview.html
Det beskrevne løsningen er basert på eiendommen UIViewContentModeScaleAspectFit av bildet, men dessverre er det ikke fungerer svært godt sikret bildet er sentrert og vokser som den skal, men den spretter området synes å være mye større enn bildet.

Denne fyren fikk ikke svaret enten:
http://discussions.apple.com/thread.jspa?messageID=8322675

Og til slutt, det samme problemet på Apples stasjonære Cocoa:
http://www.cocoadev.com/index.pl?CenteringInsideNSScrollView
Jeg antar at løsningen fungerer, men det er basert på NSClipView, som ikke er på iPhone ...

Noen som har noen løsning å jobbe på iPhone?

Svarte 13/03/2009 kl. 07:29
kilden bruker

stemmer
0

Her er en alternativ løsning, lik @ JosephH svar, men dette tar hensyn til de faktiske dimensjonene på bildet. Slik at når brukeren panner / zoom, du aldri mer mellomrom på skjermen enn nødvendig. Dette er et vanlig problem for eksempel når du viser et landskap bilde på et portrett skjermen. Det kommer til å bli mellomrom over og under bildet når hele bildet vises på skjermen (Aspect Fit). Deretter, når du zoomer inn, de andre løsningene anser at whitespace som en del av bildet, fordi det er i bildeVis. De vil la deg panorere flertallet av bildet av skjermen, slik at bare de tomme synlig. Dette ser ikke bra ut for brukeren.

Med denne klassen, trenger du å passere det bildeVis det fungerer med. Jeg ble fristet til å ha det automatisk oppdage, men dette er raskere og du vil all den hastigheten du kan få i layoutSubviewsmetoden.

Merk: Som er, krever dette at Autooppsett ikke er aktivert for 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
    }
}
Svarte 05/05/2016 kl. 09:56
kilden bruker

stemmer
0

I Mono som fungerte for meg.

this._scroll.ScrollRectToVisible(new RectangleF(_scroll.ContentSize.Width/2, _scroll.ContentSize.Height/2,1,1),false);
Svarte 08/08/2012 kl. 14:45
kilden bruker

stemmer
0

En elegant måte å sentrere innholdet i UISCrollViewdette.

Legg en observatør til contentSize din UIScrollView, så denne metoden vil bli kalt hver gang innholdet endring ...

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

Nå på observatør-metoden:

- (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 ); }
  • Du bør endre [pointer viewWithTag:100]. Skift av innholdet utsikt UIView.

    • Også endre imageGallerypeker til vindusstørrelsen.

Dette vil korrigere sentrum av innholdet hver gang hans størrelse endring.

MERK: Den eneste måten dette innholdet ikke fungerer veldig bra er med standard zoom funksjonalitet UIScrollView.

Svarte 03/11/2009 kl. 17:14
kilden bruker

stemmer
0

Ok, jeg tror jeg har funnet en ganske god løsning på dette problemet. Trikset er å hele tiden justere bildeVis ramme. Jeg finner dette fungerer mye bedre enn stadig å justere contentInsets eller contentOffSets. Jeg måtte legge til litt ekstra kode for å imøtekomme både stående og liggende bilder.

Her er koden:

- (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];
}
Svarte 04/10/2009 kl. 02:16
kilden bruker

stemmer
0

Merk: Denne metoden slags verk. Dersom bildet er mindre enn den bildeVis, vil det rulle delvis utenfor skjermen. Ikke en stor avtale, men heller ikke så fint som bildene app.

Først er det viktig å forstå at vi har å gjøre med 2 utsikten, bildeVis med bildet i det, og scrollview med bildeVis i den. Så først sette bildeVis til størrelsen på skjermen:

 [myImageView setFrame:self.view.frame];

Deretter sentrere bildet i bildeVis:

 myImageView.contentMode = UIViewContentModeCenter;

Her er min hele koden:

- (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];
 }
Svarte 08/09/2009 kl. 02:14
kilden bruker

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