Help with scrollView

Discussion in 'iOS Development' started by johnmabassa, May 14, 2009.

  1. johnmabassa

    johnmabassa Member

    Joined:
    Mar 16, 2009
    Messages:
    87
    Likes Received:
    0
    Hi,
    I was trying to make an application where there is a table with names of some items and when you click on one item, a new view with the details will be shown, now I donot want the user to go back to the tableview again and select the next item to see its details. I want to implement a scrollView with paging so that the user can swipe through all the items without going back.

    I have used some codes from "Iphone Noob viewing images as photos.app" and was able to make it work. Now the problem is that even if I click the first item or the second item.... the detail view starts with the details of first item. I am not sure how to fix this issue.

    Please find some relevant codes

    When I click on an item I am loading the scroll view and passing the array with list of items and its details.

    ScrollViewController.m

    Code:
    - (void)viewDidLoad {
    
        self.title=@"List Of Items";
    	NSMutableArray *controllers = [[NSMutableArray alloc] init];
    	
                //detailsArray has the entire list of items
    
    	for (unsigned i = 0; i < [self.detailsArray count]; i++) {
    		[controllers addObject:[NSNull null]];
    	}
    	
    	self.viewControllers = controllers;
    	[controllers release];
    	
    	// a page is the width of the scroll view
    	scrollView.pagingEnabled = YES;
    	scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [self.detailsArray count], scrollView.frame.size.height);
    	scrollView.showsHorizontalScrollIndicator = NO;
    	scrollView.showsVerticalScrollIndicator = NO;
    	scrollView.scrollsToTop = NO;
    	scrollView.delegate = self;
    	
    	
    	[self loadPage:0];
    	[self loadPage:1];
    }
    
    - (void)loadPage:(int)page {
    	if (page < 0) return;
    	if (page >= [self.detailsArray count]) return;//detailsArray has the entire list of items
    	
    	// replace the placeholder if necessary
    	DetailedViewController *controller = [viewControllers objectAtIndex:page];
    	if ((NSNull *)controller == [NSNull null]) {
    		
    		NSDictionary *itemAtIndex = (NSDictionary *)[self.detailsArray objectAtIndex:page];
    		
    		controller = [[DetailedViewController alloc] initWithDictionary:itemAtIndex];
    		
    		[viewControllers replaceObjectAtIndex:page withObject:controller];
    		[controller release];
    	}
    	
    
    	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];
    		//[scrollView scrollRectToVisible:frame animated:NO];
    	}
    }
    
    - (void)scrollViewDidScroll:(UIScrollView *)sender {
    
    	CGFloat pageWidth = scrollView.frame.size.width;
    	int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    	
    
    	[self loadPage:page - 1];
    	[self loadPage:page];
    	[self loadPage:page + 1];
    }
    It will be helpful if I could get some tutorials or sample codes?

    Thanks
    -John
  2. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    I don't necessarily agree with how you've set everyhig up, but that us neither here not there. The relevant point to his post is to check the docs. I don't have a computer in front of me and I don't remember the exact methods off hand. What you are looking for are (vaguely) the scrollToPoint and the setScrollOffset method. I've used them before, so I know they're there somewhere, and that they will do what you want.
  3. johnmabassa

    johnmabassa Member

    Joined:
    Mar 16, 2009
    Messages:
    87
    Likes Received:
    0
    Hi thanks for the help..... I used setContentOffset method to do the trick.

    -John
  4. chauhan4

    chauhan4 New Member

    Joined:
    Nov 21, 2009
    Messages:
    5
    Likes Received:
    0
    Device:
    3G iPod touch
    Hi,
    I know its been a while since the last reply on this thread but I have exactly the same set up in my app and am trying to embellish by adding paging at the detail view level. I am struggling to get this to work. As of now, I have a tab bar controller with navigations controllers added to it and each of the navigation controllers has a table view. When a cell is selected, a new view controller is loaded with details based on the selection made. I don't want the user to go back every single time they want to view the next cell in the table view. What is the best way to implement this? I have been trying to manually implement a swipe gesture using touchesBegan and touchesMoved but I haven't got it to work. Any help is greatly appreciated.
    Thanks in advance.
  5. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Create a view subclass that displays your details. Create as many of these as you need. Add each one as a subview of your scrollview's context view with the correct offsets for each one. Finally, set pagingEnabled on the scrollview.

    Assuming your sizes are correct all the way around, you'll have the effect you desire. Also, don't load all the details at one time. Instead dynamically load them for each view as the new view is shown. Have the app forget the previous details.
  6. chauhan4

    chauhan4 New Member

    Joined:
    Nov 21, 2009
    Messages:
    5
    Likes Received:
    0
    Device:
    3G iPod touch
    Hi SkylarEC,
    Thanks a lot for all your help but I am still struggling to implement this. You seem to know a lot about this and so, I had a question. When a row is selected in the table view on the root view controller, how do I set the page of the scroll view based on the selection made on the parent. It seems to load up the same page with every selection. I want to set a variable called page with the same value as indexPath.row. Once I have that as a reference, I would be able to load the views into the scroll view appropriately. Please let me know. Thanks again for all your help.
  7. chauhan4

    chauhan4 New Member

    Joined:
    Nov 21, 2009
    Messages:
    5
    Likes Received:
    0
    Device:
    3G iPod touch
    Hi,
    I've been working real hard on this and have got a part of it to work but they're still a few things that don't work as expected. As mentioned in the earlier posts, I have a tab bar controller with two tabs that are loaded with navigation controllers. The navigation controllers have a table view and when one of the rows is selected, a new window with a scrollview is loaded. The nib with the details is added to the scroll view at this point. I've got paging to work at this level of the app but when one of the rows in the table view is selected, it always loads the first page of details irrespective of the row selected. I've been trying to use setContentOffset to load the details of the row selected but I haven't gotten it to work. The code of the scroll view controller looks like this:

    Code:
    - (void)viewDidLoad {
        [super viewDidLoad];
    	
    	PQIPaintSolutionsAppDelegate *appDelegate = (PQIPaintSolutionsAppDelegate *)[[UIApplication sharedApplication] delegate];
    	
    	// Load the view controllers lazily
    	// In the meantime, load the array with placeholders which will be replaced on demand
    	NSMutableArray *controllers	= [[NSMutableArray alloc] init];
    	if (appDelegate.tabBarController.selectedIndex == 0) 
    	{
    		for (unsigned i = 0; i < [appDelegate.interiorDetailList count]; i++) 
    		{
    			[controllers addObject:[NSNull null]];
    		}
    	}
    	else 
    	{
    		for (unsigned i = 0; i < [appDelegate.exteriorDetailList count]; i++) 
    		{
    			[controllers addObject:[NSNull null]];
    		}
    	}
    	self.viewControllers = controllers;
    	[controllers release];
    	// a page is the width of the scroll view
        scrollView.pagingEnabled = YES;
    	CGSize scrollableSize;
    	if (appDelegate.tabBarController.selectedIndex == 0)
    		scrollableSize = CGSizeMake(scrollView.frame.size.width * [appDelegate.interiorDetailList count], scrollView.frame.size.height);
    	else {
    		scrollableSize = CGSizeMake(self.view.frame.size.width * [appDelegate.exteriorDetailList count], 350); //scrollView.frame.size.width * [appDelegate.exteriorDetailList count], scrollView.frame.size.height);
    	}
    	
    	[scrollView setContentSize:scrollableSize];
        scrollView.showsHorizontalScrollIndicator = YES;
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.scrollsToTop = NO;
        scrollView.delegate = self;
    	
    	NSUserDefaults *userRetrieve = [NSUserDefaults standardUserDefaults];
    	int rowOfIndexPath = [userRetrieve integerForKey:@"RowSelectedExterior"];
    	NSLog(@"rowOfIndexPath is : %d", rowOfIndexPath);
    	
        //[self loadPage:0];
        //[self loadPage:1];
    	[self loadPage:rowOfIndexPath];
    	[self loadPage:rowOfIndexPath + 1];
    
    }
    
    - (void)loadPage:(int)page
    {	NSLog(@"page variable in loadPage is %d", page);
    	PQIPaintSolutionsAppDelegate *appDelegate = (PQIPaintSolutionsAppDelegate *)[[UIApplication sharedApplication] delegate];
    	
    	if (page < 0) return;
    	if (appDelegate.tabBarController.selectedIndex == 0) 
    	{
    		if (page >= [appDelegate.interiorDetailList count]) 
    		{
    			return;
    		}
    	}
    	else 
    	{
    		if (page >= [appDelegate.exteriorDetailList count])
    		{
    			return;
    		}
    	}
    
    	// Replace the placeholder in the NSMutableArray
    	ProblemDetailViewController *problemDetailController = [viewControllers objectAtIndex:page];
    	
    	if ((NSNull *)problemDetailController == [NSNull null]) {
    		
    		// grabbing the image
    		PQIData *data;
    		if (appDelegate.tabBarController.selectedIndex == 0)
    		{
    			data = (PQIData *)[appDelegate.interiorDetailList objectAtIndex:page];
    		}
    		else 
    		{
    			data = (PQIData *)[appDelegate.exteriorDetailList objectAtIndex:page];
    		}
    
    		problemDetailController = [[ProblemDetailViewController alloc] initWithNibName:@"ProblemDetail" bundle:nil];
    		problemDetailController.problemImage = data.dataImage;
    		problemDetailController.textForTextView = [NSString stringWithFormat:@"%@\n%@\n\n%@\n%@\n\n%@\n%@", data.name, data.nameInfo, data.possibleCause, data.possibleCauseInfo, data.solution, data.solutionInfo];
            [viewControllers replaceObjectAtIndex:page withObject:problemDetailController];
            [problemDetailController release];
        }
    	
    	// add the controller's view to the scroll view
        if (nil == problemDetailController.view.superview) {
    		NSLog(@"Entering the if statement to add view to scrollview");
            CGRect frame = scrollView.frame;
            frame.origin.x = frame.size.width * page;
            frame.origin.y = 0;
    		problemDetailController.view.frame = frame;
            [scrollView addSubview:problemDetailController.view];
        }
    }
    
    - (void)scrollViewDidScroll:(UIScrollView *)sender {
        // Switch the indicator when more than 50% of the previous/next page is visible
        CGFloat pageWidth = scrollView.frame.size.width;
        int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    	
        // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
        [self loadPage:page - 1];
        [self loadPage:page];
        [self loadPage:page + 1];
    }
    
    
    Can someone please help me with this. I want the details of the row selected to be loaded into the scroll view. Any ideas on how to achieve this. Any help is really appreciated.
    Thanks in advance.
  8. johnmabassa

    johnmabassa Member

    Joined:
    Mar 16, 2009
    Messages:
    87
    Likes Received:
    0
    Hi Chauhan4,

    I have made some modifications to the code snippet that you have put, just try running it, I am not having a mac with me so not able to test it and also I am not having the code where I did this, I just searched in the back of my memory and typed it.
    Code:
    - (void)viewDidLoad {
        [super viewDidLoad];
    	
    	PQIPaintSolutionsAppDelegate *appDelegate = (PQIPaintSolutionsAppDelegate *)[[UIApplication sharedApplication] delegate];
    	
    	// Load the view controllers lazily
    	// In the meantime, load the array with placeholders which will be replaced on demand
    	NSMutableArray *controllers	= [[NSMutableArray alloc] init];
    	if (appDelegate.tabBarController.selectedIndex == 0) 
    	{
    		for (unsigned i = 0; i < [appDelegate.interiorDetailList count]; i++) 
    		{
    			[controllers addObject:[NSNull null]];
    			[self loadPage:i];
    		}
    	}
    	else 
    	{
    		for (unsigned i = 0; i < [appDelegate.exteriorDetailList count]; i++) 
    		{
    			[controllers addObject:[NSNull null]];
    			[self loadPage:i];
    		}
    	}
    	self.viewControllers = controllers;
    	[controllers release];
    	// a page is the width of the scroll view
        scrollView.pagingEnabled = YES;
    	CGSize scrollableSize;
    	if (appDelegate.tabBarController.selectedIndex == 0)
    		scrollableSize = CGSizeMake(scrollView.frame.size.width * [appDelegate.interiorDetailList count], scrollView.frame.size.height);
    	else {
    		scrollableSize = CGSizeMake(self.view.frame.size.width * [appDelegate.exteriorDetailList count], 350); //scrollView.frame.size.width * [appDelegate.exteriorDetailList count], scrollView.frame.size.height);
    	}
    	
    	[scrollView setContentSize:scrollableSize];
        scrollView.showsHorizontalScrollIndicator = YES;
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.scrollsToTop = NO;
        scrollView.delegate = self;
    	
    	NSUserDefaults *userRetrieve = [NSUserDefaults standardUserDefaults];
    	int rowOfIndexPath = [userRetrieve integerForKey:@"RowSelectedExterior"];
    	NSLog(@"rowOfIndexPath is : %d", rowOfIndexPath);
    	
    
    	[self loadNextPage:rowOfIndexPath];
    
    
    }
    -(void)loadNextPage:(int)page{
    
    	problemDetailController= [viewControllers objectAtIndex:page]
       if (nil == problemDetailController.view.superview) {
    		NSLog(@"Entering the if statement to add view to scrollview");
            CGRect frame = scrollView.frame;
            frame.origin.x = frame.size.width * page;
            frame.origin.y = 0;
    		problemDetailController.view.frame = frame;
    				CGPoint point=CGPointMake(frame.size.width * page,0);
            [scrollView addSubview:problemDetailController.view];
            		[scrollView setContentOffset:point animated:NO];
        }
    
    }
    
    - (void)loadPage:(int)page
    {	NSLog(@"page variable in loadPage is %d", page);
    	PQIPaintSolutionsAppDelegate *appDelegate = (PQIPaintSolutionsAppDelegate *)[[UIApplication sharedApplication] delegate];
    	
    	if (page < 0) return;
    	if (appDelegate.tabBarController.selectedIndex == 0) 
    	{
    		if (page >= [appDelegate.interiorDetailList count]) 
    		{
    			return;
    		}
    	}
    	else 
    	{
    		if (page >= [appDelegate.exteriorDetailList count])
    		{
    			return;
    		}
    	}
    
    	// Replace the placeholder in the NSMutableArray
    	ProblemDetailViewController *problemDetailController = [viewControllers objectAtIndex:page];
    	
    	if ((NSNull *)problemDetailController == [NSNull null]) {
    		
    		// grabbing the image
    		PQIData *data;
    		if (appDelegate.tabBarController.selectedIndex == 0)
    		{
    			data = (PQIData *)[appDelegate.interiorDetailList objectAtIndex:page];
    		}
    		else 
    		{
    			data = (PQIData *)[appDelegate.exteriorDetailList objectAtIndex:page];
    		}
    
    		problemDetailController = [[ProblemDetailViewController alloc] initWithNibName:@"ProblemDetail" bundle:nil];
    		problemDetailController.problemImage = data.dataImage;
    		problemDetailController.textForTextView = [NSString stringWithFormat:@"%@\n%@\n\n%@\n%@\n\n%@\n%@", data.name, data.nameInfo, data.possibleCause, data.possibleCauseInfo, data.solution, data.solutionInfo];
            [viewControllers replaceObjectAtIndex:page withObject:problemDetailController];
            [problemDetailController release];
        }
    	
    
    }

    Code:
    Instead of using scrollViewDidScroll, you may need to use 
    - (void)scrollViewDidEndDecelerating(UIScrollView *)scroll 
    {
      // Calculate the page number here and just call loadNextPage
    }
    
    - (void)scrollViewDidEndDragging:(UIScrollView *)scroll willDecelerate:(BOOL)decelerate
    {
     // Calculate the page number here and just call loadNextPage
    }
    -John

Share This Page