I'm using two searchbar on top of eachother in my layout like so :
Both search bar have a UISearchDisplayController that display a suggestions table.
My problem is, the top search bar's display controller draws its UITable over the bottom searchbar like so :
I tried to move the bottom table down in the uisearchdisplaydelegate like so:
- (void)searchDisplayController:(UISearchDisplayController *)controller
didLoadSearchResultsTableView:(UITableView *)tableView
{
float yOffset = 50.0f;
tableView.frame = CGRectMake(tableView.frame.origin.x,tableView.frame.origin.y + yOffset,tableView.frame.size.width, tableView.frame.size.height);
}
But even though the method get called at the right time, it doesnt seem to do anything.
Id basically like the top searchbar suggestion table to be located at the same position as the bottom search bar suggestion table
I'm using storyboards and autolayout latest xcode
In iOS 7, you can just set the y origin to the yOffset. If you print out the frame of the table view in
-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
you'll notice that the origin.y is at 0,0. In iOS 6 however, it's different. If you're planning on supporting both versions you'll need a check in there. Try setting the origin.y in the delegate method mentioned above.
Related
[Update] Ive added some content inset to my table view. So is it possible to add a view in the gap that is created ?
What I want to achieve is the following scroll effect :
Open the AppStore on the iPhone and go to the Featured tab.
Swipe down : Only the table view scrolls down, the banner with images stays fixed
Swipe up : Everything including the banner view moves up.
My initial thoughts were that there is a table view inside a scroll view but Apple advises against doing that ...
My second attempt was to use a table header view, but the header view would scroll both ways.
So what kind of tweaking has to be done to UITableViewController to achieve this effect ?
What I have so far :
What I need is basically this
For example :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y < 0 ){
CGRect frame = self.myView.frame;
frame.origin.y = scrollView.contentOffset.y ;
self.myView.frame = frame;
}
}
It's the idea !
They used sections nothing fancy.
You'll want to use:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
Try returning a UIView for the viewForHeaderInSection and it will give you the same as the App Store Features tab.
EDIT: I think I am narrowing down the issue here. I just found an easier way to recreate what I want. If you create a new project with a storyboard, drag on a tableview controller and drag on a Search Bar as a subview of the tableview. If you run this (with some dummy cells), and you scroll so about half of the search bar is showing, the search bar will snap to the top of the view. If you try this by dragging on a UIView instead of a Search Bar, this behavior no longer happens. How can I get this behavior with a UIView as a subview?
Hopefully this made it more clear, thanks guys.
I have a header in my plain style table view, I am implementing it like this:
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 51;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
SegmentedHeaderView *header = [[SegmentedHeaderView alloc]initWithFrame:CGRectMake(0, 0, 320, 51)];
return header;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat sectionHeaderHeight = 51;
if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
}
}
I want the header to scroll with the tableview and not stick to the top, and it does that correctly. However, when I scroll to the top, I want the header to work like the search bar header does in the messages app in iOS 7. In the messages app, when you are scrolling and you stop halfway through the search bar, either the search bar sticks to the top of the view, or the first cell sticks to the top of the view.
How can I implement this so when the user stops scrolling with part of the header view showing the header jumps up?
Edit: The behavior I want can also be seen with the search bar in the Mail app.
I have a question about the usage of UITableView. I have added a UIView above the cells of my UITableView (see image).
This is very nice because I can add some images and labels there and it will scroll with the cells of the table view. Now I am calling some REST API to get an image which I want to add in this view above the cells. The problem now is that I dont know the height of the image, so I have to calculate it based on the aspect ratio which already works fine. When I add the image I can change its height correctly and move down labels and buttons BUT the image overlaps some of the visible cells.
My question: How can I move down the frame of the container? of the cells? dynamically based on my image respective View height?
I have tried to set the height of the View in the TableView but it has no effect. So I suppose that I have to set the y start position of the cells but I dont know how.
Do I need to set an y offset in the delegate method -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath ?
Any ideas?
I think the key to this is setting your view to be the table view's tableHeaderView after you change the size of the view. I did it like this in a test app,
-(void)layoutHeader {
self.label.text = #"This is a long text to see if it expands to take up multple lines. The quick red fox jumped over the lazy brown dog.";
[self.label setPreferredMaxLayoutWidth:self.tableView.frame.size.width];
CGRect stringRect = [self.label.text boundingRectWithSize:CGSizeMake(self.tableView.bounds.size.width - 40,CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:self.label.font} context:nil];
CGRect headerFrame = self.header.frame;
headerFrame.size.height = stringRect.size.height + 40;
self.header.frame = headerFrame;
[self.tableView beginUpdates];
self.tableView.tableHeaderView = self.header;
[self.tableView endUpdates];
}
I called this with a delay from viewDidLoad as a test. The beginUpdates, endUpdates code isn't necessary if you don't want to see the rows move down to accommodate the new view size. The property, header, is an IBOutlet to the view I added to the top of the table view in IB, and "label" is a subview of that view.
I would personally just use tableView:viewForHeaderInSection: to build the view out, and in tableView:heightForHeaderInSection: calculate the new height and return that. That way you don't have to worry about bumping things down within the tableView since UITableView will handle the rest for you once you. Just make sure to call [_tableView reloadData]; on your tableView after you get the image.
This question should not be mixed up with this here.. These are two different things.
There is a good example how to use a UITableView Header on SO.
This all works fine and the main header is fixed on top as long as the style is set to plain.
But if I use sections, the main header no longer sticks to top and moves away while scrolling to the bottom.
In this method, I am returning the header for each section.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
In this method I am setting the height for the header section above:
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
In this method, I am setting the real table header.
- (void)viewWillAppear:(BOOL)animated {
...
self.recordTableView.tableHeaderView = headerView;
}
Is it even possible having a fixed table header, while using sections?
What is an alternative solution to this please?
If you want a UITableViewController (static cells/keyboard handling) and have a fixed header then you should use Containment. You can do this from a Storyboard by setting up a UIViewController with your fixed header and then using a Container View to embed the UITableViewController.
Once you have your containing view setup, you right-click drag from the Container View to the View Controller you want to embed - the UITableViewController in this case.
You can access and get a reference to the contained View Controller (the UITableViewController) from the Container View Controller by implementing the prepareForSegue:sender: method.
There’s no way to maintain the header of a tableView fixed, but
an useful approach when you need a unique header, is to use a UIViewController rather than a UITableViewController, and set the header (UIView) out from the tableView.
Something like this:
If you want to keep the class as a UITableViewController you can add your header as a subview to the tableview's superview. You will have to also push the tableview top inset down so your headerview doesnt hide the table.
Here is a sample code to put inside your tableViewController subclass (This example assumes your tableview controller is inside a navigation controller, so it pushes the view to below the navigation bar):
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.automaticallyAdjustsScrollViewInsets = NO;
}
-(void)addHeaderView{
CGFloat yPosition = self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height;
mainHeaderView = [[UIView alloc] init];
const CGFloat mainHeaderHeight = 44;
[mainHeaderView setFrame:CGRectMake(0, yPosition, self.view.frame.size.width, mainHeaderHeight)];
mainHeaderView.backgroundColor = [UIColor redColor];
[self.tableView.superview addSubview:mainHeaderView];
[self.tableView setContentInset:UIEdgeInsetsMake(yPosition + mainHeaderHeight, self.tableView.contentInset.left, self.tableView.contentInset.bottom, self.tableView.contentInset.right)];
}
I haven't done this, but the first thing I would think to try is to place my tableview in a UIView and make my own header there in that UIView. Seems a trivial matter to make that view appear to be the header of the table and it would certainly stay put.
I have a UITableView in the grouped style, and only one section. However there is some blank space above and below the table view that is shown when the user scrolls too far. How can I remove this blank space?
You can do this by altering the contentInset property that the table view inherits from UIScrollView.
self.tableView.contentInset = UIEdgeInsetsMake(-20, 0, -20, 0);
This will make the top and bottom touch the edge.
Add this code:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0;
}
Actually this question answered my question.
Reducing the space between sections of the UITableView.
UIView can be inserted at the top and bottom of the table(drag and drop). Set their properties as transparent and height of 1 px. This is to remove the extra padding in front of the cells.
you can also use this code for removing space between first cell of uitableview..
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.002f;// set this...
}
Uncheck Extend Edges Under Top bar.
This answer comes quite late, but I hope it helps someone.
The space is there because of the UITableView's tableHeaderView property. When the the tableHeaderView property is nil Apple defaults a view. So the way around this is to create an empty view with a height greater than 0. Setting this overrides the default view thereby removing the unwanted space.
This can be done in a Storyboard by dragging a view to the top of a tableView and then setting the height of the view to a value of 1 or greater.
Or it can be done programmatically with the following code:
Objective-C:
CGRect frame = CGRectZero;
frame.size.height = CGFLOAT_MIN;
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:frame]];
Swift:
var frame = CGRect.zero
frame.size.height = .leastNormalMagnitude
tableView.tableHeaderView = UIView(frame: frame)
Comments
As others have noted you can use this same solution for footers.
Sources and Acknowledgements
See the Documentation for more details on the tableHeaderView property.
Thanks to #liushuaikobe for verifying using the least positive normal number works.
My original answer: https://stackoverflow.com/a/22185534/2789144
In my case issue was with the constraints i was applying. I have to change them in order to show 2 rows in my case while bottom of table touching last row.
Use the bounces property of UIScrollView:
[yourTableView setBounces:NO];
This will remove what seems to be an extra padding at the top and bottom of your UITableView.
Actually, it will just disable the tableview's scrollview to scroll past the edge of the content.