Adding UISearchBar as tableHeaderView in xib not works - iphone

I added UISearchBar as tableHeaderView for UITableView in xib, by just dropping UISearchBar onto UITableView.
It is working fine, when the table has more than 6 rows.
But when there is less than 6 rows, it UITableView does not scroll.
At the same time, if i add the UISearchBar as tableHeaderView for UITableView programatically in .m file using the following statement, EVERYTHING WORKS FINE.
tableViewTemp.tableHeaderView = searchBarFriends;
Seems very strange to me,
What might be the problem?
Please advice, Thank you.

Here is a little trick I did ;) Don't make your SearchBar a subview of your UITableView. Just add instances of them both in your nib file and wire them up as IBOutlets in your UITableViewController. Then what you are going to do is set the SearchBar as the header view for your table, that way you don't have to worry about the frames overlapping and interfering with touch events. Here's how you do it:
Create the property in your TableView header file
#property ( nonatomic, retain ) IBOutlet UISearchBar *searchBar;
Set the header view for your table:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return self.searchBar; // The property you wired up in IB
}
Set the height for your header or (UISearchBar)
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 44; // The height of the search bar
}
That's all you need. Now this may not be the best solution if you have a grouped tableview or a table with multiple sections but its a clean solution for a simple table. Otherwise, you'd have to adjust the frame of the searchbar AND the tableview in code because they overlap and thats why you have touch issues. Hope this helps!

if you add search bar like below hierarchy it will work

I had almost the same problem (for me it wouldn't scroll at all with any number of rows, but it would as soon as I removed the search bar). Fixed it adding this in viewDidLoad:
self.tableView.alwaysBounceVertical = YES;

Related

Proper way to implement a footer in UITableView

So I read here that I can simply drag a UITableViewCell to the bottom of my UITableViewController in storyboard and have it act like a footer. This footer row has an activity indicator in it that's it. It's width is 320 and height 55 with the indicator centered in the row. Note that it's a UIView rather than a UITableViewCell because I can only get it to work with the former.
First, The UITableView doesn't stop at the footer. One can see the footer if he extends his scrolling beyond the bottom of the UITableView. As soon as the user releases his finger, the footer disappears from site as the UITableView returns its scrolling back to the last element. I am trying to do what Instagram is doing - if you scroll to the bottom you can see their custom activity indicator at the bottom and the UITable will remain its scrolling position at that indicator. How can I achieve this?
Second, I have some custom scrolling performed by certain user actions. Right now, I have the following code:
if (row + 1 < [self.tableView numberOfRowsInSection:0]) {
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:row+1 inSection:0]
atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
} else {
// TODO scroll a little down so the user can see the activityIndicator
}
How can I tell my tableView to scroll programmatically to the footer and have it stop there?
Third During the very beginning, my UITableView has to fetch things from my server before it can populate the tableView. Unfortunately i can't get the footer view to maximize the space of the UITableView so that the activityIndicator will appear in the center. Right now this is how it looks:
I think I have the structs set correctly:
I suspect that having a UIView within a UITableView might prevent the view from maximizing.
Summary
Any recommendations on the above issues? I apologize for the length of this question, but I feel that they are all related to the same problem mentioned above.
I finally figured it out.
With regards to #zing and #Lithu answers, that worked. However, returning a footerView from this method forces the footerView to "stick" to the bottom of the TableView. By this I mean that the footerview will always be shown (which is not something I want)
I finally used self.tableView.footerView = MyView. I disabled ALL the spring and struct settings on my UIView and it fits perfectly. (I've previously set it to maximize hoping to have it maximize when there is nothing in the table)
Regarding centering the activity indicator: I ended up setting the footer view to hidden if there's nothing in the UITableView (by checking in numberOfRows). I programmatically added the ActivityIndicator in the center if this occurs.
Thanks for all the answers!!
Did you try to do it in the proper delegate for UITableview Footer
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
Use This code to add any view in the footer.
e.g.
- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, self.tblView.frame.size.width, 49)];
return footerView;
}

UIView behind cells of a UITableView

I'm trying to insert a view behind the cells of a uitableview but I can't find a way to do it properly. Everytime I add a subview to self.view or self.tableview, it goes on the foreground, even if I use the method "sendSubviewToBack:" ...
Do someone have an idea on how to achieve it ?
PS : I don't want to use self.tableview.backgroundView because the view is fixed.
Thanks
I solved it by calling [self.view sendSubviewToBack:self.myBackgroundView] in tableView:willDisplayCell:forRowAtIndexPath:. This will put the view behind each cell.
What you experience is logical. The self.view of a UITableView is indeed the table view. If you insert a subview, it is inserted on top of the table view - and there is no way to send it to the back.
Solution 1
The most flexible solution is to switch to a UIViewConntroller and implement the table view behaviour yourself. You need to
insert your own table view as a #property. This is now a subview of self.view. You can do this in code or in IB.
declare and implement the <UITableViewDelegate> and <UITableViewDatasource> protocols
set the delegate and datasource properties of the table view to self
insert any other subviews at will and shuffle them around as you wish.
Solution 2
If you just want to display something behind the tableView you might be able to use the table view property backgroundView. This will display behind the cells, but you will have limited control over the view's size (which you could again solve with further subviews of the background view). Also, you need to make sure your cells are transparent.
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index
with index 0 will take the View to position which is the back-most one.
This is a method on UIView.
Since UITableView Inherits from UIScrollView : UIView : UIResponder : NSObject. I guess this would help.

How to add a UIView above a UITableView in iOS?

I am using the xcode template to create a UITableView application with UINavigationController.
I need to add a UIView (at fixed position) between the UINavigationBar and the UITableView. How to do that ?
Thanks.
You can do this by setting the UITableView's tableHeaderView property.
UITableView class reference
tableHeaderView
Returns an accessory view that is displayed above the table.
#property(nonatomic, retain) UIView *tableHeaderView
Discussion The default value is nil. The table header view is
different from a section header.
Availability Available in iOS 2.0 and later.
Add UIView and UITableView as subviews of UIView and then position their height, width and x, y position from the Size Inspector in Interface builder or Use CGRectMake in objective-c
you need to implement following UITableview delegate methods
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
Step 1)
Create a header view as, set outlet to that view.
#property(nonatomic,strong)IBOutlet UIView *viewHeader;
Setp 2)
Add following single line code on viewDidLoad
[self.tableview setTableHeaderView:self.viewHeader];
Done!!!
Views are maintained in a hierarchy in iOS. They are maintained essentially as an array with the latest view first. To insert some view below one view or above another you just need to manipulate this.
All this is theory, I have not done what you want. So dont hold a grudge against me ;) this is a friendly suggestion.
[self.view insertSubview:yourNewView belowSubview:navigationController];

Using rounded-rect button for TableView footer in iPhone?

I'm trying to put a button to footer of TableView.
This is what i did and I can't see the button but the string "RESULT" is displayed.
I've tried everything I can think of. but I couldn't figure out what's wrong. I need you help!
- (void)viewDidLoad {
btnSeeResult = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnSeeResult setTitle:#"RESULT" forState:UIControlStateNormal];
viewResult = [[UIView alloc] initWithFrame:btnSeeResult.frame];
[viewResult addSubview:btnSeeResult];
self.tableView.tableFooterView = btnSeeResult;
}
-(CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return viewResult.bounds.size.height;
}
Anyway, what's the difference between setting the footer view directly like
tableView.tableFooterView = footerView;
and using (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section method??
There's no reason for the viewResult wrapper. A UIButton is a UIView, so there's no reason to wrap it in another UIView in this case - especially since you then assign the button to the table's footer property which means the table should be taking control of how and when the button view ultimately displays.
You may have to set the btnSeeResult's frame so that it has a height set. It's possible the height is 0 by default in that case since you don't ever set a frame for it. You might also try something like [btnSeeResult sizeToFit]; after you set the title which should resize it enough to make room for the label text, at least.
As to your second question, the difference between tableFooterView and -(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section is that the former defines a view to attach to the bottom of the entire table, whereas the delegate method allows you to give each sub-section in your table different footers. Both can be used at the same time and in that case the last section's footer view would appear followed finally by the tableFooterView.
SeniorLee,
Welcome to StackOverflow!
You've got the right answer in your question - it's the latter code:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
When the table view goes to construct your table, it calls back to 2 classes - the table's delegate, and the table's data source.
Data Source is just what the name implies - the source of the data that is in your table. The Delegate, on the other hand, handles real-time interaction with the table and how it is to be displayed (e.g. what happens when the row is pressed?).
In many many cases, programmers set both the Data Source and the Delegate of the table view to the same class - the UITableViewController that owns the table view.
Anyhow, on to your question:
It's highly likely that the direct assignment isn't working explicitly because there is a delegate callback. When the table view goes to lay itself out, it will ask its delegate "do you have a view for the footer in section x?". That's the method above.
If you don't implement that method, the table view will have a default implementation that does something - in this case, probably set it to nil.
So, my guess is that even though you set this property directly in viewDidLoad, it's being overwritten to nil by the table view because you're not implementing the delegate callback. Instead, move your view code to the callback method and it should work beautifully.
Also, I don't think you need to wrap your UIButton in a UIView - UIButton is a subclass of UIView and thus should work just fine.

Relative Height of UITableview

In RootViewController am using a UITableView for displaying the content of data. In the didSelectRowAtIndexPath method, I am calling another view controller (DetailViewController) to display detailed data. For displaying this detailed data I am using a UITableview in the DetailViewController also. This table contains one section and only one row.
Now the problem is that I have to adjust the table's height dynamically when I move from RootViewController to DetailViewController. How can I make the height of the UITableView dynamic between the two classes?
Any help would be Appreciated!
You can implement the UITableViewDelegate method something like:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [TextToDisplay sizeWithFont:/*DESIRED_FONT*/ constrainedToSize:/*YOUR DESIRED_SIZE*/ lineBreakMode:/*DESIRED_LINEBREAKMODE*/].height;
}
to get variable heights.
It sounds like your trying to reuse a UITableView between two different UIViewControllers. I think your better off having the RootViewController have it's own UITableView which is set to a dynamic height and width using the UIView autoresizingMask property. Then when you select a row and push on the DetailViewController in a UINavigationController stack it would have it'd own UITableView to display the detail information your trying to show.
This interaction technique is used throughout other iPhone applications like Mail. If I misunderstood your question please let me know.