web-dev-qa-db-fra.com

Lier par programme UIPageControl à UIScrollView

Je crée un simple diaporama dans mon application. Je voudrais lier mon UIPageControl à mon UIScrollView. Cela ne devrait pas être trop difficile, mais je n'ai pu trouver de solution simple nulle part. Voici mon code.

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
53
Dan Carew

Peut-être que cela fonctionne pour vous

N'oubliez pas de définir le délégué UIScrollView = self (ou partout où vous avez le sélecteur ci-dessous).

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

Pour votre code ce serait alors:

fichier .h

#import <UIKit/UIKit.h>

@interface HelpViewController : UIViewController{
}

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

fichier .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
79
Jonas Schnelli

C'est en fait assez simple à configurer. Tout d'abord, vous devez créer la vue de défilement et le contrôle de page. Assurez-vous d'implémenter UIScrollViewDelegate dans l'interface de la classe.

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

Ensuite, vous devez ajouter les deux méthodes suivantes:

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

Ces méthodes ajoutent la communication requise entre le contrôle de page et la vue de défilement.

53
Ben Smiley

Le code suivant fonctionnera pour 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))
}
3
Bilal

pour obtenir un index de page exact sans arrondir la valeur, placez simplement pagecontrol.currentpage dans la méthode déléguée scrollViewDidEndDecelerating de la vue de défilement. Cela fonctionne pour moi!

2
Harshit K

Toutes ces réponses sont excellentes mais j'aimerais proposer une solution alternative, en utilisant ReactiveCocoa !

Le code suivant suppose que vous avez une propriété appelée scrollView et une appelée pageControl.

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

Tout ce qui se passe ici, c'est que vous observez des changements dans la propriété contentOffset de scrollView et calculez l'index de la page à chaque événement suivant (c'est-à-dire chaque fois que la valeur de la propriété change).

Le seul inconvénient est que vous devez déballer le CGPoint mais à la hausse il n'y a aucun code UIScrollViewDelegate nécessaire du tout!

0
barndog