I am working on creating custom Container ViewController class and am able to create 5 sub viewcontrollers and able to move from one child view controller to other child using the following API:
transitionFromViewController:fromViewController
toViewController:toViewController
duration:1.0
options:0
animations:^{
}
completion:^(BOOL finished) {
}];
Child view controllers are occupying part of Parent View Controller. Each time when user swipe I am making previous controller goes off and present controller comes on displayable area.
Now I have buttons on child viewcontrollers and when i click on them I am not getting events or trigger to the Action method of Child View Controller. But Parent View Controller is getting callbacks for its buttons even currently childview is getting displayed. Adding the code snippet below (though it is little bigger, this will help you to analyze if I am doing any mistake).
Parent ViewController:
- (void) handleSwipeGestureLeft:(UISwipeGestureRecognizer *)gesture
{
if (showPopupValue) {
return;
}
NSInteger index = [arrayOfChildVCs indexOfObject:selectedViewController];
index = MIN(index+1, [arrayOfChildVCs count]-1);
UIViewController *newSubViewController = [arrayOfChildVCs objectAtIndex:index];
endFrame.origin.x = -1024;
startOfNewVCFrame.origin.x = 1024;
[self transitionFromViewController:selectedViewController toViewController:newSubViewController];
selectedViewController = newSubViewController;
}
- (void) handleSwipeGestureRight:(UISwipeGestureRecognizer *)gesture
{
if (showPopupValue) {
return;
}
NSInteger index = [arrayOfChildVCs indexOfObject:selectedViewController];
index = MAX(index-1, 0);
UIViewController *newSubViewController = [arrayOfChildVCs objectAtIndex:index];
endFrame.origin.x = 1024;
startOfNewVCFrame.origin.x = -1024;
[self transitionFromViewController:selectedViewController toViewController:newSubViewController];
selectedViewController = newSubViewController;
}
- (void) populateChildVCList
{
if (self.currentactivity == EPI_Normal)
{
arrayOfImageNames = [[NSArray alloc]initWithObjects:#"AD_Initiate_SPI_Normal.jpg", #"AD_Initiate_CPI_Normal.jpg", #"AD_Initiate_EAC_Normal.jpg", #"AD_Initiate_PV_Normal.jpg", #"AD_Initiate_EV_Normal.jpg", nil];
}
else
{
arrayOfImageNames = [[NSArray alloc]initWithObjects:#"AD_Initiate_SPI_Trigger.jpg", #"AD_Initiate_CPI_Trigger.jpg", #"AD_Initiate_EAC_Trigger.jpg", #"AD_Initiate_PV_Trigger.jpg", #"AD_Initiate_EV_Trigger.jpg", nil];
isTriggerOn = YES;
}
arrayOfChildVCs = [[NSMutableArray alloc] init];
[arrayOfChildVCs addObject:[[PopupDummyViewController alloc]initWithNibName:#"PopupDummyViewController" bundle:nil]]; // Note: Add one dummy VC to initiate swap
for (int vcIndex = 0; vcIndex < [arrayOfImageNames count]; vcIndex++)
{
PiSLAComplianceViewController *childPopupController = [[PiSLAComplianceViewController alloc]initWithNibName:#"PiSLAComplianceViewController" bundle:nil];
childPopupController.popUpImageName = [arrayOfImageNames objectAtIndex:vcIndex];
childPopupController.imageIndex = vcIndex;
childPopupController.isTriggerOn = isTriggerOn;
[arrayOfChildVCs addObject:childPopupController];
}
selectedViewController = [arrayOfChildVCs objectAtIndex:0];
selectedViewController.view.frame = CGRectMake(0, 100, 100, 511); // Took the imageview coordinates
// Add the dummy view controller to Container View Initially
[self addChildViewController:selectedViewController];
[self.view addSubview:selectedViewController.view];
// notify it that move is done
[selectedViewController didMoveToParentViewController:self];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[super viewDidLoad];
UISwipeGestureRecognizer *swipeGestureRecognizerRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGestureRight:)];
[swipeGestureRecognizerRight setDirection:UISwipeGestureRecognizerDirectionRight];
[ self.view addGestureRecognizer:swipeGestureRecognizerRight];
UISwipeGestureRecognizer *swipeGestureRecognizerLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGestureLeft:)];
[swipeGestureRecognizerLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[ self.view addGestureRecognizer:swipeGestureRecognizerLeft];
endFrame = deliverableimageview.frame;
startOfNewVCFrame = deliverableimageview.frame;
[self populateChildVCList]; // To Create list of child view controllers and loads one invisible dummy view controller to be ready for swiping
}
- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController
{
if (fromViewController == toViewController)
{
// cannot transition to same
return;
}
// animation setup
toViewController.view.frame = startOfNewVCFrame;
// notify
[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
// transition
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:1.0
options:0
animations:^{
toViewController.view.frame = fromViewController.view.frame;
fromViewController.view.frame = endFrame;
}
completion:^(BOOL finished) {
[toViewController didMoveToParentViewController:self];
[fromViewController removeFromParentViewController];
}];
}
Related
I'm in the process of making a tutorial, and I'm trying to emulate the style of Path's tutorial like so:
http://www.appcoda.com/wp-content/uploads/2013/06/UIPageViewController-Tutorial-Screen.jpg
My issue is that if set the delegate method as so:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
// The number of items reflected in the page indicator.
return 5;
}
Then I get this stupid black bar under the dots:
http://i.stack.imgur.com/pUEdh.png
Is there a way to make this bar translucent in a way thats similar to setting a UINavigationBar to translucent?
It is very easy to make it work. You just only have to make the pageviewcontroller taller, and place a PageControl into the XIB file.
The trick is put the PageControl in the foreground (and all the other common controls) at the beginning, and update the content of the PageControl with the PageViewController. Here is the code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
// We need to cover all the control by making the frame taller (+ 37)
[[self.pageController view] setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, [[self view] bounds].size.height + 37)];
TutorialPageViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
// Bring the common controls to the foreground (they were hidden since the frame is taller)
[self.view bringSubviewToFront:self.pcDots];
[self.view bringSubviewToFront:self.btnSkip];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [(TutorialPageViewController *)viewController index];
[self.pcDots setCurrentPage:index];
if (index == 0) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [(TutorialPageViewController *)viewController index];
[self.pcDots setCurrentPage:index];
index++;
if (index == 3) {
return nil;
}
return [self viewControllerAtIndex:index];
}
- (TutorialPageViewController *)viewControllerAtIndex:(NSUInteger)index {
TutorialPageViewController *childViewController = [[TutorialPageViewController alloc] initWithNibName:#"TutorialPageViewController" bundle:nil];
childViewController.index = index;
return childViewController;
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
// The number of items reflected in the page indicator.
NSInteger tutorialSteps = 3;
[self.pcDots setNumberOfPages:tutorialSteps];
return tutorialSteps;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 0;
}
The same effect can be achieved simply by subclassing UIPageViewController and overriding viewDidLayoutSubviews as follows:
-(void)viewDidLayoutSubviews {
UIView* v = self.view;
NSArray* subviews = v.subviews;
// Confirm that the view has the exact expected structure.
// If you add any custom subviews, you will want to remove this check.
if( [subviews count] == 2 ) {
UIScrollView* sv = nil;
UIPageControl* pc = nil;
for( UIView* t in subviews ) {
if( [t isKindOfClass:[UIScrollView class]] ) {
sv = (UIScrollView*)t;
} else if( [t isKindOfClass:[UIPageControl class]] ) {
pc = (UIPageControl*)t;
}
}
if( sv != nil && pc != nil ) {
// expand scroll view to fit entire view
sv.frame = v.bounds;
// put page control in front
[v bringSubviewToFront:pc];
}
}
[super viewDidLayoutSubviews];
}
Then there is no need to maintain a separate UIPageControl and such.
Swift 3 snippet
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let scrollView = view.subviews.filter({ $0 is UIScrollView }).first,
let pageControl = view.subviews.filter({ $0 is UIPageControl }).first {
scrollView.frame = view.bounds
view.bringSubview(toFront:pageControl)
}
}
Here's a conversion of Zerotool's solution into Swift 2.1, though there's probably a more elegant way to write it:
override func viewDidLayoutSubviews() {
var scrollView: UIScrollView?
var pageControl: UIPageControl?
// If you add any custom subviews, you will want to remove this check.
if (self.view.subviews.count == 2) {
for view in self.view.subviews {
if (view.isKindOfClass(UIScrollView)) {
scrollView = view as? UIScrollView
} else if (view.isKindOfClass(UIPageControl)) {
pageControl = view as? UIPageControl
}
}
}
if let scrollView = scrollView {
if let pageControl = pageControl {
scrollView.frame = self.view.bounds
self.view.bringSubviewToFront(pageControl)
}
}
super.viewDidLayoutSubviews()
}
I don't think you can change the behavior of UIPageViewController, so it seems likely that the Path app uses its own view controller. You can do the same: create your own container view controller that uses a UIPageControl to indicate the current page.
You can simply adjust the alpha of the UIPageViewController's UIPageControl.
First, you should retrieve it from the UIPageViewController like so:
- (UIPageControl *)getPageControlForPageViewController:(UIPageViewController *)pageViewController {
for (UIView *subview in self.pageViewController.view.subviews) {
if ([subview isKindOfClass:[UIPageControl class]]) {
return (UIPageControl *) subview;
}
}
return nil;
}
Next, make use of the function. I've made a property on my ViewController called childPageControl. Give it the UIPageViewController's UIPageControl:
self.childPageControl = [self getPageControlForPageViewController:self.pageViewController];
Next, you can adjust the alpha to give a translucent effect:
self.childPageControl.alpha = .5;
You're very limited in what you can do to affect the UIPageViewController's UIPageControl, but you can at least achieve this with little effort.
Small hack I found today..
Please see the code below.
self.pageController.dataSource = self;
CGRect rect = [self.view bounds];
rect.size.height+=37;
[[self.pageController view] setFrame:rect];
NSArray *subviews = self.pageController.view.subviews;
UIPageControl *thisControl = nil;
for (int i=0; i<[subviews count]; i++) {
if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]]) {
thisControl = (UIPageControl *)[subviews objectAtIndex:i];
}
}
UIView *tempview = [[UIView alloc] initWithFrame:CGRectMake(0, -30, 320, 40)];
[tempview addSubview:thisControl];
thisControl.pageIndicatorTintColor = [UIColor lightGrayColor];
thisControl.currentPageIndicatorTintColor = [UIColor greenColor];
[self.view addSubview:tempview];
this code is in Swift
Add following in your UIPageViewController
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews {
if view.isKindOfClass(UIScrollView) {
view.frame = UIScreen.mainScreen().bounds
} else if view.isKindOfClass(UIPageControl) {
view.backgroundColor = UIColor.clearColor()
}
}
}
I wanted to do a similar effect in the app I was working on - I used a UIPageViewController with a separate UIPageControl.
This lets you place the UIPageControl anywhere you'd like in the view, including over the top of the UIPageViewController, and you keep its active page dot up to date via the UIPageViewController delegate method:
- (void)pageViewController:(UIPageViewController *)pageViewController
didFinishAnimating:(BOOL)finished
previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers
transitionCompleted:(BOOL)completed {
if (completed) {
self.pageControl.currentPage = [self.pageViewControllers indexOfObject:pageViewController.viewControllers.firstObject];
}
}
No need to traverse the subview hierarchy trying to find the internal UIPageViewController page control, nor having to resize the contents of the internal scrollview.
Hope this helps.
I solve using this code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.namesImage = #[#"page1.png", #"page2.png", #"page3.png", #"page4.png"];
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
TutorialContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
[[UIPageControl appearance] setPageIndicatorTintColor:[UIColor grayColor]];
[[UIPageControl appearance] setCurrentPageIndicatorTintColor:[UIColor whiteColor]];
[[UIPageControl appearance] setBackgroundColor: [[UIColor blackColor] colorWithAlphaComponent:0.1f]];
[[UIPageControl appearance] setOpaque:YES];
}
Swift 5.2
you can use this code for your requirment
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let myScrollView = view.subviews.filter({ $0 is UIScrollView }).first,
let myPageControl = view.subviews.filter({ $0 is UIPageControl }).first {
myScrollView.frame = view.bounds
view.bringSubviewToFront(myPageControl)
}
}
I found an other workarround that fits me better.
I reuse the code given by zerotool to get the UIPageControl (var called pageControl) and the UIScrollView (var called pageView) used by the UIPageViewController.
Once that done in the viewDidLoad, I just prevent clip subview of pageView and let the content spread more to be beneath the UIPageControl.
The pageControl is beneath the pageView so we have to manually make it come in front.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
if(
[[[self view] subviews] count] == 2
)
{
UIScrollView* pageView = nil;
UIPageControl* pageControl = nil;
UIView* selfView = self.view;
NSArray* subviews = selfView.subviews;
for( NSInteger i = 0 ; i < subviews.count && ( pageView == nil || pageControl == nil ) ; i++ )
{
UIView* t = subviews[i];
if( [t isKindOfClass:[UIScrollView class]] )
{
pageView = (UIScrollView*)t;
}
else if( [t isKindOfClass:[UIPageControl class]] )
{
pageControl = (UIPageControl*)t;
}
}
if( pageView != nil && pageControl != nil )
{
[pageView setClipsToBounds:NO];
[selfView bringSubviewToFront:pageControl];
}
}
}
Once I get my pageView covering the space occupied by the pageControl but under the pageControl, I just have to adjust the nib file use for each viewController displayed as page :
base view should not clip
the first and only subview :
should have constraint to set bottom to -37 (or more if you need but 37 is the size of the pageControl) from bottom of superview
should clip content
There is a basic form, pressing button call method performSegueWithIdentifier which shows the popover window. How could I black out (dim) the main view window until the popover is active?
I've tried to use the library SVProgressHUD like this:
- (IBAction)publishButtonAction:(id)sender {
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];
[self performSegueWithIdentifier:#"fbshareSigue" sender:self];
[SVProgressHUD dismiss];
}
Obtained for a split second - until there is a popover-window.
Where must I insert this code, if I try this?:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"fbshareSigue"]) {
OFAFBShareViewController *svc = (OFAFBShareViewController *) [segue destinationViewController];
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
svc.postBlock = self.postInitBlock;
[svc setClosePopWindow:[popoverSegue popoverController]];
}
}
- (IBAction)publishButtonAction:(id)sender {
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.5f;
dimView.tag = 1111;
dimView.userInteractionEnabled = NO;
[self.view addSubview:dimView];
[self performSegueWithIdentifier:#"fbshareSigue" sender:self];
}
/* This code should be put in the other method where you are removing the popup.. Because it will remove the dim view. here is the wrong place for this code*/
/* for (UIView *view in [self.view subviews]) {
if (view.tag == 1111) {
[view removeFromSuperview];
}
}*/
Dim doesn't work...
====================
I have View OFAResultViewController that calling Popover (OFAFBShareViewController):
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"fbshareSigue"]) {
OFAFBShareViewController *svc = (OFAFBShareViewController *) [segue destinationViewController];
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
svc.postBlock = self.postInitBlock;
[svc setClosePopWindow:[popoverSegue popoverController]];
}
}
- (IBAction)publishButtonAction:(id)sender {
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.5f;
dimView.tag = 1111;
dimView.userInteractionEnabled = NO;
[self.view addSubview:dimView];
[self performSegueWithIdentifier:#"fbshareSigue" sender:self];
}
...
In OFAFBShareViewController I'm trying to close the dim view:
...
- (IBAction)cancelButtonAction:(id)sender {
[closePopWindow dismissPopoverAnimated:YES];
for (UIView *view in [self.view subviews]) {
if (view.tag == 1111) {
[view removeFromSuperview];
}
}
...
But it doesn't work again...
You can use the following code, when you display the popup.
In OFAFBShareViewController
- (void) loadView
{
[super loadView];
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.5f;
dimView.tag = 1111;
dimView.userInteractionEnabled = NO;
[self.view addSubview:dimView];
}
After popup removed, delete this view from super view using the tag.
After iOS 5.0 there is a public API method also introduced:
======================================================
To remove the view you can use this code:
for (UIView *view in [self.view subviews]) {
if ([view.tag == 1111]) {
[view removeFromSuperview];
}
}
Leave your Remove Dim View code as it is. Only Change super.view to self.view again.
It'll work for you then.
Hope it works for you...
When you create the popover, add a dim view to the current view, and add the current view as a UIPopoverControllerDelegate of the popover controller:
Add the dimView:
let dimView = UIView(frame: view.frame)
view.addSubview(dimView)
dimView.backgroundColor = UIColor.blackColor()
dimView.alpha = 0.5
dimView.tag = 1234
dimView.userInteractionEnabled = false
view.addSubview(dimView)
Add the origin view as delegate of the popoverController:
popoverViewController!.delegate = self
Then, in order to remove the dimView when the popover is dismissed, set the current view as implementing the UIPopoverControllerDelegate, and implement the popoverControllerDidDismissPopover func. Inside this function, remove the dimView:
extension MyOriginViewController: UIPopoverControllerDelegate {
func popoverControllerDidDismissPopover(popoverController: UIPopoverController) {
for subView in view.subviews {
if subView.tag == 1234 {
subView.removeFromSuperview()
}
}
}
}
I'm currently using a tableview inside a navigation controller, inside a tab bar controller. When i'm on the detail view of the table view, i want to "swipe" between Detail view, so i have implemented a UISwipeGesture with UIViewAnimations to swipe right/left.
Everything is working, but I have a little problem... When i'm on a Detail View loaded from the table view, the self.tabBarController element is here, i have my tab bar so i can add an actionsheet on it. But when i swipe, the self.tabBarController is nil now... I don't know why... Maybe because of the navigation Controller ?
Here is my code :
- (id) init
{
if (self = [super init]) {
CGRect fullScreenRect=[[UIScreen mainScreen] applicationFrame];
UIScrollView *scrollView=[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, fullScreenRect.size.width, 367.)];
scrollView.contentSize=CGSizeMake(320,100);
scrollView.delegate = self;
self.view=scrollView;
self.myView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 367.)];
self.ButtonSizeM.tag = 0;
self.ButtonSizeP.tag = 0;
self.ContentIV = [[UIImageView alloc] init];
}
return self;
}
- (void) handleSwipeLeft {
if (!((self.ancient.tableView.indexPathForSelectedRow.section == ([self.ancient numberOfSectionsInTableView:self.ancient.tableView] - 1)) && (self.ancient.tableView.indexPathForSelectedRow.row == [self.ancient tableView:self.ancient.tableView numberOfRowsInSection:(self.ancient.tableView.indexPathForSelectedRow.section)]-1)))
{
NSIndexPath *whereToGo;
if (self.ancient.tableView.indexPathForSelectedRow.row == [self.ancient tableView:self.ancient.tableView numberOfRowsInSection:(self.ancient.tableView.indexPathForSelectedRow.section)]-1) {
whereToGo = [NSIndexPath indexPathForRow:0 inSection:(self.ancient.tableView.indexPathForSelectedRow.section)+1];
}
else {
whereToGo = [NSIndexPath indexPathForRow:(self.ancient.tableView.indexPathForSelectedRow.row)+1 inSection:self.ancient.tableView.indexPathForSelectedRow.section];
}
CCFASimpleDetail *nextView = [[CCFASimpleDetail alloc] init];
nextView = [self.ancient tableView:self.ancient.tableView prepareViewForIndexPath:whereToGo];
[nextView performSelectorOnMainThread:#selector(affichageEnPlace) withObject:nil waitUntilDone:YES];
float width = self.myView.frame.size.width;
float height = self.myView.frame.size.height;
[nextView.view setFrame:CGRectMake(width, 0.0, width, height)];
[self.view addSubview:nextView.view];
[UIView animateWithDuration:0.5f delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
[nextView.view setFrame:self.view.frame];
[self.myView setFrame:CGRectMake(-width, 0.0, width, height)];
} completion:^(BOOL finished) {
[self.myView removeFromSuperview];
[self.ancient.tableView selectRowAtIndexPath:whereToGo animated:NO scrollPosition:UITableViewScrollPositionTop];
}
];
}
}
I you could help me to find my tab bar after swiping :) ?
When you add the view here:
[self.view addSubview:nextView.view];
the UINavigation controller does not know about it, and does not set the navigationBar nad tabBar properties for you.
What you can do is have the view get its superview (which will be self.view), then ask that view for the tabBarController and tabBar from that.
I just solved my problem by adding
[self.ancient.navigationController popViewControllerAnimated:NO];
[self.ancient.navigationController pushViewController:nextView animated:NO];
on the completion block !
I have a StoryBoard. In that there is a UIViewController - on that I have put UIScrollView and UIPageControl. And on each page (say I have 3) I am trying to load a UIViewController (that shows different labels and table values).
Problem - I am able to load everything up but the label and table is not visible. Thou when I try to change the background color for each page - it does gets changed. I have researched various posts and code but nothing seems to work / show UIScrollView with StoryBoard (with UIViewController displaying labels and table).
I am thou able to do this with loading a separate XIB file but then the whole segue gets interrupted.
Please see my code below.
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
//ScrollView and PageControl
// Create view controllers placeholder array
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (int i = 0; i < numberOfPages; i++)
{
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
// Set Scroll View
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * numberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.delegate = self;
// Set Page Control
pageControl.numberOfPages = numberOfPages;
pageControl.currentPage = 0;
// Load the visible and next page
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];
}
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
if (pageControlUsed)
{
// To know if scroll is valid - from Page Control
return;
}
// Changes Page Control indicator
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
// Load the visible, previous and next pages
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
pageControlUsed = NO;
}
- (void)loadScrollViewWithPage:(int)page
{
if (page < 0) return;
if (page >= numberOfPages) return;
// Load new Controller
ReportsDetailViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{
controller = [[ReportsDetailViewController alloc] init];
controller.pageNumber = [NSNumber numberWithInt:page];
[viewControllers replaceObjectAtIndex:page withObject:controller];
}
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];
}
}
Try to create your ViewControllers like this:
YourViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"YourViewController"];
You can set the identifier of your view controller in the attribute inspector.
I had the same problem today and this did the trick for me.
I am looking for some help for a program I am developing. Basically, it contains two views. The first view has a button and a action related to it leads me to my next view where there is a scroll view for three pages ( as in the PageControl sample given by apple.) I am using navigation controller to push the view from the first view to the second view. But on pushing I am not able to scroll the page or using page control or anything. It just comes a normal view. The code is same as pageControl code and it works fine as a separate module. But when I want to integrate this pageControl code with a first view and a click button it doesn't work. Please help.
//this function is an action set against a button in the rootviewcontroller.
-(IBAction) viewScrollPages:(id)sender{
UIViewController *controller = [[MyViewController alloc] initWithPageNumber:0];
[self.navigationController pushViewController:controller animated:NO];
[controller release];
}
- (id)initWithPageNumber:(int)page {
if (self = [super initWithNibName:#"MyViewController" bundle:nil]) {
pageNumber = page;
}
return self;
}
- (void)viewDidLoad {
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; 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 * kNumberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.delegate = self;
pageControl.numberOfPages = kNumberOfPages;
pageControl.currentPage = 0;
// pages are created on demand
// load the visible page
// load the page on either side to avoid flashes when the user starts scrolling
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];
pageNumberLabel.text = [NSString stringWithFormat:#"Page %d", pageNumber + 1];
self.view.backgroundColor = [MyViewController pageControlColorWithIndex:pageNumber];
[super viewDidLoad];
}
It sounds like your pushing a normal view that is a subview of the scrollview instead of pushing the scrollview itself.