I have a TabBar application, which I have added a UIButton too, which brings up a menu.
This is how the menu button is added to the Tab Controller:
//TabBarViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.menuBtn = [UIButton buttonWithType:UIButtonTypeCustom];
menuBtn.frame = CGRectMake(285, 28, 24, 24);
[menuBtn setBackgroundImage:[UIImage imageNamed:#"menu.png"] forState:UIControlStateNormal];
[menuBtn addTarget:self action:#selector(showMenu:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.menuBtn];
}
This functions fine and produces the following:
I have the button in the Tab Bar Controller so it shows on each tab.
This all works fine, but when I use the search bar the menu button becomes in the way:
How would I be able to hide the menu button while the search is active?
I have worked out how to detect when the search bar is active, but I am having trouble trying to hide the menu button.
//SearchViewController.m
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
TabBarViewController *vc = [[TabBarViewController alloc]init];
[vc.menuBtn setHidden:YES];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
TabBarViewController *vc = [[TabBarViewController alloc]init];
[vc.menuBtn setHidden:NO];
}
I have tried a few methods, but nothing is able to hide the menu button. Is this impossible, or am I missing something?
Any help would be much appreciated, Thanks
As rdelmar commented:
you need to get a reference to the tab bar controller that you already have, not create a new one with alloc init.
Currently I was making a new TabBarViewController, with this:
TabBarViewController *vc = [[TabBarViewController alloc]init];
Instead, I needed to use a reference. I was able to do this by using 'parentViewController'.
The structure of the app from the TabBarViewController is:
TabBarViewController
SearchNavigationController
SearchViewController
So by using 'parentViewController' twice I was able to reference TabBarViewController, then hide the menuBtn.
The following is what worked for me:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
((TabBarViewController *)self.parentViewController.parentViewController).menuBtn.hidden = YES;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
((TabBarViewController *)self.parentViewController.parentViewController).menuBtn.hidden = NO;
}
Related
I have a UISearchBar with some customizations and I create a UISearchDisplayController like this
self.searchController = [[UISearchDisplayController alloc]initWithSearchBar:self.searchBar contentsController:self];
I want the search bar to appear on navigation bar so I also set
self.searchDisplayController.displaysSearchBarInNavigationBar = true;
Now the search bar shows in the Navigation Bar, but I want to show the search bar of my UISearchDisplayController only when I tap on a Navigation Bar Button Item. I want to have a behaviour like:
Hide the search bar initially
Show search bar when a navigation bar button is clicked
Hide the search bar when I tap "Cancel" button of
the search bar
I tried to hide/unhide it like:
self.searchDisplayController.searchBar.hidden = YES;
but the code doesn't seem working. I've spent a lot time searching the solution to have the behaviour I want and still no luck. Thanks.
Try this out:
CGRect searchFrame = self.searchDisplayController.searchBar.frame;
searchFrame.size.height = 0;
self.searchDisplayController.searchBar.frame = searchFrame;
self.searchDisplayController.searchBar.hidden = YES;
EDIT: I just tried with below code and it worked. See if this helps you!
- (void)viewDidLoad {
[super viewDidLoad];
[self.searchDisplayController.searchContentsController.navigationController setNavigationBarHidden:YES animated:YES];
[self performSelector:#selector(test) withObject:nil afterDelay:2.0];
}
- (void)test {
[self.searchDisplayController.searchContentsController.navigationController setNavigationBarHidden:NO animated:YES];
}
Maybe this is a suitable solution?
To complete task 1, in your TVC lifecycle method viewDidLoad, insert a non-animated scroll that places the search bar beneath the Nav bar...
- (void)viewDidLoad {
[super viewDidLoad];
// Scroll off screen the search bar (44 points)
[[self tableView] setContentOffset:CGPointMake(0, 44)];
// other code for method
}
To complete task 2, in your TVC create a custom action method associated with a UIBarButtonItem, that effectively hides the Nav bar, at the same time revealing the search bar...
- (IBAction)hideNavBar:(UIBarButtonItem *)sender {
[[self navigationController] setNavigationBarHidden:YES animated:YES]
}
To complete task 3, in your TVC use the UISearchDisplayController Delegate method to effectively display the Nav bar and at the same time hide the search bar...
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[[self navigationController] setNavigationBarHidden:NO animated:YES];
[[self tableView] setContentOffset:CGPointMake(0, 44)];
// You might also like to...
[self setSearchBarText:nil]; // if you are using a property to hold the search bar text
[self setSearchResults:nil]; // if you are using a property to hold the search results
}
I am using storyboard in my app where I have to navigate to another view controller without animation.I am successfully doing it using the custom segue.But I when I come back to the previous view controller then by using navigation bar default back button then it is animating while coming backward.So going forward it is not animating and going backward it is animating.I want to stop the default animation of the back button.
Custom Seague
// PushNoAnimationSegue.h
#interface PushNoAnimationSegue : UIStoryboardSegue
#end
// PushNoAnimationSegue.m
#implementation PushNoAnimationSegue
-(void) perform{
[[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:NO];
}
#end
Using this code I am successfully going to the next view controller without animation since -(void) perform is called automatically in the forward direction.When I come back it is not called.So please suggest me if there is anything wrong with the implementation or I should go with some other method.
hope this will help
1.custom button on navigation bar
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(x,y,width,height)];
[btn setImage:[UIImage imageNamed:#"some_image.png"] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(popViewController) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.navigationItem.leftBarButtonItem =backButtonItem;
and then
void popViewController()
{
[self.navigationController popViewControllerAnimated:NO];
}
If you use NavigationController then use this
[self.navigationController popViewControllerAnimated:NO];
Or
[self dismissViewControllerAnimated:NO completion:nil];
in my UITableViewControllers I have added navigation bars but the problem is that the Title of the navigation bar intersects with the status bar. Normally I would do "positionForBar" and return UIBarPositioningTopAttached but that only works with UIViewControllers. Thus, I used the "prefersStatusBarHidden" method an return YES. Obviously, this bears a cost to the user since they can't view the time and battery life while they're on those screens while using the app. So is there a way to keep the title navigation bar and the status bar from not overlapping, kinda like in iOS 6?
Here's what i'm talking about:
it doesn't look very clean and i'm trying to fix it
In storyboard click on your UITableViewController then simply click on edit -> embed -> navigation controller. You don't need to use it to navigate anywhere but it will setup your title bar correctly for you.
Try with the code
self.edgesForExtendedLayout = UIRectEdgeNone;
I had the same issue. this fixed it:
credit to: malcolmhall
Its just pushing the nav down but works
// in the .h
#property (strong) UINavigationBar* navigationBar;
//in the .m
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"Title";
self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectZero];
[self.view addSubview:_navigationBar];
[self.navigationBar pushNavigationItem:self.navigationItem animated:NO];
}
-(void)layoutNavigationBar{
self.navigationBar.frame = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.frame.size.width, self.topLayoutGuide.length + 44);
self.tableView.contentInset = UIEdgeInsetsMake(self.navigationBar.frame.size.height, 0, 0, 0);
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//no need to call super
[self layoutNavigationBar];
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[self layoutNavigationBar];
}
I would like to add a searchbar to a UICollectionViewController, that's embedded the following way:
UItabbarController > UINavigationbarController > UICollectionViewController > SearchBar (!)
In this view, the search bar would replace the NavigationBar.
Under the same design, if I test the above with a UITableViewController, the searchbar shows up fine (both programmatically and via the Storyboard)
Problem is I can't get to add the search bar over the UICollectionViewController when I use the StoryBoard framework; it just sits in the middle of the view, and I'm clueless as to how to move it to the top. Plus, it always appears below the UICollectionview, so it's not visible.
So, taking the other route, programmatically:
-(void)viewWillAppear:(BOOL)animated{
self.searchBarTop = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
[self.searchBarTop setPlaceholder:#"Enter your command here"];
self.searchDC = [[UISearchDisplayController alloc]initWithSearchBar:self.searchBarTop contentsController:self];
self.searchBarTop.delegate = self;
[[self navigationController] setNavigationBarHidden:NO animated:animated];
[self.navigationController.navigationBar addSubview:self.searchBarTop];
}
With this, the search bar shows up fine. But unfortunately, when I type in some text, it disappears above the view - presumably because the underlying navBar does so - (don't know why...)
I'm not sure exactly why the searchbar is fine with a UITableViewController, and why it is such a pain for a UICollectionViewController.
That said, anyone has a clue as to why the searchbar/navBar disappear, and how I can fix that ?
Any solution is welcome..
thanks !
-A
Add a Header and put the SearchBar in that (that is what I have done in the past). That being said, I have gotten in the habit of hardly ever using either a UITableViewController (unless I am implementing a StaticCell TableView) or a UICollectionViewController. What I would suggest is to implement a standard UIViewController and just add in your UICollectionView. Size the CollectionView down some and put the SearchBar at the top. This allows you to have a SearchBar that is always displayed (which my users generally like better than having to scroll to the top to change, edit a search)
I use the following code to add a UISearchBar to the UICollectionViewController.
Unfortunately I couldn't make UISearchDisplayController working.
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.collectionView.frame), 44)];
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.delegate = self;
[self.collectionView addSubview:self.searchBar];
[self.collectionView setContentOffset:CGPointMake(0, 44)];
}
- (void) viewWillAppear:(BOOL)animated{
// to show search bar
[self.collectionView setContentOffset:CGPointMake(0, 0)];
// to hide search bar
[self.collectionView setContentOffset:CGPointMake(0, 44)];
}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[searchBar setText:#""];
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
}
Apple's "Mobile Human Interface Guidelines" says about Popovers:
When possible, allow people to close one popover and open a new one
with one tap. This behavior is especially desirable when several
different bar buttons each open a popover, because it prevents people
from having to make extra taps.
The only solution I can think right now is to track the position of the touch when dismissing the popover and check whether that was the position of another button.
Is there any easier way to do this?
PS: I searched in stackoverflow and googled quite a while before posting. Sorry, if this was asked here before.
UPDATE
I guess I didn't explain myself well. Let's say I have three buttons. All of them open a popover. My user taps button #1 and a popover opens. While the popover is open, the user taps button #2. The popover gets dismissed (because the user tapped outside of the popover - default behavior of non-modal popovers) and a new popover opens up because the user had clicked on button #2. All of that without having to tap twice: once to dismiss the popover and twice for opening the new one.
2nd UPDATE
I built a simple dummy to reproduce what I'm trying to do. When the user taps on a button and a popover is open, the method that opens the popovers doesn't get called. Therefore the user has to click twice to open the second popover. Any ideas?
#import "RootViewController.h"
#import "AViewController.h"
#interface RootViewController()
#property (nonatomic, retain) UIPopoverController *currentPopover;
#end
#implementation RootViewController
#synthesize currentPopover;
- (void)loadView
{
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
UIView *view = [[UIView alloc] initWithFrame:applicationFrame];
CGRect buttonFrame = CGRectMake(50, 100, 200, 40);
for (int i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:[NSString stringWithFormat:#"Button %i", i + 1] forState:UIControlStateNormal];
[button addTarget:self action:#selector(openPopover:) forControlEvents:UIControlEventTouchDown];
[button setFrame:buttonFrame];
[view addSubview:button];
buttonFrame.origin.y += 50;
}
self.view = view;
[view release];
}
- (IBAction)openPopover:(id)sender
{
AViewController *avc = [[AViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:avc];
[avc release];
UIPopoverController *tempPopover = [[UIPopoverController alloc] initWithContentViewController:navigationController];
[tempPopover setDelegate:self];
[tempPopover setPopoverContentSize:CGSizeMake(320, 500)];
[tempPopover presentPopoverFromRect:[sender frame] inView:[self view] permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
self.currentPopover = tempPopover;
[tempPopover release];
[navigationController release];
}
- (void)dealloc
{
[currentPopover release];
[super dealloc];
}
#end
If you use bar button items in a toolbar, the open popover is not automatically closed when you tap another bar button item. In these situations you should close the visible popover and open the other one in one step.
- (IBAction)sortAction {
[searchBarView resignFirstResponder];
[self.popoverController dismissPopoverAnimated:YES]; //clear popover
self.popoverController = popoverSetting;
[self.popoverController presentPopoverFromBarButtonItem:sortBarButtonItem
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //show popover
}
hope will help you
Lets say you have 3 buttons and each opens a popup. You could use a state variable that tracks whether a popup is currently open, and inside each "open popup" method, close the existing one (if it is open) before opening the new popup.