I am a beginner with Objective-C and I am working on existing code base.
In the following code, UITapGestureRecognizer doesn't seem to trigger tap method. I have tried adding
[self setUserInteractionEnabled:YES];
Can anyone help me figure out what is not working here.
This is my UITableViewCell implementation class:
#interface ELCAssetCell ()
#property(nonatomic, strong) NSArray * rowAssets;
#property(nonatomic, strong) NSMutableArray * rowViews;
#end
#implementation ELCAssetCell
#synthesize rowAssets;
- (id)initWithReuseIdentifier:(NSString *)_identifier cellWidth:(CGFloat)width {
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:_identifier]) {
self.rowViews = [[NSMutableArray alloc] init];
for (int i = 0; i < 4; i++) {
[self.rowViews addObject:[[AssetView alloc] initWithFrame:CGRectZero]];
}
for (AssetView * view in self.rowViews) {
[self addSubview:view];
}
_width = width;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat itemWidth = _width / 4;
CGRect frame = CGRectMake(2, 2, itemWidth - 4, itemWidth - 4);
for (AssetView * view in self.rowViews) {
[view setFrame:frame];
[[view gestureRecognizers] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL
*stop) {
[view removeGestureRecognizer:obj];
}];
[view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tap:)]];
frame.origin.x += itemWidth;
}
}
- (void)tap:(UITapGestureRecognizer *)gest {
[self.delegate assetPressed:[(AssetView *)[gest view] asset]];
[(AssetView *)[gest view] toggleSelection];
}
#end
The most likely problem is that you are adding the views to the cell itself -- they should be added to the cell's contentView.
Change:
for (AssetView * view in self.rowViews) {
[self addSubview:view];
}
to:
for (AssetView * view in self.rowViews) {
[self.contentView addSubview:view];
}
Aside from that, this looks absolutely terrible!
you should be using auto-layout instead of setting frames
layoutSubviews can be called multiple times... you should be adding the UITapGestureRecognizer when you create the views, not removing / re-adding every time layoutSubviews is called.
Related
I am creating progress view by using CALayer by following
Header class
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ProgressBar : UIView
#property (strong, nonatomic) CALayer *subLayer;
#property (nonatomic) CGFloat progress;
#end
Implementation class
#implementation ProgressBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.progress = 0;
self.backgroundColor = [UIColor whiteColor];
self.subLayer = [CALayer layer];
self.subLayer.frame = self.bounds;
self.subLayer.backgroundColor = [UIColor orangeColor].CGColor;
[self.layer addSublayer:self.subLayer];
}
return self;
}
- (void)setProgress:(CGFloat)value {
NSLog(#"what is going on here");
if (self.progress != value) {
self.progress = value;
[self setNeedsLayout];
}
}
- (void)layoutSubviews {
CGRect rect = [self.subLayer frame];
rect.size.width = CGRectGetWidth([self bounds]) * self.progress;
[self.subLayer setFrame:rect];
}
In my viewcontroller, I am doing
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pBar = [[ProgressBar alloc] initWithFrame:CGRectMake(0, 50, 320, 10)];
[self.view addSubview:self.pBar];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)click:(id)sender {
[self.pBar setProgress:.8];
}
When (IBAction)click is fired, I am getting into the infinitive loop like the picture below
Does anyone know what I am getting into this loop. Please advice me on this issue. Thanks
The problem is that your setProgress: method calls the setProgress: method - recursion.
- (void)setProgress:(CGFloat)value {
NSLog(#"what is going on here");
if (self.progress != value) {
self.progress = value; // <-- This calls [self setProgress:value]
[self setNeedsLayout];
}
}
Change the bad line to:
_progress = value;
Setting the ivar directly is always required when you implement the setter method of a property.
I'm working on creating a rotation of 32 names using UILabels. How would I random rotate all 32 names?
- (IBAction)buttonPressed
{
int randomInt = rand() % [nameArray count];
[nameLabel setText:[nameArray objectAtIndex:randomInt]]
}
In your .h file you must have:
IBOutlet UILabel *nameLabel;
EDIT
I built this project and here is the exact code I used:
This is the .h file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UILabel *nameLabel;
NSArray *nameArray;
}
- (IBAction)buttonPressed;
#end
This is the .m file:
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
nameArray = [[NSArray alloc] initWithObjects:#"name1", #"name2", #"name3", #"name4", #"name5", #"name6", nil];
}
- (IBAction)buttonPressed
{
int randomInt = rand() % [nameArray count];
[nameLabel setText:[nameArray objectAtIndex:randomInt]];
}
- (void)dealloc
{
[super dealloc];
[nameArray release];
nameArray = nil;
}
#end
Make sure that both the UILabel and button actions are connected in interface builder.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
NSMutableArray *nameArray;
NSMutableArray *textFieldArray;
UIScrollView *scrollView;
}
- (IBAction)buttonPressed;
- (void)addTextFields:(int)count;
// Random sort function for the shuffle method
int randomSort(id obj1, id obj2, void *context );
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// If you want to pre load values
nameArray = [[NSMutableArray alloc] initWithObjects:#"name1", #"name2", #"name3", #"name4", #"name5", #"name6", nil];
// Initilize the array to contain all the textfields
textFieldArray = [[NSMutableArray alloc] init];
// inititlize and add the scrollview
scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
[self.view addSubview:scrollView];
// Create and add the button to randomize the fields
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(self.view.frame.size.width/2 - 150, 20, 150, 50)];
[button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Randomize" forState:UIControlStateNormal];
[scrollView addSubview:button];
// method to create any number of textfields (currently sending number of items in nameArray)
[self addTextFields:[nameArray count]];
}
- (void)addTextFields:(int)count
{
// adjust these to get the size and positions you like
#define X_POSITION 20
#define TEXT_FIELD_WIDTH 300
#define TEXT_FIELD_HEIGHT 50
// Where to place the first text field
int yPosition = 90;
for (int textFieldCount = 0; textFieldCount<count; textFieldCount++) {
//Create and add the text field
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(X_POSITION, yPosition, TEXT_FIELD_WIDTH, TEXT_FIELD_HEIGHT)];
[textField setTag:textFieldCount];
[scrollView addSubview:textField];
[textFieldArray addObject:textField];
[textField setText:[nameArray objectAtIndex:textFieldCount]];
// Where to place the next text field
yPosition += (TEXT_FIELD_HEIGHT + 20);
}
// set the scroll view content size so it will fit all the text fields
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, yPosition+TEXT_FIELD_HEIGHT+20)];
}
- (IBAction)buttonPressed
{
// release and remove everyting from the name array
[nameArray release];
nameArray = nil;
// reinitilize the name array
nameArray = [[NSMutableArray alloc] init];
// Loop through the textfields to get the names into the nameArray
for (int textFieldCount = 0; textFieldCount<[textFieldArray count]; textFieldCount++) {
[nameArray addObject:[[textFieldArray objectAtIndex:textFieldCount] text]];
}
// Randomly sort the names in the array
[nameArray sortUsingFunction:randomSort context:nil];
// Add the random names back into the text fields
for (int textFieldCount = 0; textFieldCount<[textFieldArray count]; textFieldCount++) {
[[textFieldArray objectAtIndex:textFieldCount] setText:[nameArray objectAtIndex:textFieldCount]];
}
}
int randomSort(id obj1, id obj2, void *context ) {
// returns random number -1 0 1
return (arc4random()%3 - 1);
}
- (void)dealloc
{
[super dealloc];
[nameArray release];
nameArray = nil;
}
I try to build a endless scrolling UIScrollView. So far I took the apple sample "StreetScroller". So all I do is setting the contentOffset back when it reaches the end of the scroll view.
Override -layoutSubviews of the UIScrollView:
- (void)layoutSubviews
{
CGFloat contentWidth = [self contentSize].width;
CGPoint contentOffset = [self contentOffset];
CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
CGFloat distanceFromCenter = contentOffset.x - centerOffsetX;
if (ABS(distanceFromCenter) > (contentWidth / 4.0)) {
contentOffset = CGPointMake(centerOffsetX, contentOffset.y);
[super setContentOffset:contentOffset];
}
}
Now on iOS 5 this works like a charm. But on iOS 4.3 it's not working. As soon as I call [super setContentOffset:contentOffset] it stoops scrolling because next time -layoutSubviews get's called the [self contentOffset] does not return the contentOffset that was set.
I know there are a lot a questions about infinite UIScrollViews, but one of these has fixed this problem!
Try this One. This Code is Working Properly for me on iOS 4.3
RootViewController.h
#class ViewControllerForDuplicateEndCaps;
#interface RootViewController : UIViewController {
ViewControllerForDuplicateEndCaps *viewControllerForDuplicateEndCaps;
}
#property (nonatomic, retain) ViewControllerForDuplicateEndCaps *viewControllerForDuplicateEndCaps;
- (IBAction)loadScrollViewWithDuplicateEndCaps:(id)sender;
#end
RootViewController.m
#import "RootViewController.h"
#import "ViewControllerForDuplicateEndCaps.h"
#import "InfiniteScrollViewAppDelegate.h"
#implementation RootViewController
#synthesize viewControllerForDuplicateEndCaps;
- (IBAction)loadScrollViewWithDuplicateEndCaps:(id)sender {
InfiniteScrollViewAppDelegate *delegate = (InfiniteScrollViewAppDelegate*)[[UIApplication sharedApplication] delegate];
if(self.viewControllerForDuplicateEndCaps == nil) {
ViewControllerForDuplicateEndCaps *temp = [[ViewControllerForDuplicateEndCaps alloc] initWithNibName:#"ViewControllerForDuplicateEndCaps" bundle:nil];
self.viewControllerForDuplicateEndCaps = temp;
[temp release];
}
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
[delegate.navigationController pushViewController:self.viewControllerForDuplicateEndCaps animated:YES];
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end
ViewControllerForDuplicateEndCaps.h
#import <UIKit/UIKit.h>
#interface ViewControllerForDuplicateEndCaps : UIViewController <UIScrollViewDelegate> {
IBOutlet UIScrollView *scrollView;
}
#property (nonatomic, retain) UIScrollView *scrollView;
- (void)addImageWithName:(NSString*)imageString atPosition:(int)position;
#end
ViewControllerForDuplicateEndCaps.m
#import "ViewControllerForDuplicateEndCaps.h"
#implementation ViewControllerForDuplicateEndCaps
#synthesize scrollView;
- (void)viewDidLoad {
[super viewDidLoad];
// add the last image (image4) into the first position
[self addImageWithName:#"image4.jpg" atPosition:0];
// add all of the images to the scroll view
for (int i = 1; i < 5; i++) {
[self addImageWithName:[NSString stringWithFormat:#"image%i.jpg",i] atPosition:i];
}
// add the first image (image1) into the last position
[self addImageWithName:#"image1.jpg" atPosition:5];
scrollView.contentSize = CGSizeMake(1920, 416);
[scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO];
}
- (void)addImageWithName:(NSString*)imageString atPosition:(int)position {
// add image to scroll view
UIImage *image = [UIImage imageNamed:imageString];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(position*320, 0, 320, 416);
[scrollView addSubview:imageView];
[imageView release];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender {
NSLog(#"%f",scrollView.contentOffset.x);
// The key is repositioning without animation
if (scrollView.contentOffset.x == 0) {
// user is scrolling to the left from image 1 to image 4
// reposition offset to show image 4 that is on the right in the scroll view
[scrollView scrollRectToVisible:CGRectMake(1280,0,320,416) animated:NO];
}
else if (scrollView.contentOffset.x == 1600) {
// user is scrolling to the right from image 4 to image 1
// reposition offset to show image 1 that is on the left in the scroll view
[scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO];
}
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end
In my iPad program I have an array which holds images. How can I display my all images (from an image array) in my viewController the same as the below screen shot? Is there a good way to do it, any sample application paths to refer or sample code?
I need the following functionality.
Tapping an image will show it full screen
A close button to close this view as the same as the screen shot.
Two buttons to display the remaining and previous images.
A sample screen shot is attached below. We can see that the below application is showing all images at the right side of the screen.
Alright, this should be easy, though a bit of coding is needed.
Start out with a simple view based app template.
I don't know where the images come from so I just put all the images to be shown in the resources folder.
The view controller PictureViewController will accept an array of UIImages and should be presented modally. I'll post the code below.
The code to show the PictureViewController is placed in the view controller created by the template. I just added a simple UIButton to the view to trigger an action which looks something like this:
- (IBAction)onShowPictures
{
// Load all images from the bundle, I added 14 images, named 01.jpg ... 14.jpg
NSMutableArray *images = [NSMutableArray array];
for (int i = 1; i <= 14; i++) {
[images addObject:[UIImage imageNamed:[NSString stringWithFormat:#"%02d.jpg", i]]];
}
PictureViewController *picViewController = [[PictureViewController alloc] initWithImages:images];
[self presentModalViewController:picViewController animated:YES];
[picViewController release];
}
The view controller's view was created with interface builder, looking like this:
PictureViewController.xib
View Hierarchy
The fullscreen image is linked to an outlet fullScreenImage seen in the following header file. Actions are connected as well.
I've set the fullscreen imageView's content mode to Aspect Fit.
The Thumbnails will be added dynamically with code. Here's the view controller's code
PictureViewController.h
#interface PictureViewController : UIViewController
{
NSMutableArray *imageViews;
NSArray *images;
UIImageView *fullScreenImage;
int currentPage;
}
#property (nonatomic, retain) NSMutableArray *imageViews;
#property (nonatomic, retain) NSArray *images;
#property (nonatomic, retain) IBOutlet UIImageView *fullScreenImage;
- (id)initWithImages:(NSArray *)images;
- (IBAction)onClose;
- (IBAction)onNextThumbnails;
- (IBAction)onPreviousThumbnails;
#end
PictureViewController.m
The define MAX_THUMBNAILS on top defines the maximum of thumbnails seen. A UITapGestureRecognizer will take care of the tap events for the thumbnails. Adjust the CGRectMake in setupThumbnailImageViews to position the thumbnails as you wish. This controller is just a basic approach without orientation support.
#import "PictureViewController.h"
#define MAX_THUMBNAILS 6
#interface PictureViewController ()
- (void)showSelectedImageFullscreen:(UITapGestureRecognizer *)gestureRecognizer;
- (void)setupThumbnailImageViews;
- (void)setThumbnailsForPage:(int)aPage;
- (UIImage *)imageForIndex:(int)anIndex;
#end
#implementation PictureViewController
#synthesize imageViews, images, fullScreenImage;
- (id)initWithImages:(NSArray *)someImages
{
self = [super init];
if (self) {
self.images = someImages;
self.imageViews = [NSMutableArray array];
currentPage = 0;
}
return self;
}
- (void)viewDidLoad
{
self.fullScreenImage.image = [images objectAtIndex:0];
[self setupThumbnailImageViews];
[self setThumbnailsForPage:0];
}
- (void)showSelectedImageFullscreen:(UITapGestureRecognizer *)gestureRecognizer
{
UIImageView *tappedImageView = (UIImageView *)[gestureRecognizer view];
fullScreenImage.image = tappedImageView.image;
}
- (void)setupThumbnailImageViews
{
for (int i = 0; i < MAX_THUMBNAILS; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(20.0,
166.0 + (130.0 * i),
130.0,
90.0)];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(showSelectedImageFullscreen:)];
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.numberOfTouchesRequired = 1;
[imageView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];
imageView.userInteractionEnabled = YES;
[imageViews addObject:imageView];
[self.view addSubview:imageView];
}
}
- (void)setThumbnailsForPage:(int)aPage
{
for (int i = 0; i < MAX_THUMBNAILS; i++) {
UIImageView *imageView = (UIImageView *)[imageViews objectAtIndex:i];
UIImage *image = [self imageForIndex:aPage * MAX_THUMBNAILS + i];
if (image) {
imageView.image = image;
imageView.hidden = NO;
} else {
imageView.hidden = YES;
}
}
}
- (UIImage *)imageForIndex:(int)anIndex
{
if (anIndex < [images count]) {
return [images objectAtIndex:anIndex];
} else {
return nil;
}
}
#pragma mark -
#pragma mark user interface interaction
- (IBAction)onClose
{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)onNextThumbnails
{
if (currentPage + 1 <= [images count] / MAX_THUMBNAILS) {
currentPage++;
[self setThumbnailsForPage:currentPage];
}
}
- (IBAction)onPreviousThumbnails
{
if (currentPage - 1 >= 0) {
currentPage--;
[self setThumbnailsForPage:currentPage];
}
}
#pragma mark -
#pragma mark memory management
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[images release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
[imageViews release];
[fullScreenImage release];
}
- (void)dealloc
{
[images release];
[imageViews release];
[fullScreenImage release];
[super dealloc];
}
#end
The result:
I'm having a hard time getting this right.
I've got a UIScrollView, with paging enabled. It is managed by a view controller (MainViewController) and each page is managed by a PageViewController, its view added as a subview of the scrollView at the proper offset. Scrolling is left-right, for standard orientation iPhone app. Works well. Basically exactly like the sample provided by Apple and also like the Weather app provided with the iPhone.
However, when I try to support other orientations, things don't work very well. I've supported every orientation in both MainViewController and PageViewController with this method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
However, when I rotate the device, my pages become quite skewed, and there are lots of drawing glitches, especially if only some of the pages have been loaded, then I rotate, then scroll more, etc... Very messy.
I've told my views to support auto-resizing with
theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
But to no avail. It seems to just stretch and distort my views.
In my MainViewController, I added this line in an attempt to resize all my pages' views:
- (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;
}
}
But it didn't help too much (because I lazily load the views, so not all of them are necessarily loaded when this executes).
Is there any way to solve this problem?
I have successfully achieved this using below method:
.h file code:
#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;
============================================================================================
.m file
#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];
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the 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);
}
I hope, it will be helpful to all.
Cheers.
Is it necessary to have a separate UIViewController (PageViewController) for every page in your UIScrollView? Why not let your MainViewController take care of this.
Resizing your views (and your UI in general) after rotating the device is much easier when you build your UI in Interface Builder.
I'm not absolutely sure I understand you right.. however, some thoughts:
The frame property is one thing (A), how the view contents are displayed in there is another (B). The frame CGRect is the (theoretical) boundary of your view in the superview (parent view) .. however, your View does not necessarily need to fill that whole frame area.
Regarding (A):
Here we have the UIView's autoresizingMask property to set how the frame is resized when the superview is resized. Which happens when you change the orientation. However, you can usually rely on the default settings (worked for me so far).
Regarding (B):
How the view contents are distributet in the view frame is specified by UIView's property contentMode. With this property, you can set that the aspect ratio needs to stay intact. Set it to UIViewContentModeScaleAspectFit for example, or something else..
see here:
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW99
PS: I wrote "theoretical", because your view contents may also exceed those frame boundaries - they are only limiting the view when UIView's clipsToBounds property is set to YES. I think it's a mistake that Apple set this to NO by default.
In addition to what Efrain wrote, note that the frame property IS NOT VALID if the view transform is other than the identity transform -- i.e., when the view is rotated.
Of course, you accounted for the fact that your views need to be at a new offset position, right?