Usando ScrollStyle con UIPageViewController

Uno de los cambios introducidos con iOS 6 es la capacidad de usar UIPageViewController para usar una animación de desplazamiento en lugar del estilo de giro de página estándar. Siga leyendo para saber cómo podemos usar esto para crear fácilmente un efecto de vista de desplazamiento paginado.!

Para explorar estos cambios, crearemos una aplicación de "evaluador de imágenes" en la que los usuarios pueden deslizar diferentes imágenes y darles una calificación a cada una. Aunque la premisa es básica, le dará una buena oportunidad de comenzar a usar UIPageControl con el nuevo estilo..


Paso 1: Configuración

Antes de comenzar, necesitaremos algunas fotos. Salte a Wikipedia y descargue 5 imágenes diferentes que están autorizadas bajo una propiedad creativa. Crea un nuevo proyecto de Xcode con una plantilla vacía. Denomínelo "ImageRater" o algo equivalente. También asegúrate de que el dispositivo seleccionado esté configurado para iPad, la narración está desactivada y ARC está activado.

Este proyecto se diseñará para ser utilizado solo en orientación horizontal. Antes de comenzar, abra la configuración del proyecto y seleccione solo las orientaciones del paisaje.


Paso 2: crear el modelo de imagen y ver el controlador

A continuación, debemos crear el objeto modelo y ver el controlador responsable de mostrar la imagen. Cree una nueva clase llamada "ImageModel" heredando de NSObject. Esta será una clase de modelo simple que contiene una cadena que representa el nombre del archivo de imagen y un entero que representa la "calificación" de la imagen:

ImageModel.h

 @interface ImageModel: NSObject - (id) initWithImageName: (NSString *) imageName; @property (nonatomic, strong) NSString * imageName; @ propiedad (no atómica) calificación de NSInteger; @fin

También hemos creado un método de inicio personalizado que facilitará su creación con un nombre de imagen. En la implementación del archivo .m, el método init es así:

ImageModel.m

 @implementation ImageModel - (id) initWithImageName: (NSString *) imageName self = [super init]; if (self) _imageName = imageName; _rating = 0;  devuélvete a ti mismo; 

El controlador de vista que mostrará la imagen también será muy simple. Cree una nueva clase llamada ImageViewController (heredando UIViewController) y asígnele las siguientes propiedades (además de importar ImageModel.h):

ImageViewController.h

 #importar "ImageModel.h" @interface ImageViewController: UIViewController @property (nonatomic, strong) UIImageView * imageView; @property (nonatomic, strong) etiqueta UILabel *; Modelo @Modelo (no atómico, fuerte) de ImageModel *; @fin

Y en el archivo .m, agregue el siguiente código:

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]]; [[vista propia] addSubview: _imageView]; 

Cuando se cargue la vista, estableceremos el color de fondo de las vistas y configuraremos la imagen..


Paso 3: Configurar el controlador de PageView

Cree una nueva clase llamada "RootViewController" (heredando de UIViewController). Aquí será donde suceda la acción. Contendrá el PageViewController, la etiqueta que muestra el nombre y la clasificación de la imagen, así como un paso a paso que le permite al usuario establecer la calificación de la imagen.

Una vez que haya creado la clase, abra el archivo de encabezado de los delegados de la aplicación, importe la clase RootViewController y configúrela como una propiedad:

AppDelegate.h

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

Y en el archivo de implementación, configúrelo como el controlador de vista raíz:

AppDelegate.m

 - Aplicación (BOOL): (UIApplication *) aplicación didFinishLaunchingWithOptions: (NSDictionary *) launchOptions self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] lines]]; // Punto de reemplazo para la personalización después del inicio de la aplicación. self.viewController = [[RootViewController alloc] init]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; devuelve SÍ; 

Abra el archivo .h del RootViewController y asígnele las siguientes propiedades y haga que se ajuste a los métodos UIPageViewControllerDataSource y 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 (no atómico, fuerte) UILabel * imageLabel; - (void) stepperValueChanged: (id) sender; @fin

PageViewController será responsable de mostrar los ImageViewControllers y la matriz del modelo será responsable de almacenar los objetos imageModel. El vcIndex será responsable de realizar un seguimiento del índice de la página actual. RateStepper permitirá al usuario calificar una imagen hacia arriba o hacia abajo. La imageLabel mostrará el nombre y la clasificación de la imagen actual..

El método stepperValueChanged actualizará el modelo de imagen relevante y su calificación aumentará o disminuirá.

En el archivo .m del RootViewController, importe ImageViewController y configure los controladores de vista para el controlador de vista de página:

RootViewController.m

 #import "ImageViewController.h" @implementation RootViewController - (void) viewDidLoad [super viewDidLoad]; [[vista propia] 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: UIPageViewControllerNavigationOrationation por lo que se refiere a las partes de los animales y de los animales de los Estados Unidos. _pageViewController.delegate = self; _pageViewController.dataSource = self;

Hay algunas cosas que suceden aquí. Primero, configuramos nuestro color de fondo a negro. En segundo lugar, asignamos init a nuestro pageViewController con la transición de scollStyle, la orientación de navegación horizontal y un diccionario para nuestras opciones. El diccionario contiene un NSNumber que indica que debe haber un espacio de 50 puntos entre cada viewController. Luego procedemos a establecernos como delegado y fuente de datos para pageViewController.

A continuación, necesitamos configurar un viewController inicial para comenzar con:

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: viewControllers direction: UIPageViewControllerNavigationDirectionForward animated: NO completar: nil]; [self 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;

Aquí creamos un nuevo controlador de vista de contenido, lo agregamos a una matriz y luego lo configuramos como la propiedad viewControllers para nuestro controlador de página. A continuación, agregamos el pageViewController como nuestro childViewController y luego el pageViewControllersView al nuestro. Luego le damos un pequeño recuadro para que no ocupe toda la vista y establezca nuestros reconocedores de gestos en el de los controladores de la página para que todo esté sincronizado..

Finalmente, para finalizar la vista, debemos agregar el paso a paso y la etiqueta que describe la imagen:

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]; [[vista propia] 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: @ "% @ - Calificación:% d", model.imageName, model.rating]; [[vista propia] addSubview: _imageLabel]; 

La mayoría de esto debería ser bastante sencillo. Lo principal a lo que se debe prestar atención aquí es cuando establecemos las imágenes de "incremento" y "disminución" para el control paso a paso. Necesitará encontrar sus propias imágenes para esto, pero debería ser fácil de hacer o encontrar algunos íconos gratuitos en google. Si no puede hacer esto, simplemente puede omitir la personalización del paso a paso..

Si construimos y ejecutamos nuestra aplicación ahora, debería verse algo como esto:

Este es un buen comienzo, pero las imágenes aún no se desplazan y el paso a paso bloquea la aplicación. También nos faltan los indicadores de la página. Vamos a llenar esos espacios en blanco:


Paso 4: Completar el PageViewController

Necesitamos implementar los métodos de fuente de datos que le digan a pageViewController qué controladores de vista deben cargarse antes y después del actual:

RootViewController.m

 #pragma mark - #pragma mark - UIPageViewControllerDelegate Method - (UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerBeforeViewController  

NSUInteger currentIndex = [_modelArray indexOfObject: [contentVc model]]; _vcIndex = currentIndex; [_rateStepper setValue: [[contentVc model] rating]]; ImageModel * model = [_modelArray objectAtIndex: _vcIndex]; [_imageLabel setText: [NSString stringWithFormat: @ "% @ - Clasificación:% d", model.imageName, model.rating]]; if (currentIndex == 0) return nil; ImageViewController * imageViewController = [[ImageViewController alloc] init]; imageViewController.model = [_modelArray objectAtIndex: currentIndex - 1]; devuelve 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: @ "% @ - Clasificación:% d", model.imageName, model.rating]]; if (currentIndex == _modelArray.count - 1) return nil; ImageViewController * imageViewController = [[ImageViewController alloc] init]; imageViewController.model = [_modelArray objectAtIndex: currentIndex + 1]; devuelve imageViewController;

Ambos métodos son bastante similares. Primero, obtenemos el viewController relevante antes o después del actual (y lo convertimos en un ImageViewController). Luego buscamos para encontrar dónde está el índice del modelo de ese viewController en relación con nuestra matriz de modelos. Una vez encontrado, establecemos nuestro valor actual de vcIndex en currentIndex. También nos aseguramos de actualizar el valor actual del stepper y actualizar la cadena de etiquetas para mostrar el nombre de la imagen actual y el valor de clasificación.

Si el índice estaría fuera de los límites (determinado por la igualación de 0 o el conteo de la matriz del modelo - 1), entonces no devolvemos un nuevo controlador de vista. Si hay un modelo para cargar, creamos un nuevo ImageViewController, configuramos su modelo al modelo relevante en la matriz y devolvemos el viewController.

Si compila y ejecuta ahora, las páginas se desplazarán, sin embargo, todavía nos falta la vista del indicador de página. Solo necesitamos implementar los siguientes métodos de fuente de datos de la siguiente manera:

RootViewController.m

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

Es fácil. Para el método de conteo, simplemente devolvemos el conteo de la matriz del modelo y para el Índice actual simplemente devolvemos lo que necesita para comenzar, que es 0.


Paso 5: Clasificación de las imágenes

¡Todo el trabajo duro se ha hecho! Para clasificar las imágenes, simplemente implemente nuestro método "stepperValueChanged" y agregue el siguiente código:

RootViewController.m

 #pragma mark - #pragma mark - Private Methods - (void) stepperValueChanged: (id) sender ImageModel * model = [_modelArray objectAtIndex: _vcIndex]; [model setRating: [_ rateStepper value]]; [_imageLabel setText: [NSString stringWithFormat: @ "% @ - Clasificación:% d", model.imageName, model.rating]]; 

Simplemente obtenemos el modelo en el índice actual, actualizamos su calificación según la calificación de los steppers y luego actualizamos el texto de la etiqueta..

Cree y ejecute su aplicación ahora y debería tener un aspecto similar al siguiente:


Envolver

Hemos cubierto cómo configurar un PageViewController muy simple usando el nuevo estilo de transición de desplazamiento sin el uso de un xib o un guión gráfico. Esto debería proporcionarle una comprensión sólida de cómo funciona PageViewController y permitirle modificarlo para que funcione en sus propias aplicaciones.!