I am facing problem with Accessibility read order issue.
I have a UIViewController in that 3 UIViewControllers added as childViewControllers.
NavigationController is added to the MainViewController.
When I turn on the accessibility, VO start reads from the childviewcontroller subviews and then moving to NavigationController. After reading the navigation bar Vo will not move down.
- (void)viewDidLoad
{
[super viewDidLoad];
self.suppressCart = YES;
[self setupNavigationItems];
// Set up the embedded navigation controller for the delivery/payment/review
// subviews
self.stepController = [[UINavigationController alloc] init];
self.stepController.delegate = self;
self.stepController.navigationBarHidden = YES;
// Add it to this view controller as a child
// Note: do not call begin/end appearance transitions
[self addChildViewController:self.stepController];
[self.view addSubview:self.stepController.view];
self.stepController.view.frame = CGRectOffsetAndShrink(self.view.bounds, 0, TargetBreadcrumbButtonHeight);
}
self.stepController is used to push the view controllers with in the MainViewController.
Did any one face this issue before. Need help to resolve this.
Is there any way to make VO reads every element in Infinite Loop??
Thanks,
Rakesh
Related
I am writing an application with help screens. As per my requirement I need to show the help screens when the view appears for the first time and I am placing the code on the tabbar controller class as (void)viewDidLoad:
{
[super viewDidLoad];
XDKWalkthroughController *sc = [[XDKWalkthroughController alloc]
initWithView:self.view];
[self addChildViewController:sc];
[self.view addSubview:sc.view];
sc.delegate = self;
[sc start];
}
When I am placing this code I am getting one more tabbar item along with existing tabbar item. How to avoid that in my case?
And same thing when I placed in the first view i.e in the first tab view controller view did class. Both navigation bar and tabbar are pushing the child view back.
I have tried these two scenarios, please help me with the possible solution.
I have an application in which UITabBarController as a rootViewController with two controllers. One is an empty controller and the second one is Picker controller extends from ABPeoplePickerNavigationController. The problem is view is going behind the tab bar and due to that view is cutting off from the bottom. I just highlighted the area in the screenshot:
Any help would be highly appreciated.
Officially ABPeoplePickerNavigationController doesn't support subclassing: link here
Subclassing Notes
The ABPeoplePickerNavigationController class does not support subclassing.
However, the problem is that the view of your ABPeoplePickerNavigationController subclass is extending under the tab bar.
You can, for example, change it's size at runtime in this way
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect rect = self.view.bounds;
rect.size.height = rect.size.height - 40;
self.view.frame = rect;
}
Note, the 40 is only an example, you should calculate the height of your tab bar controller because it can change for other screen dimensions and rotations.
Or, better, you can search for the underlying UITableView instance and set the contentInset property.
EDIT
This seems to have problems with the status bar, since the ABPeoplePickerNavigationController is unable to extend the navigation bar under the status bar if you change it's frame
In both this cases, however, your app will probably be rejected, because you are subclassing a class that explicitly forbids it.
A better and "legal" way to add it is to use a container view controller
Look at This Example
Create a new view controller, add a container view, then add the ABPeoplePickerNavigationController in this way:
-(void)viewDidLoad
{
[super viewDidLoad];
// create the ABPeoplePickerNavigationController instance
ABPeoplePickerNavigationController *controller = [[ABPeoplePickerNavigationController alloc] init];
// add a new child view controller to self
[self addChildViewController:controller];
// alert the child that it has been added to the father
[controller didMoveToParentViewController:self];
// update the child view frame to fit into the containerView
controller.view.frame = self.containerView.bounds;
// translate autoresizing mask into constraints, this is not needed but I usually do because is more pratical
[controller.view setTranslatesAutoresizingMaskIntoConstraints:YES];
// add the `ABPeoplePickerNavigationController` view to the container
[self.containerView addSubview:controller.view];
}
Even in this way ABPeoplePickerNavigationController has problems with the status bar (it doesn't extends correctly under it), so I constrained the container view to the Top Layout Guide and changed the color of the main view of ContainerViewController to fit with the color of the navigation bar
In viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.topViewController.extendedLayoutIncludesOpaqueBars = YES;
}
In viewDidAppear
- (void)viewDidAppear:(BOOL)animated
{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect tabBarFrame = self.tabBarController.tabBar.frame;
self.view.frame = CGRectMake(0, statusBarFrame.size.height, self.view.frame.size.width, CGRectGetMinY(tabBarFrame) - statusBarFrame.size.height);
}
A little late to the party, but here's my answer to the problem or at least some additional input for you to work out a complete solution.
The problem to me seems to be that because UIPeoplePickerNavigationController is not subclass-able or at least is not recommended to be by Apple, you can't use it entirely anyway you like. What I mean is UIPeoplePickerNavigationController is meant to be used as a modal view, which should be presented full screen on iOS and on top of every other view controller. You shouldn't try to use it as a push view controller on a navigation controller stack.
So my suggestion is quite straight-forward. You should simply use your UITabBarController as the receiver of the presentViewController:animated:completion: method. That will take care of presenting the modal on top of the tab bar.
You can access the UITabBarController through the tabBarController property of your current view controller:
ABPeoplePickerNavigationController *peoplePickerController = [ABPeoplePickerNavigationController new];
[peoplePickerController setPeoplePickerDelegate:self];
[self.tabBarController presentViewController:peoplePickerController animated:YES completion:^{}]
Note: I'm writing this from memory so there may be some method naming mistakes.
I have a UINavigationController (NC) containing a UITableViewController (TVC0). When the user taps a row, it loads a UIPageViewController (PVC), which pages back and forth between other UITableViewControllers (TVC1).
TVC0 shows up inside NC (meaning it doesn't hide behind the navigation bar at the top or the tab bar at the bottom). When it pushes PVC, the first TVC1 appears inside the bounds of the nav bar and tab bar. However when I swipe, the TVC1s inside are hidden behind the navigation bar and tab bar. I can pull to reveal the contents, but when I release, it snaps back to behind the bar.
How can I force everything to appear between the two bars? I can't use storyboard (because it's a legacy app) and the embed in... option isn't available.
[Edit]
I added some logging and discovered that my embedded TVC1s frame has an absolute origin of 0, 64, but as soon as I tap, it goes to 0, 0. If I can't figure out a real solution, I can always fake it by adding 64, but I'd much rather figure out what's actually wrong.
[/Edit]
[More Edit]
I was testing another area in the iOS 6 simulator and discovered that this paging works flawlessly in iOS 6. So the issue I'm seeing is iOS 7 specific.
[/More Edit]
Here is my TVC0 viewDidLoad, PVC pageViewController:viewControllerBeforeViewController:, and a helper viewControllerAtIndex::
- (void) viewDidLoad
{
[super viewDidLoad];
NSDictionary* options = [NSDictionary dictionaryWithObject:
[NSNumber numberWithInteger: UIPageViewControllerSpineLocationMin]
forKey:
UIPageViewControllerOptionSpineLocationKey];
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:
UIPageViewControllerTransitionStyleScroll
navigationOrientation:
UIPageViewControllerNavigationOrientationHorizontal
options: options];
self.pageController.dataSource = self;
self.pageController.view.frame = self.view.frame;
NSArray* viewControllers =
[NSArray arrayWithObject: [self viewControllerAtIndex: self.initialIndex]];
[self.pageController setViewControllers: viewControllers
direction: UIPageViewControllerNavigationDirectionForward
animated: NO
completion: nil];
[self addChildViewController: self.pageController];
[self.view addSubview: self.pageController.view];
[self.pageController didMoveToParentViewController: self];
for (UIGestureRecognizer* recognizer in self.pageController.gestureRecognizers)
{
if ([recognizer isKindOfClass: [UITapGestureRecognizer class]])
{
recognizer.enabled = NO;
}
}
}
// SearchResultsList is TVC1
- (SearchResultsList*) viewControllerAtIndex: (NSUInteger) index
{
if (index >= self.items.count)
{
return nil;
}
SearchResultsList* retVal = [[SearchResultsList alloc]
initWithNibName: #"SearchResultsList" bundle: nil];
MyListItem* myItem = [self.items objectAtIndex: index];
MyMatchesRequest* matches = [[MyMatchesRequest alloc] initWithItemId: myItem.itemId];
[matches execute: ^(MySearchResults* results)
{
retVal.tableData = [NSMutableArray arrayWithArray: results.items];
retVal.view.frame = self.view.frame;
retVal.myItem = myItem;
retVal.index = index;
self.title = myItem.displayText;
[[retVal tableView] reloadData];
}];
return retVal;
}
- (UIViewController*) pageViewController: (UIPageViewController*) pageViewController
viewControllerBeforeViewController: (UIViewController*) viewController
{
SearchResultsList* vc = (SearchResultsList*)viewController;
if (vc.index == 0)
{
[self.navigationController popViewControllerAnimated: YES];
return nil;
}
return [self viewControllerAtIndex: vc.index - 1];
}
I had a very painful learning experience with similar behavior :(
Put this in your view controller's init:
self.automaticallyAdjustsScrollViewInsets = NO;
This is a new UIViewController property that defaults to YES in iOS 7
UIViewController Docs
Because you're presenting view controllers in a container which is less than the full size of the screen you need to set
self.pageViewController.definesPresentationContext = YES;
viewControllerWhichIsApageInPageController.modalPresentationStyle = UIModalPresentationCurrentContext
You code seems a little confused. You say it is your Page View Controller's viewDidLoad, yet it creates a new PVC and adds it as a child view controller to itself as parent. If you are really doing this, you are creating a PVC inside another PVC. I doubt this is what you want.
This code really belongs in TVC0 which invokes the PVC when the user taps a row. This invocation wouldn't be correct in viewDidLoad, but might sit nicely in a didSelectRowAtIndexPath method. Instead of bringing it in as a child controller, we can simply push it onto our navigationController's stack. (I expect you are doing this anyway in your outermost PVC).
But just in case, I would remove these three lines:
[self addChildViewController: self.pageController];
[self.view addSubview: self.pageController.view];
[self.pageController didMoveToParentViewController:self];
and replace them with
[self.navigationController pushViewController:self.pageController
animated:YES];
(this is called from your TVC0 - all of the code you have shown can live in TVC0)
Then to prevent the behaviour you describe, when you create your UINavigationController it should suffice to set the translucent property of it's navigationBar to NO.
update
I have looked at this issue in sufficient detail to see some buggy behaviour as you describe occur in some circumstances, but it's fairly hard to replicate.
The cause of the 'jump-up' behaviour is clear. If you have a translucent navBar, and it's automaticallyAdjustsScrollViewInsets is set to YES, in certain situations this can result in a private subview of the pageViewController (_UIQueuingScrollView) setting it's contentOffset.y to -64 when the pageViewController is first loaded. However as soon as the pageVC gets a chance to update itself (for example by a swipe or other touch gesture) it resets it's internal subviews state, losing that rogue contentOffset. So when you touch the first page, it jumps up. Where it then stays. This may be considered a bug, although it may be the result of misusing the pageViewController.
Just setting automaticallyAdjustsScrollViewInsets to NO doesn't cure your ills, as then your pages are all positioned behind the navBar. What you need to do is adjust the frame of the pageViewController itself.
I could go in to more detail, but at that point it gets hard to apply answers to your specific case as your app design looks a little odd, which is probably contributing to the issue.
if you can set your navigation controllers' navigation bar's translucent property to NO the problem should go away.
as I mentioned earlier, I cannot replicate your issue exactly as you describe, so I think you have not given a full and clear picture of your app design
loading a pageViewController as a child of a tableViewController, and making it's view a subview of the tableView, is a very odd way to go, and is doubtless contributing to your problems.
In viewControllerBeforeViewController the pageViewController child seems to pop it's parentViewController (the tableViewController) - so you would never see it's table contents? Either there is more relevant detail to the app, or you haven't described it accurately.
I recommend you first deal with these issues. Your problem may well then disappear.
I'm currently trying to make a small demo app which is supposed to present 2 views at the same time :
- The first one, BaseViewController, is a classic controller with 2 buttons
- The second one, OverViewController, is launch on top of baseView and contains
a last button, and is supposed to be transparent and sending the touch controls
to the first one
Both viewController have their xib. To make it clear : rootView --> baseView + overView (transparent)
My problem is NOT to send the control events from the 2nd view to the first, but to make the 2nd view transparent and functionnal.
Here's what I've tried so far :
1) ------------ Presenting the two view controllers ------------
From the app rootViewController :
- (IBAction)buttonClicked:(id)sender
{
OverViewController *overVC = [[OverViewController alloc] init];
[overVC presentViewControllerFrom:self];
}
From OverViewController :
- (id)init
{
self = [super init];
if (self)
{
self.base = [[BaseViewController alloc] initWithNibName:#"BaseViewController" bundle:nil];
}
return self;
}
I made a custom method to make overView present the baseView before showing up.
- (void)presentViewControllerFrom:(RootViewController *)sender
{
[sender presentViewController:self.base animated:NO completion:nil];
self.view.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0];
self.view.opaque = NO;
[self.base presentViewController:self animated:YES completion:nil];
}
At this point, the baseView appears, followed by the overView. The button of overView work correctly. Great ! But then the background of overView doesn't show what's supposed to be behind and stays black. No alpha transparency.
2) ------------ Presenting the baseView and adding overView as a subview ------------
From the app rootViewController (same than the one before) :
- (IBAction)buttonClicked:(id)sender
{
OverViewController *overVC = [[OverViewController alloc] init];
[overVC presentViewControllerFrom:self];
}
From OverViewController (not presenting but adding subview) :
- (void)presentViewControllerFrom:(RootViewController *)sender
{
[sender presentViewController:self.base animated:NO completion:nil];
self.view.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0];
self.view.opaque = NO;
[self.base.view addSubview:self.view];
}
This time, the transparency is great but any touch on the overView button cause a EXC_BAD_ACCESS to show up.
There I am, wondering how to do this. Any help will be greatly appreciated ! :)
Don't use a combination of presenting a view controller and adding subviews. Choose 1. It should be subview that you choose. It can be owned by another controller and that controller should probably be added as a child view controller.
In your first situation you see black because iOS is removing the (now expected to not be visible) view from the view hierarchy. So your view is transparent but what you expect to be behind it is no longer there.
Your second situation is probably just resulting in an invalid view hierarchy somewhere.
The overview controller should not own the base controller. The base controller should be shown and then the overview controller view added as a subview.
i'm implementing a project with XCODE 5 and storyboard. I have added a view that is a UIPageViewController and when i alloc the first page (for this pageviewcontroller) the view appears normally but from second page the view appears under the navigation bar. What is the matter?
If i set this property
self.navigationController.navigationBar.translucent = NO;
for the view displayed the problem is solved but when i go back from Page View Controller to previous View, the buttons on it are shifted down.
Why? What is the solution?
Furthermore if i set translucent = NO the views displayed in storyboard are different from views displayed in my app (the views are not shifted in storyboard).
I can't post images because i'm not authorized.
This is the code of my PageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
variabiliGlobali = [foaGlobalVariable sharedInstance];
variabiliGlobali.giornataCalID = 1;
numeroGiornate = [variabiliGlobali.calendario count];
self.dataSource = self;
foaGiornataViewController *initialView = [[foaGiornataViewController alloc] init];
// Do any additional setup after loading the view.
[self setViewControllers:[NSArray arrayWithObject:initialView]
direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
}
The foaGiornataViewController is a view that doesn't exist on storyboard but is only a objective-c class.
Thanks in advances.
I have solved. I have setted opaque navigation bar for my Navigation Controller on storyboard.