Vinculación programática de UIPageControl a UIScrollView


Estoy haciendo una vista de presentación simple 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 ningún lugar. A continuación está mi código.

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
Author: Jeff Mercado, 2012-04-18

5 answers

Tal vez esto funcione para usted

No se olvide de establecer el delegado de UIScrollView = self (o donde tenga el 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:

.h file

#import <UIKit/UIKit.h>

@interface HelpViewController : UIViewController{
}

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

.m file

#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
 77
Author: Jonas Schnelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-18 10:05:52

Esto es en realidad 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 debe agregar los siguientes dos métodos:

- (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 agregan la comunicación requerida entre el control de página y la vista de desplazamiento.

 52
Author: Ben Smiley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-17 12:26:03

Para obtener el índice exacto de la página sin redondear el valor simplemente coloque el control de página.currentpage en el método de delegado scrollViewDidEndDecelerating de la vista de desplazamiento.Esto funciona para mí!

 2
Author: Harshit K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-26 07:36:09

El siguiente código funcionará para Swift:

func addScrollView() {        
    let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
    let numberOfPages: CGFloat = 4
    scrollView.contentSize = CGSize(width: scrollView.frame.width * numberOfPages, height: scrollView.frame.height * numberOfPages)
    scrollView.delegate = self
    scrollView.isPagingEnabled = true

    let pageControl = UIPageControl(frame: CGRect(x: 0, y: scrollView.frame.height - 37, width: scrollView.frame.width, height: 37))
    pageControl.numberOfPages = Int(numberOfPages)
    pageControl.currentPage = 0
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let value = scrollView.contentOffset.x / scrollView.frame.size.width
    pageControl.currentPage = Int(round(value))
}
 1
Author: Bilal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-14 21:12:26

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

El siguiente código supone que usted tiene una propiedad llamada scrollView y una 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 contentOffset del ScrollView y calculando el índice de página en cada evento siguiente (es decir, cada vez que cambia el valor de la propiedad).

El único inconveniente de esto es que tienes que unbox el CGPoint pero en el lado positivo no hay código UIScrollViewDelegate necesario en absoluto!

 0
Author: barndog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-16 18:28:51