I want to find out how to add a UISearchBar to a TableViewController - but not to the table view header.
I am having trouble with my existing search bar disappearing after scrolling in certain scenarios. I have found ways to make the search bar "float", but in a couple of corner cases the search bar still disappears after scrolling.
After googling this issue I have found that some people have taken the search bar out of the table view header to deal with this issue. That is relatively easy if your table view is added to a UIViewController. But how do you add a new view (in this case a search bar) to a TableViewController - that is not a subview of the table view automatically provided by the TableViewController?
iPad app iOS 6
-Thanks
Mike C.
First, use storyboards. Add a UIView object to the table header. Then, put your UISearchBar in the UIView. Also, you will need to make your table view controller the delegate for your search bar. Instead of using the scrollViewDidScroll method (or similar), put your floating code into viewDidLayoutSubviews. This works in all cases. I also call bringToFront because I use a custom section header and need to make sure the table header view always stays on top. The top UIEdgeInset is the height of the tableHeaderView.
viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGRect frame=self.tableView.tableHeaderView.frame;
frame.origin.y=self.tableView.contentOffset.y;
if (frame.origin.y <= 0) {
frame.origin.y=0;
[self.tableView setContentInset:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)];
} else {
[self.tableView setContentInset:UIEdgeInsetsMake(48.0, 0.0, 0.0, 0.0)];
}
[self.tableView.tableHeaderView setFrame:frame];
[self.tableView bringSubviewToFront:self.tableView.tableHeaderView];
}
Since nobody from either Stackoverflow, or the Apple Developer's forums responded, I got help from Ron Adams in the Idaho branch of Cocoaheads. Basically, I ended up changing my UITableViewController to a UIViewController and manually adding the tableview and search bar. A little extra work, but it works great!
Related
My goal is the following: have a UISearchBar which is always visible. When it isn't active, there is some content on the bottom part of the controller. When it becomes active, I want to display the results of the search in a UITableView that overlaps the UIController.
The way my search is setup is the following:
I have a fixed UIView on the top of my ViewController, created via Storyboard.
In my viewDidLoad method, I add the searchController.searchBar to that UIView, so that the UISearchBar is permanently active.
I use the very useful following line to hide/display the searchResultsController:
searchController.searchResultsController.view.hidden = FALSE;
All of this works perfectly, except that when I display results, if I scroll down, the results are displayed on top of the UISearchBar.
What is the way to avoid this? I believe this is due to the fact that I use the following line:
[searchBarView addSubview:self.searchController.searchBar];
where searchBarView is an empty placeholder view which I create on my Storyboard and stick to the top. This is the only way I found that have the searchBar displayed permanently. It's important to note that I don't use a navigation controller and that's why I don't add the searchController as a navigation item.
Thanks a lot for your help!
The way in which you are using UISearchController is totally wrong. In case of searchcontroller, you must provide searchcontroller as result tableview's tableHeaderView. Here you are adding searchcontroller into UIView and tableview at some other place. This is obviously not going to work.
Still you can try this possible ways ---
Make the topView an opaque.(dont provide transparency to that containerview)
Use UISearchbar instead of using UISearchcontroller.
By this way, i think your problem will get solved.
Don't use translucent navigation bar
self.navigationController.navigationBar.translucent = NO;
I have search this for many hours and final result was to put this line in viewDidLoad:
self.extendedLayoutIncludesOpaqueBars = YES;
Problem solved :)
I hope it will working for you. Thanks.
My root controller is a TabBarController (tabbed application). One of the tabs, is a UITableViewController. When I switch to that and scroll through the items, they show up under the status bar at the top (signal, battery, etc). I don't want that. I want that to be opaque or... something. It's visually jarring with the text of the table cells underlapping the status stuff.
Can I fix this from my Storyboard with some attributes setting that I don't understand? Or do I need to add some methods to my subclasses? Or maybe I need to wrap my UITableViewController with some other kind of controller?
I've tried numerous variations of the ViewController Layout and Extend Edges settings in the Storyboard attributes page, but none of them seem to change it for the better.
Update: I think my problem is very similar to iOS 7: UITableView shows under status bar. The only difference, is that I'm embedded in a TabBarController, and that case is as the root view. I tried the solution listed there of embedding in a NavigationController and setting Show Navigation Bar to False, but it didn't make any difference.
Screen Shots:
My storyboard (shrunk) showing a tabbed controller, with 2 children, one single view, and the other the table view.
Settings for the tab bar controller
Settings for the table view controller
What the app ends up looking like on my phone
How the Story Ended
Despite lots of answers below, none of them really worked. Some kind of a little, but not really. I tried the Embed in NavigationController approach as well, and that also had issues. What did work though, was this:
Add UIViewController
Set child controller relationship with it and tab bar controller (just like the other two I already had)
Add a TableView (not controller) to the new UIViewController, position as desired, it'll snap to the bottom of the status bar
Set the TableView's delegate and tableSource as the new controller
Create a custom UIViewController subclass and update the class type of the controller in the storyboard
Copy the table related methods from my custom UITableViewController subclass to my new subclass
Select my prototype table cell from the original, and command+drag it to the new table view
Happily delete the original TableViewController (and wrapper NavigationController) too
Update the tab bar item to match the previous
Chock another one up for "you're trying to hard"
Try this in viewDidLoad:
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
20 px being the height of the status bar. If you have a navigation bar use 64 instead of 20
In case anyone is still reading this thread:
What worked for me is to also uncheck the "Extend Edges" options in the parent tab bar controller. That gives a consistent behaviour in iOS7 as well as iOS6.
I was having the same problem when using the SWRevealController.
Using the comments above and below I was able to get it to work by putting this in the
-(void)viewWillAppear instead of ViewDidLoad
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
Have you tried adding something like this to the view controller's viewWillAppear method:
if ([self respondsToSelector:#selector(setEdgesForExtendedLayout:)])
{
self.edgesForExtendedLayout = UIRectEdgeNone;
}
In case anyone misses the How the story ended section at the end of the (now long) question, the short answer is: Use a simple UIViewController with a TableView, instead of a TableViewController if you want to achieve the stated goal.
I added the following to viewWillAppear
self.tableView.contentInset = UIEdgeInsetsMake(22, 0, 0, 0);
You can also solve this through Storyboard.
Select the Table View from the Project Outline (left side of the editor) and then go to Properties (right side) > Size inspector tab > Scroll View > Content Insets > Top
suppose your table's #IBOutlet is
#IBOutlet var tableView: UITableView!
create a function prepareTable(). add the below line into that method
tableView.contentInset.top = UIApplication.shared.statusBarFrame.height
call this method from ViewDidLoad()
Looks like you just want to make the NavBar nonTranslucent, you could try using
[self.navigationController.navigationBar setTranslucent:NO];
I encountered the same problem and the solution that worked for me was to add a section header view:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
I then added 20 to the origin.y of my text on the header.
I then changed the header height by adding 20 to the original height using the
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return myHeight+20;
}
For me an easy solution was (code is in C# that's because appears to be invalid)...
Just in the UITableViewController constructor create a new UIView (set same dimension of the TableView).
Add the TableView to the new created view.
Set new created View to the UITableViewController's View property...
On the constructor of the UITableViewController
var view = new UIView ();
view.Frame = this.TableView.Frame;
view.AddSubview (this.TableView);
this.View = view;
As of iOS 8.4 I didn't get anywhere with the various storyboard options listed in other answers.
I worked around this without resorting to any dimensional constants by putting a regular view in my tab controller, then filling that with a "Container View" which I then connected to my UITableViewController with an "embed" segue.
My table now respects both my navigation bar and the tab bar at the bottom.
Let's say your Outline view, or Storyboard, is a Tab Bar Controller that currently has a Table View Controller. When you run the app, your table view cells are running under the status bar that seems to have a transparent background. This sucks!
If you spent hours trying everything you could find on StackOverflow to no avail, felt like maybe it really was time to consider a new career and were preparing to dial 1-800-LUV-TRUK or 1-800-SHT-KIKR, give yourself a pat on the back, open up whatever elixir you drink in times such as this, because it's not your fault. Really. Travis is absolutely right that no amount of code in viewDidLoad, viewWillAppear, or viewDidAppear or button selecting/deselecting in IB will help in this situation.
Travis' solution above will certainly work, but it's a bit long, there's copying and pasting of code, I have a short attention span such that an episode of Bugs Bunny feels like a full-length movie to me, so I just know that I'll screw-up anything that complicated. But, hey, your mileage may, nay likely will, vary. Anyhoo...
In Xcode 7.3 for an app running iOS 9 (I assume 7 and 8 but I don't know this for certain and am currently too lazy to check) there is an easier way that doesn't require one to write any code. And it's done all within Xcode's Interface Builder.
(Caveat: Sorry if any of the terms aren't accurate. Please let me know where I was mistaken and I'll correct any mislabeling.)
Go to the Utilities area of Interface Builder and select the Object library from the library pane.
Select a Navigation View Controller object and drag it into your Storyboard scene. You'll notice that two scene items appear while you're dragging–these are a Navigation Controller Scene and a Table View Controller Scene.
Delete the duplicate Table View Controller Scene that came-along with your Navigation Controller Scene.
Select the relationship connection between your Tab Bar Controller and your Table View Controller and hit "Delete".
Reposition the Navigation Controller and your Table View Controller the way you want in your storyboard.
Control-drag from your Tab Bar Controller Scene to the Navigation Controller Scene and select "Relationship Segue, view controller".
Control-drag from your Navigation Controller Scene to your Table View Controller Scene and select "Relationship Segue, root view controller".
Lastly, in the Utilities' Objects library, drag a Navigation Item object into your Table View Controller Scene's Table View.
Now when you run your app, you will have a navigation bar and your table view cells will no longer appear under a transparent status bar.
Hope this helps.
I'm trying to change the size of a tableView I have in interface builder and can't seem to. When I first started the app I could drag it around and stretch the sides but all of a sudden I can't adjust it. I tried to delete my tableView and add a new one but the same thing happened. Thanks in advance. Here's what I see when I try to change the size:
if your using a UIViewController you can drag and drop a tableView and can place in a custom position you want. but if your using a UITableViewController you cant move the tableView to your custom position. if you want to do it in UITableViewController you can do like below
if you want your tableView content should show from a point, that you want you can do this way,
[self.tableView setContentInset:UIEdgeInsetsMake(100,0,0,0)];
else if you want set your tableView to a frame in UITableViewController you do this way,
- (void) viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.tableView.frame = CGRectMake(0,100,320,300);
}
hope this will help you.
What kind of view controller are you using to manage your table view? Since you show "prototype cells", I'm guessing it's a UITableViewController. Those are built to fill the entire screen with a single table view (which has always annoyed me.)
Starting with iOS 6, though, you can create a "container" view in another view controler, and then drag an embed segue from your container view onto the table view controller. That does all the housekeeping to make the table view controller a child view controller of the other one, and then you can make it whatever size you want.
If you don't want to use a UITableViewController as a child of another view controller, you can use a regular view controller and wire up the data source and delegate methods yourself. However, things like static table views and prototype cells don't work then.
Hopefully this helps someone still coming across this problem. What I did was make sure the UIViewController had a UIView as its direct child, then dragged the UITableView as a child of the UIView, this allowed me to resize the UITableView.
I have a screen with a table view managed by a controller based on UITableViewController. I would now like to affix a button to the bottom of the screen so that it does not scroll along with the table view cells.
Replacing the UITableViewController with a plain UIViewController is not an option, as I want to include a UIRefreshControl. From what I have read, using a UIRefreshControl without a UITableViewController is currently not possible without resorting to any hacks / relying on undocumented behaviour.
I tried using a UIToolbar provided by the navigation controller which my table view controller is contained in, but there are two problems with that approach:
I only want the toolbar with the button to be present in the top level table view. However, I have not found an elegant way to only show the toolbar for the top level table view. I want the toolbar to animate out of the screen to the left together with the table view when I drill down.
I have not found a way to increase the height of the toolbar. Would I have to put the button in a dummy UIView?
This is approximately what I am aiming for:
http://pic.rockmynews.com/img/free-iphone-app.png
Another idea is using a container view controller containing the button at the bottom and the table view controller above it as its child view controller. But that seems a lot of work for something this simple.
So what is the best way to do this? Any recommendations?
Create the UIView container view. But also create a UIViewController subclass to manage the container. Then, add your existing table view controller as a child view controller and add the table view as a subview. Now you can control all of the subviews and positions while still having automatic refresh control operation.
Just use
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
and return a UIView for the desired button. and
tableView:heightForFooterInSection
and return the footer height
If you aren't willing to use a container view controller, you could use a third-party pull to refresh control like https://github.com/samvermette/SVPullToRefresh instead. This has the added benefit of being backwards compatible with iOS 5, if you want to support it.
You can use a UITableViewController. Just override viewDidLoad and then resize the tableView to make room for your extra view and then add your view programmatically. Make sure to set the right resizing mask so that things look correct on different screen sizes. (Easily tested in the Simulator by trying it out on the iPhone4 and iPhone5)
Description of the problem: with iOS 7 in grouped UITableView there is a gap between the top of the table view and the first cell.
The strange part is that when I load the content for the first time the table appears to be ok (first image), but when I scroll down a space appears between top and first cell (second image):
With style plain this behavior does't occur but unfortunately I need to use the grouped table view style.
Any ideas about?
Just add this in you ViewDidLoad method
self.automaticallyAdjustsScrollViewInsets = NO;
The answer was very funny for me and my team, and worked like a charm
In the Interface Builder, Just move the tableview under another view
in the view hierarchy.
REASON:
We observed that this happens only for the First View in the View Hierarchy, if this first view is a UITableView.
So, all other similar UITableViews do not have this annoying section, except the first.
We Tried moving the UITableView out of the first place in the view hierarchy, and everything was working as expected.
Go to the attributes inspector of the View Controller by selecting the xib or the controller in Storyboard. Uncheck the Adjust Scroll View Insets in Layout. It will solve the problem
If you are using a UITableView with grouped style and only 1 group, use plain style instead solve your problem.
UITableViewController *tableViewController;
tableViewController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
Simplest solution to this problem in grouped type tableView is:
tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 0.01f)];
For solve this problem make sure that you unchecked this field on ViewController:
On ViewController >> Attibutes Inspector >> Layout (unchecked - Adjust Scroll View Insets)
if this is not enough, try this on TableView, set Style to Plain:
This will solve your problem
guys!
I had the same problem. TableView appeared with free space between nav bar and first cell.
This code saved me:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == 0) {
return 10;
}
else return 2;
}
There was a space above the UITableView itself, and also between the cells.
Found my solution in 2 different answers above..posting it again so that nobody misses both solutions.
This removed the space from above :
self.automaticallyAdjustsScrollViewInsets = NO;
and this removed the spaces below the cells :
Setting the 'Style' attribute of the UITableView to 'Plain'
I am working with Xcode 7.3.1, iOS9, and swift 2. I would like to share what worked for me:
Just add this in you ViewDidLoad method
self.automaticallyAdjustsScrollViewInsets = false;
Starting in iOS 7, you automatically get a group header and some space. Compare your app to the Settings app and you'll see. You can work around it by telling the UITableView to set the header height as small as possible. See How to hide first group header.
I realize this was answered a long time ago, but for anyone else running into a similar situation, I'll share what ended up working for me:
If you're using a xib, select the top level view and set 'Status Bar' to 'None' in the Simulated Metrics area of the Attributes Inspector. Fixed my spacing issue right up.
For me this didn't work
self.automaticallyAdjustsScrollViewInsets = NO;
This only caused the table view to sit under the NavigationBar.
What worked for me was to go into my storyboard, and resize my tableView. It seems my tableView had a 20px gap at the top to allow for the statusBar. I scaled it and everything lined up perfectly.
I was seeing this extra space at the top of one of my table views in a very strange situation.
After I added a UIScrollView as the root view of my first controller in my navigation stack, if I presented the next controller as a Show Detail segue, my next controller would have the space above its table view.
The solution for me was to change the segue to Present Modally and everything went back to normal.
The strangest part of the segue changing was that before I added my root view being a UIScrollView, my Show Detail segue was presenting the next controller modally. Yet after I added the root UIScrollView, the Show Detail segue was pushing on the next controller (which was not what I wanted).
Had a similar problem, even setting automaticallyAdjustsScrollViewInsets to NO. This solved for me:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
{
return CGFLOAT_MIN;
}
I was able to remove the gap between navigation bar and first cell writing this line of code in viewDidLoad()
self.tableView.contentInsetAdjustmentBehavior = .never
I tired this with Static Table Views (Style: Grouped).
In the UIViewController.h iOS9 SDK have a method:
#property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets NS_AVAILABLE_IOS(7_0); // Defaults to YES
is not a property, so
self.automaticallyAdjustsScrollViewInsets = NO;
should be
-(BOOL)automaticallyAdjustsScrollViewInsets{
return NO;
}