I'm following these instructions per the ios docs on UIPageViewController and UIPageControl:
A page indicator will be visible if both methods are implemented, transition style is 'UIPageViewControllerTransitionStyleScroll', and navigation orientation is 'UIPageViewControllerNavigationOrientationHorizontal'. Both methods are called in response to a 'setViewControllers:...' call, but the presentation index is updated automatically in the case of gesture-driven navigation.
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
So I have implemented them as follows, inside a UIViewController wrapper class:
Here is the initialization:
#interface PageViewWrapperViewController : UIViewController <UIPageViewControllerDelegate, UIPageViewControllerDataSource>
#property (strong, nonatomic) UIPageViewController *pageController;
#property (assign, nonatomic) NSInteger index;
#property (strong, nonatomic) UILabel *screenNumber;
#property UIPageControl *childPageControl;
#end
- (void)viewDidLoad {
[super viewDidLoad];
self.index = 0;
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
self.pageController.delegate = self;
[self.pageController.view setFrame:[[self view] bounds]] ;
UIViewController *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];
self.childPageControl = [[UIPageControl alloc] init];
// self.childPageControl = [self getPageControlForPageViewController:self.pageController];
self.childPageControl.alpha = .5;
[self.view bringSubviewToFront:self.childPageControl];
}
Here are the required methods for the UIPageControl:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return 5;
}
-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return self.index;
}
And here is where I give the PageController the individual view controllers:
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index{
if(index==0)
{
//JudgeViewController *next1 = [[JudgeViewController alloc] init];
JudgeTutorViewController *next1 = [[JudgeTutorViewController alloc] init];
next1.view.userInteractionEnabled = NO;
return next1;
}
else if(index==1)
{
FollowTableViewController *next1 = [[FollowTableViewController alloc] init];
next1.view.userInteractionEnabled = NO;
next1.typeDisplay = 1;
return next1;
}
else if (index==2)
{
StatTutorViewController *next1 = [[StatTutorViewController
alloc] init];
next1.view.userInteractionEnabled = NO;
next1.user = [[UserObject userUnique] copyUser].name;
return next1;
}
else if (index==3)
{
MenuTutorViewController *next1 = [[MenuTutorViewController
alloc] init];
next1.view.userInteractionEnabled = NO;
return next1;
}
else if(index ==4)
{
BuzzTutorViewController *next1 = [[BuzzTutorViewController alloc] init];
next1.view.userInteractionEnabled = NO;
return next1;
}
self.index = index;
return nil;
}
The UIPageViewController itself is working fine, but I don't see the UIPageControl. What is missing from my code?
Thank you for any suggestions.
Actually, neither of these answers is what the problem is. In fact, I didn't change my code but once I flushed my build settings a few times that did the trick. Thank you all!
self.childPageControl = [[UIPageControl alloc] init];
// self.childPageControl = [self getPageControlForPageViewController:self.pageController];
self.childPageControl.alpha = .5;
[self.view bringSubviewToFront:self.childPageControl];
At no point are you adding the page control as a subview. The view debugger in Xcode is a great way to spot missing UI elements like this.
Related
I have a UIPageViewController that is added as subview on UIView. The UIView sits on the top of UIViewController's view, at start it puts the UIPageViewController lower than it should sit, but right after I click on the next button to push the next UIPageViewController's view, it send it back to the correct position.
What is he doing that? I tried everything but still can figure out the problem.
This is how it looks:
What seems to be the problem? Thanks in advance!
EDIT: This is my 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];
DataChildViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
self.pageController.dataSource = self;
self.pageController.delegate = self;
self.pageController.view.userInteractionEnabled = NO;
self.pageController.view.frame = self.view.bounds;
[self.pageControllerParent addSubview:self.pageController.view];
[self addChildViewController:self.pageController];
self.currentPageControllerIndex = 1;
}
- (IBAction)buttonNextDidClicked
{
self.buttonNext.enabled = NO;
__weak typeof(self) __self = self;
[self.pageController setViewControllers:#[[self viewControllerAtIndex:self.currentPageControllerIndex]]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:^(BOOL finished) {
__self.currentPageControllerIndex++;
__self.buttonNext.enabled = YES;
}];
}
#pragma mark - UIPageViewControllerDelegate & DataSource
- (DataChildViewController *)viewControllerAtIndex:(NSUInteger)index
{
DataChildViewController *childViewController = [[DataChildViewController alloc] initWithNibName:#"DataChildViewController" bundle:nil];
childViewController.index = index;
return childViewController;
}
So, I've figured out the problem.
On viewDidLoad I had this line:
self.pageController.view.frame = self.view.bounds;
When it actually should be:
self.pageController.view.frame = self.pageControllerParent.bounds;
I'm wanting to add a UIScrollView with paging to go through different views from my existing view controller which is the root view of my app. I also have tab bar and navigation bar controllers along with it. Can I add a scroll view to this view controller to accomplish what I'm wanting, and if so, can someone point me in the right direction on how to go about it?
Here is my view controller.
#import "KFBViewController.h"
#import "ListViewController.h"
#import "ActionAlertsViewController.h"
#import "MarketUpdatesViewController.h"
#import "AgStoriesViewController.h"
#import "KFBNewsViewController.h"
#import "MemberBenefits.h"
#import "SocialNetworks.h"
#import "WebViewController.h"
#import "YouTubeView.h"
#import "KFBFlickrViewController.h"
#import "RSFM.h"
#import "UAPush.h"
#import "TUSafariActivity.h"
#interface KFBViewController ()
{
}
#end
#implementation KFBViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.title = NSLocalizedString(#"Home", #"Home");
self.tabBarItem.image = [UIImage imageNamed:#"home"];
self.navigationController.delegate = self;
}
return self;
}
- (void) showMenu
{
NSURL *urlToShare = [NSURL URLWithString:#"https://itunes.apple.com/us/app/kentucky-farm-bureau/id580530986?mt=8"];
NSArray *activityItems = #[urlToShare];
// TUSafariActivity *activity = [[TUSafariActivity alloc] init];
UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:activityItems applicationActivities:nil];
activityVC.excludedActivityTypes = #[UIActivityTypePrint, UIActivityTypeAssignToContact, UIActivityTypePostToWeibo, UIActivityTypeSaveToCameraRoll];
[self presentViewController:activityVC animated:TRUE completion:nil];
}
- (IBAction)gotoSecondView
{
YouTubeView *youTubeView = [[YouTubeView alloc] initWithNibName:#"YouTubeView" bundle:nil];
youTubeView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:youTubeView animated:YES completion:nil];
}
- (IBAction)gotoPublicAffairs
{
ListViewController *publicAffairs = [[ListViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[publicAffairs setWebViewController:wvc];
publicAffairs.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:publicAffairs animated:YES];
}
- (IBAction)gotoActionAlerts
{
ActionAlertsViewController *actionAlerts = [[ActionAlertsViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[actionAlerts setWebViewController:wvc];
actionAlerts.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:actionAlerts animated:YES];
}
- (IBAction)gotoMarketUpdates
{
MarketUpdatesViewController *marketUpdates = [[MarketUpdatesViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[marketUpdates setWebViewController:wvc];
marketUpdates.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:marketUpdates animated:YES];
}
- (IBAction)gotoAgStories
{
AgStoriesViewController *agStories = [[AgStoriesViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[agStories setWebViewController:wvc];
agStories.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:agStories animated:YES];
}
- (IBAction)gotoKFBNews
{
KFBNewsViewController *kfbNews = [[KFBNewsViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[kfbNews setWebViewController:wvc];
kfbNews.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:kfbNews animated:YES];
}
- (IBAction)gotoMemberBenefits
{
MemberBenefits *memberBenefits = [[MemberBenefits alloc] initWithNibName:nil bundle:nil];
memberBenefits.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:memberBenefits animated:YES];
}
-(IBAction)gotoPhotos:(id)sender
{
KFBFlickrViewController *photosView = [[KFBFlickrViewController alloc] initWithNibName:#"KFBFlickrViewController" bundle:nil];
[self.navigationController pushViewController:photosView animated:YES];
}
- (IBAction)gotoSocialNetworks
{
SocialNetworks *socialNetworks = [[SocialNetworks alloc] initWithNibName:nil bundle:nil];
socialNetworks.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:socialNetworks animated:YES];
}
- (IBAction)gotoFarmMarkets
{
RSFM *rsfm = [[RSFM alloc] initWithNibName:nil bundle:nil];
rsfm.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:rsfm animated:YES];
}
- (IBAction)settingsButtonPressed:(id)sender
{
[UAPush openApnsSettings:self animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = #"Home";
UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc] initWithTitle:#"\u2699" style:UIBarButtonItemStyleBordered target:self action:#selector(settingsButtonPressed:)];
[settingsButton setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont boldSystemFontOfSize:24], UITextAttributeFont,nil] forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem = settingsButton;
UIBarButtonItem *systemAction = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(showMenu)];
self.navigationItem.rightBarButtonItem = systemAction;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
#end
This works really well for me:
Declare a property for your UIScrollView, and set your ViewController as a UIScrollViewDelegate
#interface ViewController : UIViewController<UIScrollViewDelegate>
#property (strong, nonatomic) UIScrollView *theScrollView;
#end
**Note that I'm setting up my UIScrollView with code, but it can easily be done with a XIB.
In viewDidLoad: of your ViewController
self.theScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, 300)];
self.theScrollView.delegate = self;
self.theScrollView.pagingEnabled = YES;
self.theScrollView.showsHorizontalScrollIndicator = NO;
self.theScrollView.showsVerticalScrollIndicator = NO;
[self.view addSubview:self.theScrollView];
NSArray *viewArray = [NSArray arrayWithObjects://your UIViews];
for(int i=0; i<viewArray.count; i++)
{
CGRect frame;
frame.origin.x = self.theScrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.theScrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[subview addSubview:[viewArray objectAtIndex:i]];
[self.theScrollView addSubview:subview];
}
self.theScrollView.contentSize = CGSizeMake(self.theScrollView.frame.size.width * viewArray.count, self.theScrollView.frame.size.height);
Most paging scrollViews also have a UIPageControl associated with it. To do that, override this UIScrollViewDelegate method:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat pageWidth = self.theScrollView.frame.size.width;
int page = floor((self.theScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.thePageControl.currentPage = page;
}
I would perhaps try using UIPageViewController, rather than a regular paging scrollview.
Apple's PhotoScroller sample code provides a very good example of how to use UIPageViewController.
I also have some code on github that modifies PhotoScroller to load the UIPageViewController inside a UIViewController subclass. (In Apple's sample code, the UIPageViewController is the root view controller.)
I have never used a UIPageViewController with different UIViewController subclasses in each page (the PhotoScroller sample code uses PhotoViewControllers in all pages), but I can't see why it couldn't be done with a few modifications to the code.
This link helps for you. Here page controller and scrollview both are used -
PageControl Example in iPhone
I have the following code to create a UIPageViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
self.index = 0;
self.pageContainer = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageContainer.dataSource = self;
[[self.pageContainer view] setFrame:[[self view] bounds]];
DMSignUp1ViewController *first = [[DMSignUp1ViewController alloc] init];
DMSignUp2ViewController *second = [[DMSignUp2ViewController alloc] init];
self.viewControllers = [[NSArray alloc] initWithObjects:first, second, nil];
[self.pageContainer setViewControllers:self.viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageContainer];
[[self view] addSubview:[self.pageContainer view]];
[self.pageContainer didMoveToParentViewController:self];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
if(self.index == 0) {
return nil;
}
self.index--;
return [self.viewControllers objectAtIndex:self.index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
if(self.index == 1) {
return nil;
}
self.index++;
return [self.viewControllers objectAtIndex:self.index];
}
I have two UIViewControllers: DMSignUp1 and 2 which I create and then place in the viewControllers array.
When I go to run it, I get the following error: 'The number of view controllers provided (2) doesn't match the number required (1) for the requested transition'
Which I understand is because I am passing the array to use as the view controller. So how do I set that I want to use the first view controller in the array?
Add the following method at the end of the ViewController.m file
- (DMSignUp1ViewController *)viewControllerAtIndex:(NSUInteger)index {
DMSignUp1ViewController *first= [[DMSignUp1ViewController alloc] initWithNibName:#"APPChildViewController" bundle:nil];
first.index = index;
return childViewController;
}
And, replace the following code
DMSignUp1ViewController *first = [[DMSignUp1ViewController alloc] init];
DMSignUp2ViewController *second = [[DMSignUp2ViewController alloc] init];
self.viewControllers = [[NSArray alloc] initWithObjects:first, second, nil];
With
APPChildViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
Hope this might help you...
If you have the UIPageViewController spineLocation set to anything other than UIPageViewControllerSpineLocationMid when you're using [self.pageContainer setViewControllers: you can only pass an array with one view controller. The API isn't very clear really with it saying Controllers. You then provide the additional viewControllers when the UIPageViewController requests them through the dataSource.
Link to the spine reference.
I am trying to make an iPhone app work in an iPad but the UIPopoverController is
comming back with error.
- (IBAction)photoTapped1 {
if(UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone){
// If in editing state, then display an image picker; if not, create and push a photo view controller.
if (self.editing) {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
[self presentViewController:imagePicker animated:YES completion:nil];
[imagePicker release];
} else {
RecipePhotoViewController *recipePhotoViewController = [[RecipePhotoViewController alloc] init];
recipePhotoViewController.hidesBottomBarWhenPushed = YES;
recipePhotoViewController.recipe = recipe;
[self.navigationController pushViewController:recipePhotoViewController animated:YES];
[recipePhotoViewController release];
}
}else{
if (self.editing){
self.popover = [[UIPopoverController alloc] initWithContentViewController:popover];
self.popover.delegate =self;
[popover release];
}else{
RecipePhotoViewController *recipePhotoViewController = [[RecipePhotoViewController alloc] init];
recipePhotoViewController.hidesBottomBarWhenPushed = YES;
recipePhotoViewController.recipe = recipe;
[self.navigationController pushViewController:recipePhotoViewController animated:YES];
[recipePhotoViewController release];
}}}
The error I am getting is:
'NSInvalidArgumentException', reason: '-[UIPopoverController initWithContentViewController:] must not be called with nil.'
Anyone available to give me a hand on this code, I have looked on the internet for solutions and samples but can not seem to make it work.
Thank you.
___ added to original question_____
I am adding the recipePhotoViewController here, I am assuming that ImageView manipulation is the same for iPhone and iPad.
my.h File
#class Recipe;
#interface RecipePhotoViewController : UIViewController {
#private
Recipe *recipe;
UIImageView *imageView;
}
#property(nonatomic, retain) Recipe *recipe;
#property(nonatomic, retain) UIImageView *imageView;
#end
Here is my .m file
#implementation RecipePhotoViewController
#synthesize recipe;
#synthesize imageView;
- (void)loadView {
self.title = #"Photo";
imageView = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.backgroundColor = [UIColor blackColor];
self.view = imageView; }
- (void)viewWillAppear:(BOOL)animated {
imageView.image = [recipe.image valueForKey:#"image"];}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc {
[imageView release];
[recipe release];
[super dealloc];
} #end
You are initializing the popover controller in a wrong way:
self.popover = [[UIPopoverController alloc] initWithContentViewController:popover];
You should pass the controller you would like to display inside of the popover -- not the popover itself (which is nil since you have not yet initialised it)!
Maybe this would do it for you?
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
self.popover = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
If this is correct, then you should also present the pop over you have just created: – presentPopoverFromRect:inView:permittedArrowDirections:animated:
-- e.g.:
[self.popover presentPopoverFromRect:sender.frame inView:[self view] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
where sender is the argument to :
- (IBAction)photoTapped1:(id)sender {
The content of your popover which you store in the variable popover is obviously nil. I can't see it ever being created in the code you provided.
Maybe you intended to present the Recipe photo controller as the content of the popover. In that case you would do something like
RecipePhotoViewController *recipePhotoViewController = [[RecipePhotoViewController alloc] init];
self.popover = [[UIPopoverController alloc] initWithContentViewController:recipePhotoViewController];
problem is in this line of your code ,
self.popover = [[UIPopoverController alloc] initWithContentViewController:popover];
try like this
UIViewController* popoverContent = [[UIViewController alloc] init];
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 400, 320, 260)];
popoverContent.view = popoverView;
//Add what ever you want popoverView
self.popover = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
self.popover.delegate =self;
The code:
UIViewController *viewController = [[UIViewController alloc] initWithNibName:#"NibName" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
navigationController.navigationBar.tintColor = [UIColor redColor];
self.popoverController = [[[UIPopoverController alloc]
initWithContentViewController:navigationController] autorelease];
popoverController.popoverContentSize = viewController.view.frame.size;
[popoverController presentPopoverFromRect:sender.frame inView:sender.superview
permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
[viewController release];
[navigationController release];
The tint color property of UINavigationBar doesn't work, it still has the default color.
What could I be doing wrong?
self.popoverController.popoverBackgroundViewClass = [MyCustomBackgroundView class];
#interface MyCustomBackgroundView : UIPopoverBackgroundView {
#private
}
#end
#implementation MyCustomBackgroundView
#synthesize arrowOffset;
#synthesize arrowDirection;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor redColor];
}
return self;
}
+ (UIEdgeInsets)contentViewInsets {
return UIEdgeInsetsMake(0, 0, 1, 0);
}
+ (CGFloat)arrowHeight{
return 0.0;
}
+ (CGFloat)arrowBase{
return 0.0;
}
#end
As of iOS 5, popoverBackgroundViewClass is available which is the way to accomplish this.