Utilisation de ScrollStyle avec UIPageViewController

L'une des modifications introduites avec iOS 6 est la possibilité d'utiliser UIPageViewController pour utiliser une animation avec défilement au lieu du style de changement de page standard. Poursuivez votre lecture pour savoir comment utiliser ceci pour créer facilement un effet de vue de défilement paginé.!

Pour explorer ces modifications, nous allons créer une application "d'évaluation d'image" où les utilisateurs peuvent faire défiler différentes images et attribuer une note à chacune d'entre elles. Bien que le principe soit basique, cela vous donnera une bonne chance de commencer à utiliser UIPageControl avec le nouveau style..


Étape 1: Mise en place

Avant de commencer, nous aurons besoin de quelques images. Sautez dans Wikipedia et téléchargez 5 images différentes sous licence Creative Commons. Créez un nouveau projet Xcode avec un modèle vide. Nommez-le "ImageRater" ou quelque chose d'équivalent. Assurez-vous également que le périphérique ciblé est configuré sur iPad, que le scénario est désactivé et que ARC est activé..

Ce projet sera conçu pour être utilisé uniquement en orientation paysage. Avant de commencer, ouvrez les paramètres du projet et sélectionnez uniquement les orientations Paysage.


Étape 2: Créer le modèle d'image et le contrôleur de vue

Ensuite, nous devons créer l'objet de modèle et le contrôleur de vue responsables de l'affichage de l'image. Créez une nouvelle classe appelée "ImageModel" héritant de NSObject. Ce sera une classe de modèle simple contenant une chaîne représentant le nom du fichier image et un entier représentant l'image "rating":

ImageModel.h

 @interface ImageModel: NSObject - (id) initWithImageName: (NSString *) imageName; @property (nonatomic, strong) NSString * imageName; @property (nonatomic) NSInteger rating; @fin

Nous avons également créé une méthode d'init personnalisée qui facilitera leur création avec un nom d'image. Dans le fichier .m, implémentez, la méthode init ressemble à ceci:

ImageModèle.m

 @implementation ImageModel - (id) initWithImageName: (NSString *) imageName self = [super init]; if (self) _imageName = imageName; _rating = 0;  retourner soi-même; 

Le contrôleur de vue qui affichera l'image sera également très simple. Créez une nouvelle classe appelée ImageViewController (héritant de UIViewController) et attribuez-lui les propriétés suivantes (en plus d'importer ImageModel.h):

ImageViewController.h

 #import "ImageModel.h" @interface ImageViewController: UIViewController @ property (nonatomique, fort) UIImageView * imageView; @property (nonatomic, strong) UILabel * label; @property (nonatomic, strong) modèle ImageModel *; @fin

Et dans le fichier .m, ajoutez le code suivant:

ImageViewController.m

 - (void) viewDidLoad [super viewDidLoad]; [self.view setBackgroundColor: [UIColor whiteColor]]; CGRect insetFrame = CGRectMake (20, 80, self.view.frame.size.width - 40, self.view.frame.size.height - 100); _imageView = [[UIImageView alloc] initWithFrame: insetFrame]; _imageView.backgroundColor = [UIColor clearColor]; [_imageView setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; [_imageView setImage: [UIImage imageNamed: _model.imageName]]; [[auto view] addSubview: _imageView]; 

Lorsque la vue se charge, nous allons définir la couleur d'arrière-plan des vues et configurer l'imageView.


Étape 3: Configurer le PageViewController

Créez une nouvelle classe appelée "RootViewController" (héritant de UIViewController). Ce sera où l'action se passe. Il contiendra le PageViewController, l'étiquette qui affiche le nom et le classement de l'image, ainsi qu'un stepper qui permet à l'utilisateur de définir le classement de l'image..

Une fois la classe créée, ouvrez le fichier d'en-tête des délégués de l'application, importez la classe RootViewController et définissez-la en tant que propriété:

AppDelegate.h

 #import "RootViewController.h" @interface AppDelegate: UIResponder  @property (strong, nonatomic) UIWindow * fenêtre; @property (strong, nonatomic) RootViewController * viewController; @fin

Et dans le fichier d'implémentation, définissez-le comme contrôleur de vue racine:

AppDelegate.m

 - Application (BOOL): application (UIApplication *) application didFinishLaunchingWithOptions: (NSDictionary *) launchOptions self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen]] borns]]; // Point de remplacement pour la personnalisation après le lancement de l'application. self.viewController = [[RootViewController alloc] init]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; retourner OUI; 

Ouvrez le fichier .h du RootViewController, attribuez-lui les propriétés suivantes et conformez-le aux méthodes UIPageViewControllerDataSource et Delegate:

RootViewController.h

 @interface RootViewController: UIViewController  @property (nonatomic, strong) UIPageViewController * pageViewController; @property (nonatomic, strong) NSMutableArray * modelArray; @property (nonatomic) NSInteger vcIndex; @property (nonatomic, strong) UIStepper * rateStepper; @property (nonatomic, strong) UILabel * imageLabel; - (void) stepperValueChanged: (id) expéditeur; @fin

PageViewController sera responsable de l'affichage des ImageViewControllers et le tableau de modèles sera responsable du stockage des objets imageModel. VcIndex sera responsable de garder une trace de l'index de page actuel. RateStepper permettra à l'utilisateur d'évaluer une image vers le haut ou le bas. L'imageLabel affichera le nom et le classement de l'image actuelle.

La méthode stepperValueChanged met à jour le modèle d'image pertinent en lui attribuant une note supérieure ou inférieure..

Dans le fichier .m de RootViewController, importez ImageViewController et configurez les contrôleurs de vue pour le contrôleur de vue de page:

RootViewController.m

 #import "ImageViewController.h" @implementation RootViewController - (void) viewDidLoad [super viewDidLoad]; [[auto view] setBackgroundColor: [UIColor blackColor]]; _modelArray = [NSMutableArray arrayWithObjects: [[ImageModel alloc] initWithImageName: @ "cat.jpg"], [[ImageModel alloc] initWithImageName: @ "DawnFlight.jpeg"], [[ImageModel alloc] initWithImageName: @ "James.jpg" , [[ImageModel alloc] initWithImageName: @ "MOS_KIM.jpg"], [[ImageModel alloc] initWithImageName: @ "Pterophorus.jpg"], nil]; _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle: UIPageViewControllerTransitionStyleScroll navigationOrientation: UIPageViewControllerNavigationOrientationHorizontal options: _pageViewController.delegate = self; _pageViewController.dataSource = self;

Il y a quelques choses qui se passent ici. Tout d'abord, nous avons défini la couleur d'arrière-plan sur le noir. Deuxièmement, nous allouons à init notre pageViewController avec la transition scollStyle, l’orientation de navigation horizontale et un dictionnaire pour nos options. Le dictionnaire contient un NSNumber indiquant qu'il doit y avoir un espacement de 50 points entre chaque viewController. Nous procédons ensuite à nous définir comme délégué et source de données pour le pageViewController.

Ensuite, nous devons configurer un viewController initial pour commencer avec:

RootViewController.m

 _pageViewController.delegate = self; _pageViewController.dataSource = self; ImageViewController * imageViewController = [[ImageViewController alloc] init]; imageViewController.model = [_modelArray objectAtIndex: 0]; NSArray * viewControllers = [NSArray arrayWithObject: imageViewController]; [self.pageViewController setViewControllers: direction de viewControllers: UIPageViewControllerNavigationDirectionForward animée: NON complétée: nil]; [auto addChildViewController: _pageViewController]; [self.view addSubview: _pageViewController.view]; [_pageViewController didMoveToParentViewController: self]; CGRect pageViewRect = self.view.bounds; pageViewRect = CGRectInset (pageViewRect, 40.0, 80.0f); self.pageViewController.view.frame = pageViewRect; self.view.gestureRecognizers = _pageViewController.gestureRecognizers;

Ici, nous créons un nouveau contrôleur de vue de contenu, l'ajoutons à un tableau, puis définissons ce tableau en tant que propriété viewControllers pour notre pageController. Ensuite, nous ajoutons le pageViewController en tant que notre childViewController, puis le pageViewControllersView au nôtre. Nous lui donnons ensuite un peu d'insert pour qu'il ne prenne pas la totalité de la vue et que nos identifiants de mouvements soient identiques à ceux de pageViewControllers afin que tout soit synchronisé..

Enfin, pour terminer la vue, nous devons ajouter le stepper et l'étiquette décrivant l'image:

RootViewController.m

 self.view.gestureRecognizers = _pageViewController.gestureRecognizers; _rateStepper = [[UIStepper alloc] initWithFrame: CGRectMake (40, 680, 40, 30)]; [_rateStepper addTarget: action propre: @selector (stepperValueChanged :) pour forControlEvents: UIControlEventValueChanged]; [_rateStepper setMinimumValue: 0]; [_rateStepper setMaximumValue: 10]; [_rateStepper setIncrementImage: [UIImage imageNamed: @ "arrowup"] pourState: UIControlStateNormal]; [_rateStepper setDecrementImage: [UIImage imageNamed: @ "arrowdown"] pourState: UIControlStateNormal]; [[auto view] addSubview: _rateStepper]; _imageLabel = [[UILabel alloc]] initWithFrame: CGRectMake (0, 0, self.view.frame.size.width, 40)]; _imageLabel.backgroundColor = [UIColor clearColor]; _imageLabel.textColor = [UIColor whiteColor]; [_imageLabel setFont: [UIFont boldSystemFontOfSize: 20]]; [_imageLabel setAutoresizingMask: UIViewAutoresizingFlexibleWidth]; [_imageLabel setTextAlignment: NSTextAlignmentCenter]; ImageModel * model = [_modelArray objectAtIndex: 0]; _imageLabel.text = [NSString stringWithFormat: @ "% @ - Rating:% d", model.imageName, model.rating]; [[auto view] addSubview: _imageLabel]; 

La plupart de cela devrait être assez simple. La principale chose à faire attention ici est où nous définissons les images "incrémenter" et "décrémenter" pour le contrôle pas à pas. Vous aurez besoin de trouver vos propres images pour cela, mais il devrait être facile de créer ou de trouver des icônes gratuites sur Google. Si vous ne pouvez pas faire cela, vous pouvez simplement ignorer la personnalisation du stepper.

Si nous construisons et exécutons notre application maintenant, elle devrait ressembler à ceci:

C'est un bon début, mais les images ne défilent pas encore et le stepper bloque l'application. Nous manquons également les indicateurs de page. Remplissons ces blancs:


Étape 4: Terminer le PageViewController

Nous devons implémenter les méthodes de source de données qui indiquent au pageViewController quels contrôleurs de vue doivent être chargés avant et après le contrôleur actuel:

RootViewController.m

 #pragma mark - #pragma mark - Méthode UIPageViewControllerDelegate - (UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerBeforeViewController: (UIViewController *) NSUInteger currentIndex = [_modelArray indexOfObject: [modèle contentVc]]; _vcIndex = currentIndex; [_rateStepper setValue: [[contentVc model] rating]]; ImageModel * model = [_modelArray objectAtIndex: _vcIndex]; [_imageLabel setText: [NSString stringWithFormat: @ "% @ - Rating:% d", model.imageName, model.rating]]; if (currentIndex == 0) return nil;  ImageViewController * imageViewController = [[ImageViewController alloc] init]; imageViewController.model = [_modelArray objectAtIndex: currentIndex - 1]; retourne imageViewController;  - (UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerAfterViewController: (UIViewController *) viewController ImageViewController * contentVc = (ImageViewController *); NSUInteger currentIndex = [_modelArray indexOfObject: [modèle contentVc]]; _vcIndex = currentIndex; [_rateStepper setValue: [[contentVc model] rating]]; ImageModel * model = [_modelArray objectAtIndex: _vcIndex]; [_imageLabel setText: [NSString stringWithFormat: @ "% @ - Rating:% d", model.imageName, model.rating]]; if (currentIndex == _modelArray.count - 1) return nil;  ImageViewController * imageViewController = [[ImageViewController alloc] init]; imageViewController.model = [_modelArray objectAtIndex: currentIndex + 1]; retourne imageViewController; 

Ces deux méthodes sont assez similaires. Tout d'abord, nous obtenons le viewController approprié avant ou après l'actuel (et le convertissons en un ImageViewController). Nous cherchons ensuite où est l'index du modèle de ce viewController par rapport à notre tableau de modèles. Une fois trouvé, nous définissons notre valeur vcIndex actuelle sur currentIndex. Nous nous assurons également de mettre à jour la valeur actuelle du stepper et de mettre à jour la chaîne d'étiquette pour afficher le nom de l'image actuelle et la valeur d'évaluation..

Si l'index est hors limites (déterminé par une valeur égale à 0 ou au nombre de modèles du tableau - 1), nous ne renvoyons pas de nouveau contrôleur de vue. Si un modèle doit être chargé, nous créons un nouveau ImageViewController, définissons son modèle sur le modèle approprié du tableau et renvoyons le viewController..

Si vous construisez et exécutez maintenant, les pages défileront, mais la vue Indicateur de page nous manque encore. Nous avons seulement besoin d'implémenter les méthodes dataSource suivantes comme ci-dessous:

RootViewController.m

 #pragma mark - #pragma mark - UIPageViewControllerDataSource, méthode - (NSInteger) presentationCountForPageViewController: (UIPageViewController *) pageViewController return _modelArray.count;  - (NSInteger) presentationIndexForPageViewController: (UIPageViewController *) pageViewController return 0; 

C'est si facile. Pour la méthode count, nous renvoyons simplement le décompte du tableau de modèle et pour l'indice actuel, nous renvoyons simplement ce dont il a besoin pour commencer, à savoir 0.


Étape 5: Noter les images

Le plus dur a été fait! Pour classer les images, implémentez simplement notre méthode "stepperValueChanged" et ajoutez le code ci-dessous:

RootViewController.m

 #pragma mark - #pragma mark - Méthodes privées - (void) stepperValueChanged: expéditeur (id) ImageModel * model = [_modelArray objectAtIndex: _vcIndex]; [model setRating: [_ rateStepper value]]; [_imageLabel setText: [NSString stringWithFormat: @ "% @ - Rating:% d", model.imageName, model.rating]]; 

Nous obtenons simplement le modèle à l'index actuel, mettons à jour son classement en fonction du classement des steppers, puis mettons à jour le texte de l'étiquette..

Générez et exécutez votre application maintenant et elle devrait ressembler à ceci:


Emballer

Nous avons expliqué comment configurer un PageViewController très simple en utilisant le nouveau style de transition de défilement sans utiliser de xib ou de storyboard. Cela devrait vous donner une solide compréhension du fonctionnement de PageViewController et vous permettre de le modifier pour qu'il fonctionne dans vos propres applications.!