Een van de veranderingen die met iOS 6 werden geïntroduceerd, is de mogelijkheid om de UIPageViewController te gebruiken om een scrolanimatie te gebruiken in plaats van de standaardpaginastijl. Lees verder om te leren hoe we dit kunnen gebruiken om eenvoudig een gepagineerd scrollweergave-effect te maken!
Om deze veranderingen te verkennen, zullen we een "image rater" -toepassing creëren waarin gebruikers door verschillende foto's kunnen vegen en aan elk een beoordeling kunnen geven. Hoewel het uitgangspunt basaal is, biedt het u een goede kans om de UIPageControl met de nieuwe stijl te gaan gebruiken.
Voordat we beginnen, hebben we wat foto's nodig. Spring in Wikipedia en download 5 verschillende foto's die zijn gelicentieerd onder Creative Commons. Maak een nieuw Xcode-project met een lege sjabloon. Noem het "ImageRater" of iets gelijkwaardigs. Zorg er ook voor dat het doelapparaat op de iPad is ingesteld, dat het verhaal is uitgeschakeld en ARC is ingeschakeld.
Dit project zal worden ontworpen om alleen in liggende oriëntatie te worden gebruikt. Voordat we beginnen, open je de projectinstellingen en selecteer je alleen de landschapsoriëntaties.
Vervolgens moeten we het modelobject maken en de controller bekijken die verantwoordelijk is voor het weergeven van de afbeelding. Maak een nieuwe klasse genaamd "ImageModel" die erven van NSObject. Dit is een eenvoudige modelklasse die een tekenreeks bevat die de afbeeldingsbestandsnaam vertegenwoordigt en een geheel getal dat de afbeelding "beoordeling" vertegenwoordigt:
ImageModel.h
@interface ImageModel: NSObject - (id) initWithImageName: (NSString *) imageName; @property (nonatomic, strong) NSString * imageName; @eigenschap (niet-atomair) NSInteger rating; @einde
We hebben ook een aangepaste init-methode gemaakt die het gemakkelijker maakt om deze met een afbeeldingsnaam te maken. In het .m-bestandsimplement werkt de init-methode als volgt:
ImageModel.m
@implementation ImageModel - (id) initWithImageName: (NSString *) imageName self = [super init]; if (self) _imageName = imageName; _rating = 0; terugkeer zelf;
De beeldcontroller die de afbeelding zal weergeven, zal ook heel eenvoudig zijn. Maak een nieuwe klasse met de naam ImageViewController (die UIViewController overneemt) en geef deze de volgende eigenschappen (evenals het importeren van ImageModel.h):
ImageViewController.h
#import "ImageModel.h" @interface ImageViewController: UIViewController @property (nonatomic, strong) UIImageView * imageView; @property (nonatomic, strong) UILabel * label; @property (niet-atomisch, sterk) ImageModel * -model; @einde
En voeg in het .m-bestand de volgende code toe:
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-toewijzing] initWithFrame: insetFrame]; _imageView.backgroundColor = [UIColor clearColor]; [_imageView setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; [_imageView setImage: [UIImage imageNamed: _model.imageName]]; [[zelfweergave] addSubview: _imageView];
Wanneer het beeld wordt geladen, stellen we de achtergrondkleur van de weergave in en stellen we de beeldweergave in.
Maak een nieuwe klasse met de naam "RootViewController" (overerfd van UIViewController). Dit is waar de actie plaatsvindt. Het bevat de PageViewController, het label met de naam en classificatie van de afbeelding, evenals een stepper waarmee de gebruiker de beoordeling voor de afbeelding kan instellen.
Nadat u de klasse hebt gemaakt, opent u het headerbestand van de app-gedelegeerden, importeert u de klasse RootViewController en stelt u deze in als een eigenschap:
AppDelegate.h
#import "RootViewController.h" @interface AppDelegate: UIResponder@property (sterk, niet-atomisch) UIWindow * -venster; @property (strong, nonatomic) RootViewController * viewController; @einde
En in het implementatiebestand stelt u het in als de rootview-controller:
AppDelegate.m
- (BOOL) applicatie: (UIApplication *) applicatie didFinishLaunchingWithOptions: (NSDictionary *) launchOptions self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; // Override-punt voor aanpassing na het starten van de toepassing. self.viewController = [[RootViewController alloc] init]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; terugkeer JA;
Open het .h-bestand van de RootViewController en geef het de volgende eigenschappen en zorg ervoor dat het voldoet aan de methoden UIPageViewControllerDataSource en 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) afzender; @einde
De paginaViewController zal verantwoordelijk zijn voor het weergeven van de ImageViewControllers en de modelserie zal verantwoordelijk zijn voor het opslaan van de imageModel-objecten. De vcIndex is verantwoordelijk voor het bijhouden van de huidige pagina-index. Met RateStepper kan de gebruiker een afbeelding een hoger of lager niveau geven. Het imageLabel geeft de naam en beoordeling van de huidige afbeelding weer.
De stepperValueChanged-methode werkt het relevante afbeeldingsmodel bij dat de beoordeling hoger of lager instelt.
Importeer in het .m-bestand van de RootViewController de ImageViewController en stel de view-controllers in voor de pageview-controller:
RootViewController.m
#import "ImageViewController.h" @implementation RootViewController - (void) viewDidLoad [super viewDidLoad]; [[zelfweergave] 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"], nihil]; _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle: UIPageViewControllerTransitionStyleScroll navigationOrientation: UIPageViewControllerNavigationOrientationHorizontal options: [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat: 50.0f] forKey: UIPageViewControllerOptionInterPageSpacingSleutel]]; _pageViewController.delegate = zelf; _pageViewController.dataSource = self;
Er zijn hier een paar dingen aan de hand. Eerst stellen we onze achtergrondkleur in op zwart. Ten tweede, wij wijzen init onze pageViewController aan met de scollStyle-overgang, de horizontale navigatie-oriëntatie en een woordenboek voor onze opties. Het woordenboek bevat een NSNumber die aangeeft dat er een afstand van 50 punten moet zijn tussen elke viewController. Vervolgens gaan we over naar de gedelegeerde en gegevensbron voor de paginaViewController.
Vervolgens moeten we een eerste viewController instellen om te beginnen met:
RootViewController.m
_pageViewController.delegate = zelf; _pageViewController.dataSource = self; ImageViewController * imageViewController = [[ImageViewController alloc] init]; imageViewController.model = [_modelArray-objectAtIndex: 0]; NSArray * viewControllers = [NSArray arrayWithObject: imageViewController]; [self.pageViewController setViewControllers: viewControllers direction: UIPageViewControllerNavigationDirectionForward geanimeerd: NO completion: nil]; [self addChildViewController: _pageViewController]; [self.view addSubview: _pageViewController.view]; [_pageViewController didMoveToParentViewController: self]; CGRect-paginaViewRect = self.view.bounds; pageViewRect = CGRectInset (pageViewRect, 40.0, 80.0f); self.pageViewController.view.frame = pageViewRect; self.view.gestureRecognizers = _pageViewController.gestureRecognizers;
Hier maken we een nieuwe content view-controller, voegen deze toe aan een array en stellen die array vervolgens in als de eigenschap viewControllers voor onze pageController. Vervolgens voegen we de paginaViewController als onze childViewController en vervolgens de paginaViewControllersView toe aan de onze. We geven het een beetje een inset, zodat het niet de volledige weergave in beslag neemt en onze gebarenherkenners instellen op die van de paginaViewControllers zodat alles synchroon loopt.
Om de weergave te voltooien, moeten we tenslotte de stepper en het label toevoegen dat de afbeelding beschrijft:
RootViewController.m
self.view.gestureRecognizers = _pageViewController.gestureRecognizers; _rateStepper = [[UIStepper alloc] initWithFrame: CGRectMake (40, 680, 40, 30)]; [_rateStepper addTarget: self action: @selector (stepperValueChanged :) forControlEvents: UIControlEventValueChanged]; [_rateStepper setMinimumValue: 0]; [_rateStepper setMaximumValue: 10]; [_rateStepper setIncrementImage: [UIImage imageNamed: @ "arrowup"] forState: UIControlStateNormal]; [_rateStepper setDecrementImage: [UIImage imageNamed: @ "arrowdown"] forState: UIControlStateNormal]; [[zelfweergave] 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]; [[zelfweergave] addSubview: _imageLabel];
Het meeste hiervan zou redelijk eenvoudig moeten zijn. Het belangrijkste om hier op te letten, is waar we de "increment" en "decrement" -afbeeldingen voor de stepperregeling instellen. Je zult hier je eigen afbeeldingen voor moeten zoeken, maar het zou gemakkelijk moeten zijn om een aantal gratis iconen op google te maken of te vinden. Als u dit niet kunt, sla dan eenvoudigweg de stappenmaker over.
Als we onze app nu bouwen en uitvoeren, zou het er ongeveer zo uit moeten zien:
Dit is een goed begin, maar de afbeeldingen scrollen nog niet en de stepper crasht de app. We missen ook de pagina-indicatoren. Laten we die lege plekken invullen:
We moeten de datasource-methoden implementeren die de pagina vertellenViewController welke controllers moeten worden geladen voor en na de huidige:
RootViewController.m
#pragma mark - #pragma mark - UIPageViewControllerDelegate Method - (UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerBeforeViewController: (UIViewController *) viewController ImageViewController * contentVc = (ImageViewController *) viewController; NSUInteger currentIndex = [_modelArray indexOfObject: [contentVc model]]; _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]; return imageViewController; - (UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerAfterViewController: (UIViewController *) viewController ImageViewController * contentVc = (ImageViewController *) viewController; NSUInteger currentIndex = [_modelArray indexOfObject: [contentVc model]]; _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]; return imageViewController;
Beide methoden lijken erg op elkaar. Eerst krijgen we de relevante viewController voor of na de huidige (en naar een ImageViewController gestuurd). Vervolgens kijken we waar de index van dat viewController-model zich verhoudt tot onze modelarray. Eenmaal gevonden, stellen we onze huidige vcIndex-waarde in op de currentIndex. We zorgen er ook voor dat de huidige waarde van de stepper wordt bijgewerkt en dat de labelstring wordt bijgewerkt om de huidige afbeeldingsnaam en beoordelingswaarde weer te geven.
Als de index buiten de grenzen zou zijn (bepaald door 0 of de telling van de modelarray - 1), dan geven we geen nieuwe weergavecontroller terug. Als er een model moet worden geladen, maken we een nieuwe ImageViewController, stellen we het model in op het relevante model in de array en geven we de viewController terug.
Als u nu bouwt en uitvoert, zullen de pagina's scrollen, maar we missen nog steeds de pagina-indicatorweergave. We hoeven alleen de volgende dataSource-methoden te implementeren, zoals hieronder:
RootViewController.m
#pragma mark - #pragma mark - UIPageViewControllerDataSource Method - (NSInteger) presentationCountForPageViewController: (UIPageViewController *) pageViewController return _modelArray.count; - (NSInteger) presentationIndexForPageViewController: (UIPageViewController *) pageViewController return 0;
Het is zo makkelijk. Voor de telmethode retourneren we eenvoudig de telling van de modelarray en voor de huidige index geven we eenvoudig terug waar het moet beginnen, namelijk 0.
Al het harde werk is gedaan! Om de afbeeldingen te rangschikken, implementeer eenvoudig onze "stepperValueChanged" methode en voeg de onderstaande code toe:
RootViewController.m
#pragma mark - #pragma mark - Private Methods - (void) stepperValueChanged: (id) afzender ImageModel * model = [_modelArray objectAtIndex: _vcIndex]; [model setRating: [_ rateStepper value]]; [_imageLabel setText: [NSString stringWithFormat: @ "% @ - Rating:% d", model.imageName, model.rating]];
We krijgen het model gewoon bij de huidige index, werken de classificatie bij op basis van de classificatie van de stepper en werken dan de labeltekst bij.
Bouw en run nu uw applicatie en het zou er ongeveer zo uit moeten zien:
We hebben besproken hoe je een heel eenvoudige PageViewController kunt instellen met behulp van de nieuwe scroll-overgangsstijl zonder het gebruik van een xib of storyboard. Dit zou u een goed begrip moeten geven van hoe de PageViewController werkt en u in staat stellen deze aan uw eigen applicaties aan te passen!