Display UISearchBar over tableView when user touches UIBarButtonItem - ios

In my iOS app, I would like to have a right side search button in my UINavigationController, and when a user touches the button, the UISearchBar above my UITableView is shown.
I would like the UISearchBar hidden when the view loads, and then hidden again when the user clicks the Cancel button in the UISearchDisplayController.
I've searched everywhere and cannot find an example. Help?

There is a nice sample project here. The key points are:
1.Hide the Search Bar before presenting the View:
-(void)viewWillAppear:(BOOL)animated {
[self hideSearchBar];
}
-(void)hideSearchBar {
CGRect newBounds = self.tableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.tableView.bounds = newBounds;
}
2.On the action target for your search button, display the Search Bar
// make the search bar visible
// code example from https://github.com/versluis/Table-Seach-2013 to deal with iOS 7 behavior
-(IBAction)displaySearchBar:(id)sender {
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
NSTimeInterval delay;
if (self.tableView.contentOffset.y >1000) delay = 0.4;
else delay = 0.1;
[self performSelector:#selector(activateSearch) withObject:nil afterDelay:delay];
}
- (void)activateSearch
{
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.searchBar becomeFirstResponder];
}
3.Finally, hide the SearchBar when Cancel is clicked
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self hideSearchBar];
}

Related

How to create a shrink animation in uinavigationbar?

I use this code in objective c to make a fade in fadeout animation when the user scrolls up or down the uitableview. Is there any way to make a nice animation like shrinking the navigationbar slowly while the user scrolls to top slowly? The more he scrolls to the top the more the navigationbar should shrink.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scrollPos = self.tableView.contentOffset.y ;
if(scrollPos >= _currentOffset ){
//hide navbar and fadeout
[UIView animateWithDuration:0.50 animations:^{
[self.navigationController setNavigationBarHidden:YES animated:YES];
self.navigationController.navigationBar.alpha = 0.0f;
}];
} else {
//Slide it up incrementally and fadein, etc.
[UIView animateWithDuration:0.50 animations:^{
[self.navigationController setNavigationBarHidden:NO animated:YES];
self.navigationController.navigationBar.alpha = 1.0f;
}];
}
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
scrollView = self.tableView;
_currentOffset = self.tableView.contentOffset.y;
}
You cannot customize the size of UINavigationBar on your own. You can only hide/appear it. Apple does not allow you to do that.
You can use UIView instead! Just hide your UINavigationBar and put the same frame of UIView. Since UIView is highly customizable, you can do whatever you want.

Hide NavigationControllerBar when scrolling the tableview

I have implemented a UITableViewController.
The first section is a large image. When the view controller appeared initially, I set the navigationBar to be translucent.
When the tableview is scroll down, the navigationBar.translucent is set to NO and the tableview content frame is moved upwards so that the first section is out of the screen. I implemented the movement in the scrollview delegate :
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
When the tableview is scroll up, the navigation becomes translucent again and the tableview frame is restored.
The problem is, when the scrollview delegate catches the scroll gesture. Once the tableview and navigationBar begins the animation. The scroll action of the tableview stops. Therefore if I want to scroll the tableview to bottom I have to scroll twice, the first time animates the frames and then scroll again, and I think it can be enhanced.
Here is the code.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == _subTable) {
NSIndexPath * indexPath ;
CGFloat offset = scrollView.contentOffset.y;
if ((offset - currentOffset)>40) {
if (!scrollAnimate) {
self.navigationController.navigationBar.translucent = NO;
[UIView animateWithDuration:0.5 animations:^{
[_mainTable setContentOffset:CGPointMake(0, headHeight) animated:YES];
[_subTable setFrame:CGRectMake(CGRectGetWidth(self.menuTable.frame) , 0, kScreen_Width/3.5*2.5, kScreen_Height-schedualHeight-48)];
[_mainTable setFrame:CGRectMake(0, 0, kScreen_Width, _mainTable.frame.size.height+headHeight)];
[_menuTable setFrame: CGRectMake(0, 0, kScreen_Width/3.5, _mainTable.frame.size.height+headHeight-48)];
}];
if (CGRectGetMaxY(_checkOutBar.frame)!= kScreen_Height-44)
{
[_checkOutBar setFrame:CGRectOffset(_checkOutBar.frame, 0, -44)];
}
scrollAnimate = !scrollAnimate;
frameOffset = !frameOffset;
[_mainTable reloadData];
_checkOutBar.tag = 1000;
}
}
else if((offset - currentOffset)<-40)
{
if (scrollAnimate) {
self.navigationController.navigationBar.translucent = YES;
[UIView animateWithDuration:0.5 animations:^{
[_mainTable setFrame:CGRectMake(0, 0, kScreen_Width, kScreen_Height+self.navigationController.navigationBar.frame.size.height+headHeight)];
[self.mainTable setFrame:CGRectOffset(_mainTable.frame, 0, -(self.navigationController.navigationBar.frame.size.height))];
[_subTable setFrame:CGRectMake(CGRectGetWidth(self.menuTable.frame), 0, kScreen_Width/3.5*2.5, tableHeight)];
[_menuTable setFrame:CGRectMake(0, 0, kScreen_Width/3.5, tableHeight)];
}];
scrollAnimate = !scrollAnimate;
frameOffset = !frameOffset;
[_mainTable reloadData];
if (CGRectGetMaxY(_checkOutBar.frame)!= kScreen_Height) {
[_checkOutBar setFrame:CGRectOffset(_checkOutBar.frame, 0, 44)];
}
_checkOutBar.tag = 2000;
}
}
if ((offset - currentOffset)>0)
{
indexPath = [[_subTable indexPathsForVisibleRows]lastObject];
}
else
{
indexPath = [[_subTable indexPathsForVisibleRows]firstObject];
}
if (indexPath) {
if (indexPath.row == 0) {
selected = indexPath.section;
[_menuTable reloadData];
}
}
currentOffset = offset;
}
}
From Apple documents. set NavigationController. hidesBarsOnSwipe = YES;
hidesBarsOnSwipe
Property
A Boolean value indicating whether the navigation bar hides its bars in response to a swipe gesture.
Declaration:
SWIFT:
var hidesBarsOnSwipe: Bool
OBJECTIVE-C:
#property(nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe
Discussion:
When this property is set to YES, an upward swipe hides the navigation bar and toolbar. A downward swipe shows both bars again. If the toolbar does not have any items, it remains visible even after a swipe. The default value of this property is NO.
Availability:
Available in iOS 8.0 and later.

How to implement the scroll process of tableheaderview?

When I add some hidden header view, like search bar, to the table view, it scrolls automatically to content's top or table cell's top, when I set the offset of the scroll to the middle of a search bar. (I used below code)
// in viewDidLoad section
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]
[self.tableView setTableHeaderView:searchBar]
// in viewWillAppear: section
[self.tableView setContentOffset:CGPointMake(0, 44)];
For example, if I scroll up a little amount when the search bar is hidden, it automatically scrolls to display the entire search bar.
And if I scroll down a little when the search bar is displayed, it automatically scrolls to make the search bar hidden.
I used below code to implement this feature to my collection view's header, but that wasn't exactly the same as the table view's feature.
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
CGFloat offset = scrollView.contentOffset.y;
if (offset > 22 && offset < 44) {
[scrollView setContentOffset:CGPointMake(0, 44) animated:YES];
} else if (offset > 44) {
return;
} else {
[scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}
}
I think it is very hard to mimic above feature exactly, because the judgment of displaying the entire search bar or hiding the search bar is very subtle.
So my question is, "Is there any pre-implemented method in iOS SDK, or in UICollectionViewController?".
I googled for many hours but I couldn't found the answer.
I couldn't find the pre-implemented way to implement that feature, but the below way seems to make things similar to that of table view's.
First, add CGFloat type ivar originScrollOffset.
Then, I used the below code to implement scroll view delegate.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
originScrollOffset = scrollView.contentOffset.y;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
CGFloat endScrollOffset = scrollView.contentOffset.y;
NSLog(#"%f %f", originScrollOffset, endScrollOffset);
if (endScrollOffset <= 44 && endScrollOffset >= 0) {
if (originScrollOffset >= 44) {
if (originScrollOffset - endScrollOffset > 10) {
originScrollOffset = 0;
[self.collectionView setContentOffset:CGPointMake(0, 0) animated:YES];
} else {
originScrollOffset = 44;
[self.collectionView setContentOffset:CGPointMake(0, 44) animated:YES];
}
} else {
if (endScrollOffset - originScrollOffset > 10) {
originScrollOffset = 44;
[self.collectionView setContentOffset:CGPointMake(0, 44) animated:YES];
} else {
originScrollOffset = 0;
[self.collectionView setContentOffset:CGPointMake(0, 0) animated:YES];
}
}
}
}

Adding a toolbar to the result of an UISearchDisplayController

i´m having a tough time with UISearchDisplayController. In my scenario i have an UIView pushed onto a navgation controller. In the UIView i have an UITableView and UIToolbar. In the UITableView I´m using UISearchDisplayController.
The toolbar buttons are used to add additional filter options to the search. My problem is that I can´t figure out, how to add the toolbar at the bottom of the result table view of the UISearchDisplayController.
What is the way to go to add a toolbar to the results?
I finally managed to solve my problem.
Instead of using UISearchDisplayController i only add a UISearchBar to my UITableView and replicate the behavior of UISearchDisplayController with the UISearchBarDelegate methods.
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self setSearchText:searchText];
[self filterCards];
}
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
{
[self setScopeIndex:selectedScope];
[self filterCards];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
// Move searchbar to table view
[self.chapterSearchBar removeFromSuperview];
[self.chapterTableView addSubview:[self chapterSearchBar]];
// Show navigation controller
[self.navigationController setNavigationBarHidden:NO animated:YES];
// Hide scope bar an resize
[searchBar setShowsScopeBar:NO];
[searchBar sizeToFit];
// Hide cancel button
[searchBar setShowsCancelButton:NO animated:YES];
// Resize table view
CGRect tableViewRect = [self.chapterTableView frame];
tableViewRect.origin.y = 0;
[self.chapterTableView setFrame:tableViewRect];
// Hide keyboard
[searchBar resignFirstResponder];
[self setSearchText:#""];
[self filterCards];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
// Move searchbar to controller view
[self.chapterSearchBar removeFromSuperview];
[self.view addSubview:[self chapterSearchBar]];
// Hide navigation controller
[self.navigationController setNavigationBarHidden:YES animated:YES];
// Show scope bar an resize
[searchBar setShowsScopeBar:YES];
[searchBar sizeToFit];
// Show cancel button
[searchBar setShowsCancelButton:YES animated:YES];
// Resize table view
CGRect tableViewRect = [self.chapterTableView frame];
tableViewRect.origin.y = 44;
[self.chapterTableView setFrame:tableViewRect];
return YES;
}
If anyone's curious how to solve this issue with still using UISearchDisplayController (cleaner probably), simply set the items of your toolbar to your view controller's toolbarItems while search is active:
self.navigationController.toolbarHidden = NO;
self.toolbarItems = optionsToolbar.items;
The UISearchDisplayController retains the view controller's toolbar according to toolbarItems, so this might already be done for you. Can be useful if the toolbar is only being used during search.

Clear button at uisearchbar not working at all

I created a search bar programmatically and added to my view using the codes below:
- (void)viewDidLoad
{
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(xPositionForSearchBar, yPositionForSearchBar, widthForSearchBar, heightForSearchBar)];
UIView *bg = [[searchBar subviews] objectAtIndex:0];
searchBar.delegate = self;
searchBar.placeholder = #"Search record";
for(UIView *view in searchBar.subviews){
if([view isKindOfClass:[UITextField class]]){
UITextField *tf = (UITextField *)view;
tf.delegate = self;
break;
}
}
[bg removeFromSuperview];
[self.view addSubview: searchBar];
}
The code is implemented with UISearchBarDelegate and UITextFieldDelegate.
I have tried using
- (void)searchBarCancelButtonClicked:(UISearchBar *)aSearchBar
{
NSLog(#"cancel clicked");
searchBar.text = #"";
[aSearchBar resignFirstResponder];
}
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
NSLog(#"clear");
[self performSelector:#selector(searchBarCancelButtonClicked:) withObject:searchBar afterDelay: 0.1];
return YES;
}
and yet, the text inside the searchBar is not cleared at all when i click on the "clear button" - a circle with a "X" inside.
The clear button works when I implemented it in IB. Wonder why?
Kindly advice, many thanks.
This might happen if you position your search bar out of the bounds of a parent view. Then, the touches aren't delivered to your searchBar properly. This also affects text editing controls like copy & paste.
I have checked your code it work fine on device as well as on simulator.

Resources