(iPhone/iOS) UISearchBar Scope Buttons cover first row of UITableView - iphone

I know this question has been asked before, but I have yet to find a true solution. I have a UITableView with a UISearchBar as its tableHeaderView. Whenever the scope buttons appear, they cover the first row of the UITableView.
I have tried using UITableView.contentOffset to offset the UITableView by the height of the scope buttons, and this works until the user taps the UITableView or scrolls it, at which point the UITableView jumps back to its original offset.
The best I've been able to do is set the UISearchBar as a separate item in the view, and simply resize the UITableView dynamically to show or hide it when the user taps a search button. The only problem is that there is no animation, so the transition is sharp.
UPDATE: I solved the problem by implementing a UISearchDisplayController, as this was the cleanest and easiest solution to work with. The UISearchDisplayController automatically shows/hides the scope buttons and moves the UITableView down accordingly. I didn't do this at first because I wanted the UITableView to remain visible rather than initially being blacked out by the UISearchDisplayController, however I've come to realize that the blackout does not hinder any functionality; the user would not have initiated a search if he wanted to continue looking at the UITableView the way it was.

Ideas:
Set the tableHeaderView to a UIView that has the UISearchBar as its subview, and resize that UIView when the scope buttons appear. The UITableView will hopefully respond to that view changing its frame.
Set the UISearchBar as the content of the first cell of the UITableView and use (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation when the scope buttons hide or show. Return the proper height to have the cell animate to its new height.
Or you could use the method you describe (UISearchBar as a separate item in the view), and use an animation block to animate the transition so it's less sharp.
[UIView animateWithDuration:1.0 animations:^
{
//change table view frame here
}];

If you adjust the cell height of the header based on if the search controller is active or not, all works well
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
var headerHeight: CGFloat = 0.0
if searchController.isActive
{
headerHeight = searchController.searchBar.frame.size.height
}
return headerHeight
}

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;
}

Implementing a dynamic height on UITableView

I have a UITableView embedded in a UIViewController. The TableViewCells are rows for the user to select something, so when they touch it a checkmark appears, heres where my question comes in:
I dont want the UITableView to scroll in its window, I want the TableView to grow with the items it contains. Do I need to put a scroll view on the UIViewController and then the TableView on that? Or will the ViewController scroll if the content is bigger than the View?
Also, Im not even sure where to start with changing the height dynamically of the UITableView, everywhere I look its about changing the cell heighets dynamically.
Please Help! Thank you!
self.tableView.scrollEnabled=false;
stops the scrolling
self.tableView.frame=CGRectMake(0, 0, (float)width, (float)height);
sets the size of your tableview
But I don't understand why you want to stop tableview scrolling and to scroll the whole view....

How to interact with a UITableView displayed overlapping another UITableView

I have one UITableView displaying some data, and when the user begins typing in a UITextField above the UITableView, another UITableView is displayed below the UITextField to show suggestions. This "suggestions" UITableView overlaps the UITableView below the UITextField. Tapping on one of the suggestions will populate the text box with the item tapped.
The suggestions UITableView displays in front of the other UITableView, but problem is that none of the taps to the suggestions UITableView register if they're outside the bounds of the view that contains it.
This is probably a really simple problem dealing more with UIViews in general, but I'm having trouble. Thanks for the help!
You have to adjust your second tableview which is giving you suggestions below testfield which will solve most of your issues
hope it helps you
you can show the second UITableView within another view that is displayed above the current view, like a popover, using
[self.view addSubview:secondView].
Once a selection is made, you can remove this view using
[secondView removeFromSuperview];

UITableViewCell subview (left side)

Is it possible to implement a subview of a UITableViewCell on the left side of the cell that crossfades when the table enters the editing mode?
Another problem I face is that the bounds of the cell.textLabel are read-only. Is it possible to use some sort of inset for that label? (Because I, like mentioned above, want to use a View on the left side)
Edit: How do I perform an action (in this case fade a subview) when the whole table enters editingmode? (Not through a swipe over a cell). The reason why I want to implement this is because the tableview shows the "-" button on the left side of the cells if it is in editingmode. (I want to show my own button on the left side of the cells if editing=NO, fade it out if editing=YES and show it again if the tableView leaves editingmode (editing=NO))
A first thought directs me to something like this:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
if(editing) {
//fade out my own button
} else {
//show my own button
}
}
But I would have to loop through all the cells and I think this leads to a substantial performance worsening. What do you think?
You want to set the Editing Accessory View of a UITableViewCell. See the editingAccessoryView property for information on this. More information can be found in the Customizing Cells section of the TableView Programming Guide.
The label within the content view of a table view cell is read-only so you can not reassign it but its properties are mutable. You can actually move the label around within the bounds of the table view cell. It's probably confusing to grasp, but have a look at the Characteristics of Cell Objects section of the Table View Programming Guide. In it, the bounding boxes for each of the nested views are shown (not all of them are always visible). For your purposes, a good exercise would be to set the background color of each subview of a UITableViewCell to a different color and then try to adjust the sizes of them. Doing so and understanding what's going on will probably let you achieve the end-result that you desire.
In the end I created a custom UILabel that I used instead of the default UITableView textLabel and added a custom button on the left side. In the setEditing method I fade this button in/out.

Determine whether UITableViewCell is editing from "swipe" or "self.editButton"

I'm trying to determine whether a UITableViewCell subclass is in edit mode from a user's swipe (in which case I don't need to indent my subviews) or from the user pressing the "Edit" button associated with the UITableViewController. (In which case I do.)
I know it's possible from a cell's perspective, since the self.textLabel view automatically indents properly. I have tried:
-(void)layoutSubviews {
[super layoutSubviews];
CGRect labelFrame = self.textLabel.frame;
labelFrame.origin.x += 5;
myCustomUILabel.frame = labelFrame;
}
But my custom label does not properly indent. (Though the self.textLabel view does?)
I would like to avoid the following:
Providing the cells with a reference to the parent table.
Overriding methods in the UITableViewController class to let the cells know whether they are being edited individually or the entire table is editing.
You can override willTransitionToState: in your UITableViewCell subclass. When the "Edit" button is pressed the state will be UITableViewCellStateShowingEditControlMask(=1) and when swiping it will be UITableViewCellStateShowingDeleteConfirmationMask(=2).
You should not be doing the indentation manually. The UITableViewCell will do it for you!
All you have to do is make sure that you add your subviews to 'contentView' of the UITableViewCell. This is the reason why self.textLabel indents properly as you have identified.
Look at the documentation of contentView property for a UITableViewCell:
The content view of a UITableViewCell object is the default superview for content displayed by the cell. If you want to customize cells by simply adding additional views, you should add them to the content view so they will be positioned appropriately as the cell transitions into and out of editing mode.