Hide UISearchBar until user scrolls? - ios

I implemented a search bar and search display controller on top of my table view.
When the view loads the search bar and relative scopes are always visible.
Is there a simple way to hide it until the user scrolls down, like it happens in the Music app?

You need to add search bar as a header of the table view and then set the contentoffset property of table view in viewDidLoad as,
[self.tableView setContentOffset:CGPointMake(0,44) animated:YES];//or (0, 88) depends on the height of it
For search display controller, you can try this as well,
[self.searchDisplayController setActive:NO animated:YES];

another approach without hardcode
[self.tableView setContentOffset:CGPointMake(0.0, self.tableView.tableHeaderView.frame.size.height) animated:YES];

After a few hours of hair pulling, something that works
on iOS 9
doesn't depend on the number of rows in the table
with variable height rows
Considering the searchbar is the tableView.tableHeaderView
#interface MyTableViewController ()
#property (nonatomic, assign) BOOL firstLayout;
#end
- (void) viewDidLoad {
[super viewDidLoad];
self.firstLayout = YES;
//your code
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
if(self.firstLayout){
CGPoint offset = CGPointMake(0, self.tableView.tableHeaderView.frame.size.height - self.tableView.contentInset.top);
[self.tableView setContentOffset:offset];
self.firstLayout = NO;
}
}

for iOS 7 and using UINavigationController
[self.tableView setContentOffset:CGPointMake(0, self.searchBar.height + self.navigationController.navigationBar.height)];

Best way i did reload tableview in
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
[self performSelector:#selector(reload:) withObject:nil afterDelay:0.0];
self.edgesForExtendedLayout = UIRectEdgeNone;
}
- (void)reload:(__unused id)sender {
[self.searchDisplayController setActive:YES];
[self.tableView reloadData];
[self.refreshControl endRefreshing];
} else {
[self.refreshControl endRefreshing];
[[[UIAlertView alloc]initWithTitle:#"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] show];
}
}
Thanks

This works fine on iOS9+
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableView.contentOffset = CGPointMake(0, -20);
});
}

Related

Disabling selection in the background when activity indicator is present

I am adding activity indicator on top of the view and wish to disable the selections in the background when the activity indicator is on. Also for some reason, my activity indicator is still spins for about 30-45 seconds(depending on the network speed) after the data is displayed on the table view. I have created a category for activity indicator.
Activity Indicator category code:
- (UIView *)overlayView {
return objc_getAssociatedObject(self, OverlayViewKey);
}
- (void)setOverlayView:(UIView *)overlayView {
objc_setAssociatedObject(self, OverlayViewKey, overlayView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)showActivityIndicatorForView:(UIView *)view {
self.overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
self.center = self.overlayView.center;
[view setUserInteractionEnabled:NO];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self.overlayView setUserInteractionEnabled:NO];
[self startAnimating];
[self.overlayView addSubview:self];
[view addSubview:self.overlayView];
[view bringSubviewToFront:self.overlayView];
self.hidesWhenStopped = YES;
self.hidden = NO;
}
- (void)hideActivityIndicatorForView:(UIView *)view {
[self stopAnimating];
[self.overlayView setUserInteractionEnabled:YES];
[self.overlayView removeFromSuperview];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
[view setUserInteractionEnabled:YES];
}
Usages in table view controller:
#interface MyTableViewController()
#property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
#end
#implementation MyTableViewController
- (id) initWithSomething:(NSString *)something {
self = [super init];
if (self) {
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.overlayView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self getDataServiceRequest];
[self.activityIndicator showActivityIndicatorForView:self.navigationController.view];
}
- (void)requestCompletionCallBack sender:(ServiceAPI *)sender {
// Do something here with the data
[self.activityIndicator hideActivityIndicatorForView:self.navigationController.view];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
#end
What am I doing wrong here? Why am I still able to select the data in the background when the activity indicator is on and even after disabling the user interaction.
Move your call to hideActivityIndicatorForView to inside the call to dispatch_async(dispatch_get_main_queue(). It's a UI call, and needs to be done on the main thread.
As for how to disable other actions on your view controller, you have a few options. One simple thing I've done is the put the activity indicator inside a view that's pinned to the whole screen, set to opaque=false, and with a color that's black with an alpha setting of 0.5. That way the content underneath is visible but the user can't click on it. You need to add an outlet to your "coveringView" and show-hide it instead of showing/hiding the activity indicator view.
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
fix it
[self performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];

how to hide systems status bar and show alert in status bar for few sec by animation in iOS 9

I want to show alert in status bar for small duration with animation and hide systems status bar for that duration
I have referred this but enable to hide system's status bar for that particular time,failed to add animation
Here is my code
NSString *status=#"welcome..";
UIView *notificationView= [JDStatusBarNotification showWithStatus:(NSString *)status styleName:JDStatusBarStyleDark];
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
notificationView.frame=statusBarFrame;
[self.view addSubview:notificationView];
UIView *dismissNotificationView=[JDStatusBarNotification showWithStatus:(NSString *)status
dismissAfter:(NSTimeInterval)5.0f styleName:JDStatusBarStyleDark];
[self.view addSubview:dismissNotificationView]; `
also tried this but it moves another window then shows and turns back
here is the code used
MTStatusBarOverlay *overlay = [MTStatusBarOverlay sharedInstance];
overlay.animation = MTStatusBarOverlayAnimationFallDown; // MTStatusBarOverlayAnimationShrink
overlay.detailViewMode = MTDetailViewModeHistory; // enable automatic history-tracking and show in detail-view
overlay.delegate = self;
overlay.progress = 0.0;
[overlay postImmediateFinishMessage:#"welcome" duration:2.0 animated:YES];
overlay.progress = 1.0;
please help..thanks in advance
I'm not sure when you want the alert to appear, so I will assume just after loading the view. I didn't use the two frameworks, but tested it with a generic red UIView and it worked with the code below:
#import "ViewController.h"
#interface ViewController () {
BOOL animating;
CGRect aimFrame;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
animating = YES; //To set if we are showing the alert or not
aimFrame = [[UIApplication sharedApplication] statusBarFrame];
[self setNeedsStatusBarAppearanceUpdate];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIView *notificationView = [[UIView alloc] init];
[notificationView setFrame:aimFrame];
[notificationView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:notificationView];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[notificationView removeFromSuperview];
animating = NO;
[self setNeedsStatusBarAppearanceUpdate];
});
}
- (BOOL)prefersStatusBarHidden {
// Toggle based upon if we are showing the alert
if (animating) {
return YES;
} else {
return NO;
}
}
#end
I hope this helps, let me know if it still doesn't work or if I miss understood something :)
Try my code to complete hide the status bar:
-(BOOL)prefersStatusBarHidden{
return YES;
}

Objective C- UIActivityIndicatorView not animating

I am having some trouble getting my UIActivityIndicatorView to start animating. Here is my setup:
In my viewDidLoad in my view controller I have:
- (void)viewDidLoad{
schoolList = NO;
_activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[_activityIndicator startAnimating];
[NSThread detachNewThreadSelector: #selector(getSchoolList) toTarget: self withObject: nil];
[self performSelector:#selector(updateUI) withObject:nil afterDelay:20.0];
[super viewDidLoad];
}
The selector getSchoolList communicates with a server to retrieve a list of schools in a given state. Then, the selector updateUI is called to populate my UIPickerView with the list. In my updateUI selector I have:
-(void)updateUI {
_schools = [_server returnData];
if(!(_schools == nil)) {
NSLog(#"update the UI");
}
else
NSLog(#"Error:Show re-load button");
[_activityIndicator stopAnimating];
}
When I run this code, my UIActivityIndicatorView shows up, but does not animate. Can someone explain the proper way to animate my UIActivityIndicatorView? Any help is much appreciated.
You need to add the UIActivityIndicatorView to your view in viewDidLoad like this:
- (void)viewDidLoad {
schoolList = NO;
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self addSubview:_activityIndicator];
[_activityIndicator startAnimating];
[NSThread detachNewThreadSelector: #selector(getSchoolList) toTarget: self withObject: nil];
[self performSelector:#selector(updateUI) withObject:nil afterDelay:20.0];
[super viewDidLoad];
}
EDIT
If _activityIndicator is a properly connected IBOutlet to a UIActivityIndicatorView, you should only need to check the 'animating' box. There would be no need to alloc/init another UIActivityIndicatorView.
Breakpoint the update function, but I don't see where you add that as a view to the hierarchy. I think you're looking at a different indicator view in the program.

Hidden searchbar slides down when view shown second time

I use the following code to hide searchbar:
- (void)updateContentOffset
{
self.tableView.contentOffset = CGPointMake(0, 44);
}
- (void)viewWillAppear:(BOOL)animated
{
NSLog(#"%s",__PRETTY_FUNCTION__);
[super viewWillAppear:animated];
[self searchBarShouldEndEditing:self.searchDisplayController.searchBar];
[self performSelector:#selector(updateContentOffset) withObject:nil afterDelay:0.0];
self.fetchedResultsController.delegate = self;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.fetchedResultsController performFetch:nil];
[self.tableView reloadData];
[self.tableView scrollRectToVisible:CGRectMake(0, 44, 1, 1) animated:YES];
}
The code works perfectly when view is shown for the first time.
Next time it's shown(returning from another controller) it slides a bit down than it should be and I have no idea why it happens.
OK, in my case I played with a delay and found that making it 0.1 makes it work as planned.
[self performSelector:#selector(updateContentOffset) withObject:nil afterDelay:0.1];

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.

Resources