2012-04-17 15 views
50

Estoy haciendo una simple presentación de diapositivas dentro de mi aplicación. Me gustaría vincular mi UIPageControl a mi UIScrollView. Esto no debería ser demasiado difícil, pero no he podido encontrar una solución simple en ninguna parte. A continuación está mi código.Vinculación mediante programación de UIPageControl a UIScrollView

HelpViewController.h

#import <UIKit/UIKit.h> 

@interface HelpViewController : UIViewController{ 
} 
@end 

HelpViewController.m

#import "HelpViewController.h" 

@interface HelpViewController() 

@end 

@implementation HelpViewController 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    CGRect scrollViewFrame = CGRectMake(0, 62, 320, 404); 
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame]; 
    [self.view addSubview:scrollView]; 
    CGSize scrollViewContentSize = CGSizeMake(640, 404); 
    [scrollView setContentSize:scrollViewContentSize]; 
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 50, 21)]; 
    [label setText:@"Hello"]; 
    [scrollView addSubview:label]; 
    [scrollView setPagingEnabled:YES]; 
    scrollView.showsHorizontalScrollIndicator = NO; 
    UIPageControl *pageControl = [[UIPageControl alloc] init]; 
    pageControl.frame = CGRectMake(110,5,100,100); 
    pageControl.numberOfPages = 2; 
    pageControl.currentPage = 0; 
    [self.view addSubview:pageControl]; 
    pageControl.backgroundColor = [UIColor redColor]; 
} 

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

@end 
+0

He respondido esto correctamente aquí https://stackoverflow.com/questions/3533047/how-do-you-combine-uiscrollview-with-uipagecontrol-to-show-different-views/14230698#14230698 es mejor tener una respuesta en un lugar ... arreglé los cambios propuestos allí. – Renetik

Respuesta

77

Tal vez esto funciona para usted

No se olvide de establecer delegado = self del UIScrollView (o donde usted tiene la selector a continuación).

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    CGFloat pageWidth = self.scrollView.frame.size.width; // you need to have a **iVar** with getter for scrollView 
    float fractionalPage = self.scrollView.contentOffset.x/pageWidth; 
    NSInteger page = lround(fractionalPage); 
    self.pageControl.currentPage = page; // you need to have a **iVar** with getter for pageControl 
} 

Para su código, entonces sería:

archivo .h

#import <UIKit/UIKit.h> 

@interface HelpViewController : UIViewController{ 
} 

@property (nonatomic, retain) UIScrollView *scrollView; 
@property (nonatomic, retain) UIPageControl * pageControl; 
@end 

archivo .m

#import "HelpViewController.h" 

@interface HelpViewController() 

@end 

@implementation HelpViewController 
@synthesize scrollView=scrollView_; 
@synthesize pageControl=pageControl_; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    CGRect scrollViewFrame = CGRectMake(0, 62, 320, 404); 
    self.scrollView = [[[UIScrollView alloc] initWithFrame:scrollViewFrame] autorelease]; 
    self.scrollView.delegate = self; 
    [self.view addSubview:self.scrollView]; 
    CGSize scrollViewContentSize = CGSizeMake(640, 404); 
    [self.scrollView setContentSize:scrollViewContentSize]; 
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 50, 21)]; 
    [label setText:@"Hello"]; 
    [self.scrollView addSubview:label]; 
    [self.scrollView setPagingEnabled:YES]; 
    self.scrollView.showsHorizontalScrollIndicator = NO; 
    self.pageControl = [[[UIPageControl alloc] init] autorelease]; 
    self.pageControl.frame = CGRectMake(110,5,100,100); 
    self.pageControl.numberOfPages = 2; 
    self.pageControl.currentPage = 0; 
    [self.view addSubview:self.pageControl]; 
    pageControl.backgroundColor = [UIColor redColor]; 
} 

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
     CGFloat pageWidth = self.scrollView.frame.size.width; 
     float fractionalPage = self.scrollView.contentOffset.x/pageWidth; 
     NSInteger page = lround(fractionalPage); 
     self.pageControl.currentPage = page; 
    } 


@end 
+0

¡Gracias por la ayuda! La lógica es sólida, pero no entiendo muy bien la implementación. He actualizado mi publicación para incluir mis archivos completos .h y .m. –

+0

¡actualizado! solo copie el código ... :) ... no ha sido probado, quizás haya un error tipográfico. Pero debería funcionar –

+0

Muchas gracias. Me has ahorrado muchos dolores de cabeza.Mi problema terminó siendo con el delegado. –

2

para obtener el índice página exacta y sin redondeo del valor simplemente pon el pagecontrol.currentpage en el método de delegado scrollViewDidEndDecelerating de la vista de desplazamiento. ¡Esto funciona para mí!

51

Esto es bastante simple de configurar. En primer lugar, debe crear la vista de desplazamiento y el control de página. Asegúrese de implementar UIScrollViewDelegate en la interfaz de la clase.

UIScrollView * scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 3, scrollView.frame.size.height); 
    scrollView.delegate = self; 

    UIPageControl * pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 90, scrollView.frame.size.width, 20)]; 
    pageControl.numberOfPages = scrollView.contentSize.width/scrollView.frame.size.width; 
    [pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged]; 

Luego hay que añadir los dos métodos siguientes:

- (IBAction)changePage:(id)sender { 
    CGFloat x = pageControl.currentPage * scrollView.frame.size.width; 
    [scrollView setContentOffset:CGPointMake(x, 0) animated:YES]; 
} 

-(void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    NSInteger pageNumber = roundf(scrollView.contentOffset.x/(scrollView.frame.size.width)); 
    pageControl.currentPage = pageNumber; 
} 

Estos métodos añaden la comunicación necesaria entre el control de la página y la vista de desplazamiento.

+0

Para determinar correctamente el número de página que necesita para múltiples por el pageControl.numberOfPages –

0

Todas estas respuestas son geniales pero me gustaría ofrecer una solución alternativa, ¡usando ReactiveCocoa!

El siguiente código supone que tiene una propiedad llamada scrollView y otra llamada pageControl.

[RACObserve(self.scrollView, contentOffset) 
    subscribeNext:^(NSValue* value){ 
     CGPoint offset = [value CGPointValue]; 
     CGFloat fractional = offset.x/self.scrollView.width; 
     [self.pageControl setCurrentPage:lroundf(fractional)]; 
    }]; 

Todo lo que está pasando aquí es que está observando el cambio en la propiedad de la contentOffset ScrollView y calculando el índice de página en cada próximo evento (es decir, cada vez que cambia el valor de la propiedad).

¡El único inconveniente de esto es que debe desempaquetar el CGPoint pero al alza no se necesita el código UIScrollViewDelegate!

Cuestiones relacionadas