objective guide framework developer apple apis objective-c cocoa-touch ios uiscrollview uiinterfaceorientation

objective-c - guide - swift ios documentation



UIScrollView con páginas habilitadas y cambios de rotación/orientación del dispositivo(MADNESS) (4)

Estoy teniendo dificultades para hacer esto bien.

Tengo un UIScrollView, con la paginación habilitada. Es administrado por un controlador de vista (MainViewController) y cada página es administrada por un PageViewController, su vista se agrega como una subvista de scrollView con el desplazamiento correcto. El desplazamiento es de izquierda a derecha, para la aplicación de iPhone de orientación estándar. Funciona bien. Básicamente, exactamente igual que la muestra provista por Apple y también como la aplicación Weather provista con el iPhone.

Sin embargo, cuando trato de apoyar otras orientaciones, las cosas no funcionan muy bien. He apoyado todas las orientaciones tanto en MainViewController como en PageViewController con este método:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; }

Sin embargo, cuando giro el dispositivo, mis páginas se vuelven bastante inclinadas y hay muchos fallos de dibujo, especialmente si solo se han cargado algunas de las páginas, luego giro, luego me desplazo más, etc. Muy desordenado.

He dicho a mis puntos de vista para apoyar el cambio de tamaño automático con

theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Pero fue en vano. Parece simplemente estirar y distorsionar mis puntos de vista.

En mi MainViewController, agregué esta línea en un intento de cambiar el tamaño de las vistas de todas mis páginas:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * ([self.viewControllers count]), self.scrollView.frame.size.height); for (int i = 0; i < [self.viewControllers count]; i++) { PageViewController *controller = [self.viewControllers objectAtIndex:i]; if ((NSNull *)controller == [NSNull null]) continue; NSLog(@"Changing frame: %d", i); CGRect frame = self.scrollView.frame; frame.origin.x = frame.size.width * i; frame.origin.y = 0; controller.view.frame = frame; } }

Pero no sirvió de mucho (porque cargué las vistas de forma perezosa, por lo que no todas se cargan necesariamente cuando esto se ejecuta).

¿Hay alguna manera de resolver este problema?


Además de lo que escribió Efrain, tenga en cuenta que la propiedad de marco NO ES VÁLIDA si la transformación de la vista es distinta de la transformación de identidad, es decir , cuando se gira la vista.

Por supuesto, usted tuvo en cuenta el hecho de que sus vistas deben estar en una nueva posición de compensación, ¿verdad?


Lo he logrado con éxito utilizando el método siguiente:

Código de archivo .h:

@interface ScrollViewController2 : UIViewController <UIWebViewDelegate, UIScrollViewDelegate> { NSMutableArray *views; int currentPage; IBOutlet UIScrollView *scrollView; BOOL bolPageControlUsed; int intCurrIndex; NSMutableArray *arrayContentData; NSMutableArray *viewControllers; } @property (nonatomic, retain) IBOutlet UIScrollView *scrollView; @property (nonatomic, retain) NSMutableArray *arrayContentData; @property (nonatomic, retain) NSMutableArray *viewControllers; @property (nonatomic) BOOL bolPageControlUsed; @property (nonatomic) int intCurrIndex; -(void)bindPages; - (void)setUpScrollView; - (void)alignSubviews; - (NSURLRequest *)getPageFromDocumentsDirectory:(NSString *)pstrPageName; -(void)initiateScrollView; -(void)loadScrollViewWithPage:(int)page;

================================================== ==========================================

archivo .m

@synthesize scrollView;

@synthesize arrayContentData, viewControllers, bolPageControlUsed, intCurrIndex;

- (void)viewDidLoad { [super viewDidLoad]; [self bindPages]; //[self setUpScrollView]; [self initiateScrollView]; } #pragma mark - #pragma mark Bind Pages -(void)bindPages{ self.arrayContentData = [[NSMutableArray alloc] init]; [self.arrayContentData addObject:@"1.html"]; [self.arrayContentData addObject:@"2.html"]; [self.arrayContentData addObject:@"3.html"]; [self.arrayContentData addObject:@"4.html"]; [self.arrayContentData addObject:@"5.html"]; [self.arrayContentData addObject:@"6.html"]; [self.arrayContentData addObject:@"1.html"]; [self.arrayContentData addObject:@"2.html"]; [self.arrayContentData addObject:@"3.html"]; [self.arrayContentData addObject:@"4.html"]; [self.arrayContentData addObject:@"5.html"]; [self.arrayContentData addObject:@"6.html"]; [self.arrayContentData addObject:@"1.html"]; [self.arrayContentData addObject:@"2.html"]; [self.arrayContentData addObject:@"3.html"]; [self.arrayContentData addObject:@"4.html"]; [self.arrayContentData addObject:@"5.html"]; [self.arrayContentData addObject:@"6.html"]; [self.arrayContentData addObject:@"1.html"]; [self.arrayContentData addObject:@"2.html"]; [self.arrayContentData addObject:@"3.html"]; [self.arrayContentData addObject:@"4.html"]; [self.arrayContentData addObject:@"5.html"]; [self.arrayContentData addObject:@"6.html"]; } #pragma mark - #pragma mark Get Filename from Document Directory - (NSURLRequest *)getPageFromDocumentsDirectory:(NSString *)pstrPageName { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentDirectory = [paths objectAtIndex:0]; NSString *yourFilePath = [NSString stringWithFormat:@"%@/Html/%@", documentDirectory, pstrPageName]; NSURL *url = [NSURL fileURLWithPath:yourFilePath]; NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; return requestObj; } #pragma mark - #pragma mark ScrollView Methods -(void)initiateScrollView{ views = [[NSMutableArray alloc] initWithCapacity:[self.arrayContentData count]]; NSMutableArray *controllers = [[NSMutableArray alloc] init]; for (unsigned i = 0; i < [self.arrayContentData count]; i++) { [controllers addObject:[NSNull null]]; } self.viewControllers = controllers; [controllers release]; scrollView.contentSize = CGSizeMake([self.arrayContentData count]*scrollView.bounds.size.width, scrollView.bounds.size.height); scrollView.delegate = self; if(self.intCurrIndex == 0){ [self loadScrollViewWithPage:self.intCurrIndex]; } } -(void)loadScrollViewWithPage:(int)page{ if (page < 0) return; if (page >= [self.arrayContentData count]) return; // replace the placeholder if necessary NSString *strContentName = [self.arrayContentData objectAtIndex:page]; //UIImageView *controller = [viewControllers objectAtIndex:page]; UIWebView *controller = [viewControllers objectAtIndex:page]; if ((NSNull *)controller == [NSNull null]) { UIView *v = [[UIView alloc] initWithFrame:scrollView.bounds]; v.backgroundColor = [UIColor colorWithHue:arc4random()/(float)0x100000000 saturation:0.75 brightness:1.0 alpha:1.0]; controller = [[UIWebView alloc] initWithFrame:v.bounds]; controller.delegate = self; controller.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; controller.center = CGPointMake(v.bounds.size.width/2, v.bounds.size.height/2); [controller loadRequest:[self getPageFromDocumentsDirectory:strContentName]]; [v addSubview:controller]; [controller release]; [scrollView addSubview:v]; [views addObject:v]; [viewControllers replaceObjectAtIndex:page withObject:controller]; [v release]; } [self alignSubviews]; /* // add the controller''s view to the scroll view if (nil == controller.superview) { CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * page; //frame.origin.y = 0; controller.frame = frame; [scrollView addSubview:controller]; }*/ } -(void)scrollViewDidScroll:(UIScrollView *)sender{ // We don''t want a "feedback loop" between the UIPageControl and the scroll delegate in // which a scroll event generated from the user hitting the page control triggers updates from // the delegate method. We use a boolean to disable the delegate logic when the page control is used. if (self.bolPageControlUsed) { // do nothing - the scroll was initiated from the page control, not the user dragging return; } // Switch the indicator when more than 50% of the previous/next page is visible currentPage = scrollView.contentOffset.x / scrollView.bounds.size.width; [self loadScrollViewWithPage:currentPage]; }

// Al final de la animación de desplazamiento, reinicie el valor booleano utilizado cuando los desplazamientos se originan en UIPageControl - (void) scrollViewDidEndDecelerating: (UIScrollView *) scrollView {self.bolPageControlUsed = NO; }

#pragma mark - #pragma mark setUp ScrollView - (void)setUpScrollView { // Set up some colorful content views views = [[NSMutableArray alloc] initWithCapacity:[self.arrayContentData count]]; for (int i = 0; i < [self.arrayContentData count]; i++) { UIView *v = [[UIView alloc] initWithFrame:scrollView.bounds]; v.backgroundColor = [UIColor colorWithHue:arc4random()/(float)0x100000000 saturation:0.75 brightness:1.0 alpha:1.0]; NSString *strContentName = [self.arrayContentData objectAtIndex:i]; UIWebView *controller = [[UIWebView alloc] initWithFrame:v.bounds]; controller.delegate = self; controller.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; controller.center = CGPointMake(v.bounds.size.width/2, v.bounds.size.height/2); [controller loadRequest:[self getPageFromDocumentsDirectory:strContentName]]; [v addSubview:controller]; [controller release]; [scrollView addSubview:v]; [views addObject:v]; [v release]; } [self alignSubviews]; [scrollView flashScrollIndicators]; } #pragma mark - #pragma mark Align Scroll Subviews - (void)alignSubviews { // Position all the content views at their respective page positions scrollView.contentSize = CGSizeMake([self.arrayContentData count]*scrollView.bounds.size.width, scrollView.bounds.size.height); NSUInteger i = 0; for (UIView *v in views) { v.frame = CGRectMake(i * scrollView.bounds.size.width, 0, scrollView.bounds.size.width, scrollView.bounds.size.height); for (UIWebView *w in v.subviews) { [w setFrame:v.bounds]; } i++; } } #pragma mark - #pragma mark UIWebView delegate - (void)webViewDidStartLoad:(UIWebView *)webView { } - (void)webViewDidFinishLoad:(UIWebView *)webView { } #pragma mark - #pragma mark Orientation // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return YES; } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { currentPage = scrollView.contentOffset.x / scrollView.bounds.size.width; } - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration { [self alignSubviews]; //NSLog(@"%f", currentPage * scrollView.bounds.size.width); scrollView.contentOffset = CGPointMake(currentPage * scrollView.bounds.size.width, 0); }

Espero que sea de utilidad para todos.

Aclamaciones.


No estoy absolutamente seguro de entenderte bien ... sin embargo, algunos pensamientos:

La propiedad de marco es una cosa (A), la forma en que se muestran los contenidos de la vista es otra (B). El marco CGRect es el límite (teórico) de su vista en la vista de supervisión (vista principal). Sin embargo, su Vista no necesariamente tiene que llenar toda el área del marco .

Con respecto a (A): Aquí tenemos la propiedad de máscara de autorización de autoresizingMask para establecer cómo se redimensiona el marco cuando se redimensiona la supervisión. Lo que sucede cuando cambias la orientación. Sin embargo, normalmente puede confiar en la configuración predeterminada (funcionó para mí hasta ahora).

Respecto a (B): la propiedad contentMode de UIView especifica cómo se distribuyen los contenidos de la vista en el marco de la vista. Con esta propiedad, puede establecer que la relación de aspecto debe permanecer intacta. Establézcalo en UIViewContentModeScaleAspectFit por ejemplo, o algo más ...

vea aquí: http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW99

PD: escribí "teórico", porque los contenidos de tu vista también pueden exceder esos límites de marco, solo limitan la vista cuando la propiedad clipsToBounds de UIView se establece en SÍ. Creo que es un error que Apple establezca esto en NO de forma predeterminada.


Si entiendo su pregunta correctamente, la respuesta se da en esta excelente presentación de la WWDC: https://deimos.apple.com/WebObjects/Core.woa/BrowsePrivately/adc.apple.com.4092349126.04109539109.4144345585?i=1699219987 (Nota que tienes que ser un desarrollador de iPhone registrado para acceder a estos videos).

Por cierto, ¿es necesario tener un UIViewController (PageViewController) separado para cada página en su UIScrollView? Por qué no dejas que tu MainViewController se encargue de esto.

Cambiar el tamaño de sus vistas (y su interfaz de usuario en general) después de rotar el dispositivo es mucho más fácil cuando construye su interfaz de usuario en Interface Builder.

Una vez más, recomiendo la sesión WWDC vinculada anteriormente, ya que me ayudó bastante con las vistas de desplazamiento paginadas y cómo manejar la rotación.

¡La mejor de las suertes!