How can I show a back arrow in the master-view popover button for UISplitViewController in iOS 7? - ios

In my detail VC, I am implementing this UISplitViewController delegate method:
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc
It is then easy for me to set the title of the button, but the result is just a button with plain text, and no back arrow. I am looking to get something like the Mail app where the master popover button also has the back chevron.
How can I do this?

Create your custom bar button item, with the chevron image, set up as you want, and set the target and action of your bar button item to be that of the one passed by the delegate callback. This way, your bar button will perform the same action as the one the system passes to you. You must create your own bar button with an image, because there is no possible way with AppStore approved API to create back bar buttons.
In iOS7, the private subclasses are UINavigationItemView + _UINavigationBarBackIndicatorView. One is the button, the other - the chevron. _UINavigationBarBackIndicatorView is a subclass of UIImageView. So it's pretty close to what you will achieve.

In iOS 8, UISplitViewController has a method:
- (UIBarButtonItem *)displayModeButtonItem
If you set the returned bar button item as the left button of a navigation bar (UINavigationBar), it will display the chevron for you.
On the other hand, if you put the returned bar button item into a toolbar (UIToolbar), it will not display the chevron.
For places where I want the chevron back button shown, but also need several of my own bar button items shown (like the Mail app on iPad does), I have to use a UINavigationBar and a UIToolbar. It's an ugly solution, but I have to partially overlay the UINavigationBar on top of the UIToolbar in order to get a back button chevron along with several of my own bar button items.

To access the default back button image used by Apple as what Leo said, the arrow is a class of type _UINavigationBarBackIndicatorView. Set this image to a back bar button and you are good to go.
Here follows the hack,
UIImage *imgViewBack ;
for (UIView *view in self.navigationController.navigationBar.subviews) {
// The arrow is a class of type _UINavigationBarBackIndicatorView. This is not any of the private methods, so I think
// this is fine for the AppStore...
if ([NSStringFromClass([view class]) isEqualToString:#"_UINavigationBarBackIndicatorView"]) {
// Set the image from the Default BackBtn Imageview
UIImageView *imgView = (UIImageView *) view;
if(imgView){
imgViewBack = imgView.image ;
}
}
}
This is based on Ryan Henning's answer.
It's possible to show a back button representing the master view from the detail view controller. The UISplitview controller doesn't provide a native method for this, but it returns a bar button object which we can directly assign as navigation controller bar button. Its obvious that the detail view controller should be inside a navigation controller for this to work.
self.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;

Related

iOS 10 - View Controller / Navigation Bar Title hidden

I'm currently facing stranges behaviours with iOS 10.
Indeed, everything was working fine, but since I updated to xCode 8 and began testing my App on iOS 10, a lot of stuff went wrong.
For example, all my Navigation Bar's titles are not displayed anymore.
More precisely, when I'm using the menu to navigate threw my app, every time I switch to a different view, there are no title, BUT when I press the back button, I can briefly see it before the transition to the other view.
I don't understand this new behaviour, I didn't change anything in the code, and when I launch the App on iOS 9 or lesser, everything is working properly.
I tried to set the title in the ViewWillAppear / ViewDidLoad, in the prepareForSegue, but nothing is working.
if ([segue.identifier isEqualToString:kMy_Segue]) {
MyViewController* destinationVC = segue.destinationViewController;
[destinationVC setTitle:#"MyTitle"];
}
I feel like there are some changes with the pushed Navigation Controller, or the title item is not at the same index than the Navigation Bar itself because when I navigate threw subviews in the menu, the title only appears when I press back.
For example I have a category in my Menu called "World".
When I tap it I want the title of the subview to be "World", but nothing is displayed. Then, I have all the continents listed "Africa", "Europe", "Asia" etc...
When I tap on Africa, I want the next title to be "Africa" right?
And again, nothing is displayed BUT if I press the back button and go back to the list of continents, the title "World" appears.
If anyone has encountered this issue, I would really appreciate some help.
Follow this:
Solution-1
Goto to the viewController, then click on NavigationItem as shown below:
In the right pane, change "Title" as follows:
Solution-2
Add a UIView to your navigationBar as shown below:
Add an UILabel to your navigationItem as shown below:
Change the frame of the newly added UILabel as follows:
Change text of UILabel to "Sample Title" and change UIView backgroundColor to clearColor.
I have made a sample in Xcode8, please check my GitHub link below:
https://github.com/k-sathireddy/NavigationItemSample
Have you try to adding navigation item on to your navigation bar? You'r using Storyboard for this design.
I found a solution to my issue. It's really weird.
I have a fade animation to the navigation bar on the Home Page.
It's a scroll view so that when I scroll down I can still see the title and the navigation bar.
On iOS < 10, the fade animation only change the background color and transparency. But when I launch the app on iOS 10, the fade effect hide everything, the menu icon, the title, everything. I believe Apple changed the structure of the navigation bar items.
Moreover, when I tap on the menu icon to navigate threw my App when the fade animation is on going, I can see that the title and the navigation bar items are under "fade effect" and even for the next ViewControllers's title after my navigation.
So it's working, it's just that the menu icon, titles etc.. are hidden on the Navigation Bar.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIColor * color = [Constants backgroundColor];
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat threshold = 250;
if (offsetY > threshold) {
[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:1]];
} else {
CGFloat alpha = offsetY / threshold;
[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:alpha]];
}
}
I guess the issue is coming from the library LTNavigationBar that I used to change the appearance of the NavigationBar dynamically...

UISearchController's searchbar is not responding

I am not able to get responding events on tapping UISearchController's search bar in iOS 8.
I am displaying custom view with dim background like alert view appearance, on pressing button in a view, where custom view has UISearchController's search bar as sub view. Programmatically added searchController. When I try to touch search bar, it is not responding in iOS 8 whereas I have added search bar with UISearchDisplayController for iOS 7, it is working fine.
I have viewController A with navigation bar. In viewController A, I have a button. On pressing button, I am trying to show view as custom view with dim background like alert view appearance. So I have added following line in button method.
class_name *view = [[class_name alloc] initWithNibName:#"xib_name" bundle:nil];
[self.navigationController.view addSubview:view];
Xib file of class_name has dim background with subviews like searchController's search bar.
Instead of
[self.navigationController.view addSubview:view];
added
[self presentViewController:view animated:YES completion:nil];
UISearchController's search bar is working now but i am not able to get transparent background view, instead black background appears.
I need to display previous views content and on top that current views content like alert view.
Please guide me in objective-C.

How to add Navigation bar to view controller with tab bar item

I have an app that uses bottom tabs aswell as a side menu, to have the button that initiates the side menu i use the typical three line menu button, to put that there I have a Navigation Bar. With the bar in place there is no way I can get the bar to be on top of the screen. I built it with interface builder, and heres a screenshot. The question is how do i have the navigation bar alone without the other grey bar above it?
The issue you're encountering is due to the fact that you're manually creating a navigation bar for your view controller, instead of using the bar that you get for free by embedding the view controller in a tab bar controller, hence the reason you see two bars. The other answer suggesting hiding the auto-generated navigation bar is not the correct solution. Instead, you should place your menu button and view title in the auto-generated bar instead of manually creating your own (you almost never want to do that, in-fact).
So what you should do instead is set the title property of your view controller to be "News", and the leftBarButtonItem property of the view controller to be your hamburger menu button (an instance of UIBarButtonItem initialized with an image for the icon).
For example (inside your view controller's viewDidLoad method or wherever appropriate):
self.title = #"News";
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menuIcon"] style:UIBarButtonItemStylePlain target:self action:#selector(showSideMenu)];
If you want to remove the topmost navigation bar you need use self.navigationController.navigationBarHidden = YES; for view controllers that used for tabs in UITabBarController:
// StoriesViewController.m
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = YES;
}

UINaviagtionBar subview doesn't fade out during UIViewController "Back" transition

I have a UINavigationBar based app. I've created a custom UIView with some titles and added it as a subview to the navigation bar:
[self.navigationController.navigationBar addSubview:_navbarView];
Everything works ok until I hit the back button in the navigation bar and the UIViewController transition occurs.
The problem is that my custom view doesn't fade away like the others elements in the UINavigationBar, it just stays the same and disappears when the transition is complete.
I want it to fade away during the transition like the native elements of the UINavigationBar, is there any way to achieve this?
If you add a subview to the navigation bar, then it will just stay there; the navigation controller doesn't know to do anything special with it. You say your custom view has "some titles" - have you tried doing this instead?
self.navigationItem.titleView = _navbarView;
Then the navigation controller knows that the view should be used in place of your controller's title, and it should animate in and out.
If that doesn't work, you'll need to look at becoming the navigation controller's delegate. Since iOS7, this can get quite complex.
If you need custom navigation bar it could be a good idea to create UINavigationController with custom UINavigationBar
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
in your navigation bar class you can implement
- (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated
{
if (animated) {
//your_problem_view animation here
}
[super popNavigationItemAnimated];
}

iOS Navigation Bar: change left bar button from menu to back

I have an app that uses a side menu and has a few main screens that can be accessed from the menu and others that can only be accessed from these screens.
What I want is to have a menu button on the navigation bar that opens the menu and can only be visible on the main screens. On the other screens I want to have a back button, instead of the menu button.
I've already put the menu button like this:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"IconMenu"] style:UIBarButtonItemStylePlain target:self.revealViewController action:#selector(revealToggle:)];
But I can't figure out how to change it with the back button when I need it.
Assuming than by "main screens" you mean root (first) view controllers in the navigation view controllers corresponding to the selected side menu items, this might be a solution for your problem: you can create a superclass for all your view controllers, say MyBaseViewController and rewrite viewWillAppear: method, that will determine whether it should have a default back button or a "revealSideMenu" button, based on whether it's a "main screen" or not.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self == [self.navigationController.viewControllers firstObject]) {
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"IconMenu"] style:UIBarButtonItemStylePlain target:self.revealViewController action:#selector(revealToggle:)];
}
}
you can do that in 2 different ways:
the first is in the viewDidAppear check if the back button is already present (when you push a VC the back button automatically added but is avalaible programmatically only after the viewDidAppear) and then decide to add or not the menu button,
the second is add a parameter to your VC init method like isRoot or hasMenu or whatever you like to name it, and using that flag decide to add the menu or the back button
if you chose to add your own back button you have to call this method in your back selector
[self.navigationController popViewControllerAnimated:YES];
The easiest way, IMO, is just to click on the title bar of the first ViewController and in the Attribute Inspector (⌥+⌘+4) change the Navigation Item info the way you want: Title -> what will show up in the back button* or if you want it to say something other than the Title of the first ViewController or the word "Back" you can just put it in the Back Button field.
*If the Title of the second ViewController is too long for it to fit it will be replaced with the word "Back" (and if the word "Back" doesn't fit it will only have the arrow sign).

Resources