I'm trying to make an application that uses a UIScrollView to page between an indeterminate number of dynamically generated custom view controllers. Unfortunately, when I try the code shown below, all I get is a blank screen. Additionally, the nslog statement that I put right after the subview is supposedly added to the UIScrollView always says that the UIScrollView has zero subviews. I'm totally baffled by this problem and would greatly appreciate any help.
- (void)loadView
{
[super loadView];
scrollView.pagingEnabled = YES;
viewControllers = [[NSMutableArray alloc] init];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGFloat screenScale = [[UIScreen mainScreen] scale];
CGFloat width = screenBounds.size.width * screenScale;
CGFloat height = screenBounds.size.height * screenScale;
scrollView.contentSize = CGSizeMake(width * [routes count], height);
for( int i = 0; i < [arrayWithDataForViewControllers count]; i++)
{
ViewController *controller = [[ViewController alloc] init];
controller.view.frame = CGRectMake(width*i, 20, width, height);
[scrollView addSubview:controller.view];
NSLog(#"SUBVIEWS %d", [[scrollView subviews] count]);
[viewControllers addObject:controller];
}
}
Check your ViewController's view outside of the scrollview - chances are that it's view property is nil.
Related
For hours I've been trying to figure out why the UIScrollView won't display the images from a NSMutableArray.
I realized the uiimageview objects are in the subview collection inside the UISCrollview but somehow the UIViewContentModeScaleAspectFit is ignored... How can I fit to scale then?
please, any tips?
- (void)viewDidLoad
{
[super viewDidLoad];
BookDalc* bookDalc = [[BookDalc alloc] init];
NSMutableArray* books = [bookDalc FindByIconID:IconID];
for(int i = 0;i<books.count;i++)
{
CGRect frame;
frame.origin.x = self.scrBook.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrBook.frame.size;
UIImageView *subview = [[UIImageView alloc] initWithFrame:frame];
subview.contentMode = UIViewContentModeScaleAspectFit;
BookEntity *currentModel = [books objectAtIndex:i];
UIImage *currentImage = [currentModel TheImage];
subview.image = currentImage;
[self.scrBook addSubview:subview];
}
self.scrBook.contentSize
= CGSizeMake(self.scrBook.frame.size.width * books.count, self.scrBook.frame.size.height);
}
The frame of self.srcBook might not be set.
For more information read this answer.
Why am I having to manually set my view's frame in viewDidLoad?
I am trying to create a UIScrollView programatically. I have a scrollView for that ViewController. Here is how I instantiate it in loadView:
CGRect fullScreenRect = [[UIScreen mainScreen] applicationFrame];
self.scrollView = [[UIScrollView alloc] initWithFrame:fullScreenRect];
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
I then some items onto it, and then add it to view in loadView as follows:
[self.scrollView addSubview:self.searchBar];
[self.scrollView addSubview:button];
[self.view addSubview:self.scrollView];
So far everything should be fine. However, in other functions, I will be adding ImageViews and then I will need to set the scrollview's content size. The way I do it is just use [self.scrollView addToSubView:image] and when I want to edit the content size of the scrollview, I do it as follows:
// Calculate scroll view size
float sizeOfContent = 0;
for (int i = 0; i < [self.scrollView.subviews count]; i++) {
UIImageView *view =[self.scrollView.subviews objectAtIndex:i];
sizeOfContent += view.frame.size.height;
[view release];
}
// Set content size for scroll view
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, sizeOfContent);
I keep getting an EXC_BAD_ACCESS error in the main.m class.
I suspect that the problem is with retaining the actual scrollView since I think scrollView is not retaining the same object that is a subview of view.
Any suggestions? Thanks in advance!
If you have defined self.scrollView as #property(nonatomic, retain) then first wrong thing is the line;
self.scrollView = [[UIScrollView alloc] initWithFrame:fullScreenRect];
It sets the retain count of scrollView to 2, which is not what you expect. alloc retained properties like this,
scrollView = [[UIScrollView alloc] initWithFrame:fullScreenRect];
I think your BAD_ACCESS error comes from here;
for (int i = 0; i < [self.scrollView.subviews count]; i++) {
UIImageView *view =[self.scrollView.subviews objectAtIndex:i];
sizeOfContent += view.frame.size.height;
[view release];
}
Why are you releasing view? You did not alloc it, so there is no reason to release it. Remove the [view release] line and check again.
I have a scrollview of images, I will like to tab them and will pushed to another view.
once i tab on the image, the whole view should push to another view.
From this View to another view
Detail view
Sorry for not asking the question clearly.
my scrollview
-(void)pictureScrolling
{
//init scrollview in location on screen
scrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 100, 320, 290)];
scrollview.backgroundColor = [UIColor redColor];
//pass image filenames
NSMutableArray *fileNames = nearbyFrog.imageFiles; //[[[NSMutableArray alloc] init] autorelease];
//setup the array of uiimageviews
NSMutableArray *imgArray = [[NSMutableArray alloc] init];
UIImageView *imageView;
//loop through the array imgNames to add file names to imgArray
for (NSString *imageName in fileNames) {
imageView = [[UIImageView alloc] init];
imageView.image = [UIImage imageNamed:imageName];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[imgArray addObject:imageView];
[imageView release];
}
CGSize pageSize = scrollview.frame.size;
NSUInteger page = 0;
for (UIView *viewForScrollView in imgArray) {
[scrollview addSubview:viewForScrollView];
viewForScrollView.frame = CGRectMake(pageSize.width * page++ +10, 0, pageSize.width -20 , pageSize.height);
// making use of the scrollView's frame size (pageSize) so we need to;
// +10 to left offset of image pos (1/2 the gap)
// -20 for UIImageView's width (to leave 10 gap at left and right)
}
//add scroll view to view
[self.view addSubview:scrollview];
scrollview.contentSize = CGSizeMake(pageSize.width * [imgArray count], pageSize.height);
//scrollview.contentSize = CGSizeMake(320 *viewcount + 20, 290 );
scrollview.showsHorizontalScrollIndicator =NO;
[scrollview setPagingEnabled:YES];
scrollview.delegate =self;
//paging function for scrollview
CGRect frame = [[UIScreen mainScreen] applicationFrame];
self.pageControl = [[[UIPageControl alloc] initWithFrame:CGRectMake(0, 100, 100, 50)] autorelease];
self.pageControl.center = CGPointMake(frame.size.width/2, frame.size.height-60);
self.pageControl.numberOfPages = [fileNames count];
[self.view addSubview:self.pageControl];
//handle Touch Even
[pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
[imgArray release];
}
anybody knows how to do it or can show me a tutorial?
Thanks
I think this is the best way to implement it
Create your own Custom UIImageView class. This is required to store an additional property which will help you identify which image for clicked.
Create a delegate for that class which is called with the single tap event is raised in the UIImageView
Add the Images inside the scrollview using this custom class. The delegate of this class will tell you which image was tapped. You can use this to push a new view controller passing the image details (if necessary).
You can find some sample code in the ThumbImageView class in the scrollviewSuite sample
http://developer.apple.com/library/ios/#samplecode/ScrollViewSuite/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008904-Intro-DontLinkElementID_2
I want to use a UIScrollView to display multiple UIViews as the user scrolls through the UIScrollView control. I'm not worried about showing Pagination just yet.
I already managed to implement some of it, but is not working the way I want it to.
Currently:
I have 3 ViewControllers with different nib files. The root view controller is the one with the UIScrollView, and it to load the rest of the view controllers.
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; i++) {
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.delegate = self;
pageControl.numberOfPages = kNumberOfPages;
pageControl.currentPage = 0;
[self loadScrollViewWithPage:0];
- (void)loadScrollViewWithPage:(int)page {
if (page == 0) {
PageTwo *controller2 = [viewControllers objectAtIndex:page];
if ((NSNull *)controller2 == [NSNull null]) {
controller2 = [[PageTwo alloc] initWithPageNumber:page];
[viewControllers replaceObjectAtIndex:page withObject:controller2];
[controller2 release];
}
// add the controller's view to the scroll view
if (nil == controller2.view.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller2.view.frame = frame;
[scrollView addSubview:controller2.view];
}
}
if (page == 1) {
// replace the placeholder if necessary
NewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
controller = [[NewController alloc] initWithPageNumber:page];
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (nil == controller.view.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
}
}
That's all fine... However, what I want it to do is to load the root nib first. But I'm not sure how to go about this. I know I have to increase the number of pages to 3, but when I initialize the controllers I don't know how to tell it that page == 0 should be the current view.
Any ideas?
Update:
Sigh, I overlooked something.. Didn't notice that if don't specify a page at level 0 it just shows the current view hah!
Silly me.
I overlooked something.. Didn't notice that if don't specify a page at level 0 it just shows the current view hah!
I've searched and searched for a tutorial for this but none of them are what I'm looking for. I've tried Apple's sample but it is just colors and I don't know how to make it views. All I'm looking for is a screen that will page while showing the page control. Each time the scroll view pages i want it to show a completely different view with buttons, a lot like the home screen of the iPhone. I found the sample code below which works very well with just images, but I'd like to modify to work with separate views. Please Help! Thank you.
- (void)setupPage {
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor clearColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
NSUInteger nimages = 0;
CGFloat cx = 0;
for (; ; nimages++) {
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", (nimages + 1)];
UIImage *image = [UIImage imageNamed:imageName];
if (image == nil) {
break;
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.size.height = image.size.height;
rect.size.width = image.size.width;
rect.origin.x = ((scrollView.frame.size.width - image.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - image.size.height) / 2);
imageView.frame = rect;
[scrollView addSubview:imageView];
[imageView release];
cx += scrollView.frame.size.width;
}
self.pageControl.numberOfPages = nimages;
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
}
I was experimenting with this just the other day. I'm still getting used to using a UIScrollView but here's how you can add views to your UIScrollView:
UIView *blueView = [[UIView alloc] init];
blueView.frame = CGRectMake(100, 0, 500, 1024);
blueView.backgroundColor = [UIColor colorWithRed:164.0/256 green:176.0/256 blue:224.0/256 alpha:1];
[scrollView addSubview:blueView];
[blueView release];
UIView *orangeView = [[UIView alloc] init];
orangeView.frame = CGRectMake(700, 0, 500, 1024);
orangeView.backgroundColor = [UIColor colorWithRed:252.0/256 green:196.0/256 blue:131.1/256 alpha:1];
[scrollView addSubview:orangeView];
[orangeView release];
Notice that I'm setting the x value in frame.origin of each view so that they're sitting adjacent to each other. You also have to set the content size of the UIScrollView with something like [scrollView setContentSize:CGSizeMake(1200, 1024)]; so that it knows how big its subviews are.
Then, if you need to control a UIPageControl, you would set its numberOfPages to 2 (for the example scrollview above) and change its currentPage property. You could do this by implementing scrollViewDidEndDecelerating:, which is a method in the UIScrollViewDelegate. You could check which "page" the scrollview is at by checking its contentOffset.x value.
Hope this helps!
Here's the Apple PageControl code with images. To use, just drag your images to the project. The default images are image1.jpg, image2.jpg, etc. If you need png, just change the extension to .png.
Then replace the MyViewController.m code with this code, and you've got pagecontrol with Images.
Cheers, Jordan
http://pastebin.com/raw.php?i=c3hS29sC
// Adding UIView to PageControl example
- (id)initWithPageNumber:(int)page {
UIScreen *screen = [UIScreen mainScreen];
CGRect frame = [screen applicationFrame];
frame.origin.y=0;
if (self = [super initWithNibName:#"MyView" bundle:nil]) {
UIView *view = [[UIView alloc] initWithFrame:frame];
[self.view addSubview:view];
// Add whatever you want to the view here.
[view release];
pageNumber = page;
}
return self;
}
Here's another answer...
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"Views" owner:self options:nil];
infoView = [nibViews objectAtIndex:0];
[self.view addSubview:infoView];
Then you have your view.
Cheers