3

I need to dynamically create some views in my app and place some buttons on them dynamically again. If the amount (count) of the buttons is more then ten I want to place the buttons on a new view and the transitions between the views must be with UIPageControl. Even though I googled and searched from Apple's Developer page I couldn't find a way of solving my problem. Can someone please help?

ilhan çetin
  • 383
  • 5
  • 19
  • 1
    possible duplicate of [UIPageControl Help](http://stackoverflow.com/questions/1816144/uipagecontrol-help) – Jim Puls Jan 29 '12 at 22:56
  • I don't think this is duplicate i had looked at that question but i didn't want to use UIScrollView. Thanks for warning – ilhan çetin Jan 29 '12 at 23:23

1 Answers1

11

Add your views as side-by-side subviews of an UIScrollView, using the addSubview method. Then use the UIPageControl with the UIScrollView, as in this example.


I made a class that manages a UIScrollView, a UIPageControl, and an array of UIViews. It is a simplified version of what I use in my own code. It does the following:

  • Sets up the scroll view to display an array of UIViews. It doesn't care if the views have been generated dynamically or not.
  • Handles scroll and page control events.
  • Synchronizes the scroll view with the page control.

PageViewManager.h

#import <Foundation/Foundation.h>

@interface PageViewManager : NSObject <UIScrollViewDelegate>
{
    UIScrollView* scrollView_;
    UIPageControl* pageControl_;
    NSArray* pages_;
    BOOL pageControlUsed_;
    NSInteger pageIndex_;
}

- (id)initWithScrollView:(UIScrollView*)scrollView
             pageControl:(UIPageControl*)pageControl;
- (void)loadPages:(NSArray*)pages;
- (void)loadControllerViews:(NSArray*)pageControllers;

@end

PageViewManager.m

#import "PageViewManager.h"

@interface PageViewManager ()

- (void)pageControlChanged;

@end

@implementation PageViewManager

- (id)initWithScrollView:(UIScrollView*)scrollView
             pageControl:(UIPageControl*)pageControl
{
    self = [super init];
    if (self)
    {
        scrollView_ = scrollView;
        pageControl_ = pageControl;
        pageControlUsed_ = NO;
        pageIndex_ = 0;

        [pageControl_ addTarget:self action:@selector(pageControlChanged)
               forControlEvents:UIControlEventValueChanged];
    }
    return self;
}

/*  Setup the PageViewManager with an array of UIViews. */
- (void)loadPages:(NSArray*)pages
{
    pages_ = pages;
    scrollView_.delegate = self;
    pageControl_.numberOfPages = [pages count];

    CGFloat pageWidth  = scrollView_.frame.size.width;
    CGFloat pageHeight = scrollView_.frame.size.height;

    scrollView_.pagingEnabled = YES;
    scrollView_.contentSize = CGSizeMake(pageWidth*[pages_ count], pageHeight);
    scrollView_.scrollsToTop = NO;
    scrollView_.delaysContentTouches = NO;

    [pages_ enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop)
    {
        UIView* page = obj;
        page.frame = CGRectMake(pageWidth * index, 0,
                                pageWidth, pageHeight);
        [scrollView_ addSubview:page];
    }];
}

/*  Setup the PageViewManager with an array of UIViewControllers. */
- (void)loadControllerViews:(NSArray*)pageControllers
{
    NSMutableArray* pages = [NSMutableArray arrayWithCapacity:
                             pageControllers.count];
    [pageControllers enumerateObjectsUsingBlock:
        ^(id obj, NSUInteger idx, BOOL *stop)
        {
            UIViewController* controller = obj;
            [pages addObject:controller.view];
        }];

    [self loadPages:pages];
}

- (void)pageControlChanged
{
    pageIndex_ = pageControl_.currentPage;

    // Set the boolean used when scrolls originate from the page control.
    pageControlUsed_ = YES;

    // Update the scroll view to the appropriate page
    CGFloat pageWidth  = scrollView_.frame.size.width;
    CGFloat pageHeight = scrollView_.frame.size.height;
    CGRect rect = CGRectMake(pageWidth * pageIndex_, 0, pageWidth, pageHeight);
    [scrollView_ scrollRectToVisible:rect animated:YES];
}

- (void)scrollViewDidScroll:(UIScrollView*)sender
{
    // If the scroll was initiated from the page control, do nothing.
    if (!pageControlUsed_)
    {
        /*  Switch the page control when more than 50% of the previous/next
            page is visible. */
        CGFloat pageWidth = scrollView_.frame.size.width;
        CGFloat xOffset = scrollView_.contentOffset.x;
        int index = floor((xOffset - pageWidth/2) / pageWidth) + 1;
        if (index != pageIndex_)
        {
            pageIndex_ = index;
            pageControl_.currentPage = index;
        }
    }
}

- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView
{
    pageControlUsed_ = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView
{
    pageControlUsed_ = NO;
}

@end

To use this class, you embed it inside a UIViewController than contains the UIScrollView and the UIPageControl.

Usage:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // Create some views dynamically
    UIView* v1 = ...
    UIView* v2 = ...

    // Put the views inside an NSArray:
    NSArray* pages_ = [NSArray arrayWithObjects:v1, v2, nil];

    /* Create the PageViewManager, which is a member (or property) of this
       UIViewController. The UIScrollView and UIPageControl belong to this 
       UIViewController, but we're letting the PageViewManager manage them for us. */
    pageViewManager_ = [[PageViewManager alloc]
                        initWithScrollView:self.scrollView
                               pageControl:self.pageControl];

    // Make the PageViewManager display our array of UIViews on the UIScrollView.
    [pageViewManager_ loadViews:pages_];
}

My sample code assumes that you're using ARC.

Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
  • Sorry but can't i use it without scrollview? – ilhan çetin Jan 29 '12 at 23:02
  • 1
    If you want to be able to scroll from one the page to the next by using your finger (like the iPhone's home screen), then the easiest way (that I know of) is to use a UIScrollView. When users see the UIPageControl on your user interface, they're going to expect to able to move from one page to another by flicking. – Emile Cormier Jan 29 '12 at 23:12
  • Thank you @Emile, i was exactly asking that. – ilhan çetin Jan 29 '12 at 23:21
  • this example is for static page number, i want to create&increment new views dynamically – ilhan çetin Feb 15 '12 at 15:36
  • If you don't how to create views programmatically, do a web search for "creating UIView programmatically" and you'll find many guides on this topic. Books on iPhone development will also cover this in detail. After reading up and giving it a try, you can post a new question here requesting for help if you run into trouble. – Emile Cormier Feb 15 '12 at 18:41
  • @Emilie : I dont use ARC but i can handle from this point. Thank you very much – ilhan çetin Feb 15 '12 at 19:08
  • @ilhançetin : So that others may benefit from my answer, can you please change the title of your question to something more general, like: "How do I add views to an UIScrollView and keep it synchronized with a UIPageControl?" – Emile Cormier Feb 15 '12 at 19:39
  • I think you were asking for something like this:) Plz See my edit – ilhan çetin Feb 15 '12 at 19:45
  • @Emilie: Unfortunatelly i have an other problem too, in my app i save some data with NSUserDefaults(that data are property lis objects) and i want to populate tableview in bacground, but even tough i make changes in server side nothing changes in my app. I need to use core data but couldn't design the data model, can you give a hend please? – ilhan çetin Feb 15 '12 at 20:01
  • @ilhançetin: I'm not your personal assistant. Your last comment has nothing to do with your original question. If you have other issues, use the search feature of this site. If you can't find a question matching your problem, ask a new question. – Emile Cormier Feb 15 '12 at 20:24
  • @Emilie: I know that you aren't my personal assistant but i tought just you can have an idea. Thanks again – ilhan çetin Feb 16 '12 at 08:52
  • @Emilie: here is my question. I would be pleased if you could help http://stackoverflow.com/questions/9311223/how-to-design-data-model-for-core-data-with-the-this-json-data – ilhan çetin Feb 16 '12 at 12:25