I'm having a problem understanding mechanism of setContentOffset, if my tableView has contentSize.height of 100 points and I set content offset to 200 points the table won't bounce to content like it would do if user manually scrolled tableView to 200 points. User has to tap tableView in order to bounce back to content.
Is there a way to mimic user scroll with setContentOffset?
Swift 4
You can try
tableView.scrollToRow(at: yourIndex, at: bottom/middle/none/top, animated: true/false)
Place this in ViewDidLoad in your TableViewController and the tableView will begin at your desired place. If you set animated to true then you will have your desired scroll effect.
As far as setContentOffset that is more to simply offset the tableView so that it is positioned more correctly, not meant to mimic a scrolling action
Related
I have a UITableView that represents playable rounds in a game. On first launch, only two cells are shown in the tableView. As the user beats levels, more and more rows are added to the tableView. I reloadData every time the tableView is displayed (which happens each time the user beats a level).
Once the tableView contains enough cells to require scrolling, the tableView will not scroll and where the user left it. It will scroll to reveal that the cells are down below, but when the user releases their finger, the tableView bounces back, not allowing the user to interact with those cells that require scrolling to see. After completing another level and returning back to the tableView, the view will scroll properly.
When the scrolling issue exists, it is as though the tableView does not realize that it is big enough to require scrolling, so it bounces back to its original position, despite the fact that there are cells that are displayed down below when the user attempts to scroll.
I do not implement the heightForRowAtIndexPath or heightForHeaderInSection methods in the tableView's delegate, so that should not be interfering. I have searched this site and Google for similar issues, and have tried a few things including setting the contentSize, but have been unsuccessful.
Is there any reason for this lack of scrolling? Or, more importantly, is there a way to fix it? Thanks!
EDIT:
I see some comments asking about the frame. I logged the frame of the view the table is in, the frame of the tableView itself, and the tableView's content size in the viewDidAppear method of the view the table i in.
Here are the results when the view appears the time before scrolling is necessary. Scrolling behavior is as expected; the user can scroll past the visible area, and it bounces back.
view.frame: {{0, 20}, {320, 460}}
tableView.frame: {{0, 145}, {320, 315}}
tableView.contentSize: {320, 308}
Here are the results when the view appears when scrolling should be necessary. Scrolling will allow the cells below to appear, but when the user releases their finger, it bounces back when it should not.
view.frame: {{0, 20}, {320, 460}}
tableView.frame: {{0, 145}, {320, 315}}
tableView.contentSize: {320, 352}
Note that the contentSize.height did change by 44, as it should have after a new cell was added. The contentSize.height is now larger than tableView.frame.height, but the scrolling behavior does not reflect this.
The protocol UITableViewDelegate conforms to UIScrollViewDelegate, so all you need to do is to implement the methods -scrollViewWillBeginDragging and -scrollViewDidScroll directly in your UITableViewDelegate implementation and they will be called automatically if the implementation class is set as delegate to your UITableView.
So in those methods you can implement logic related to showing content of your tableView. Like suppose you said while scrolling it should show new cell i.e the top most cell must hide at that time. You could write logic in above method as,
//set your content of tableview to show new cell each time.
OR for scroll direction , you have method - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView,
// you can set here start and end coordinates and change them accordingly when scroll decelerates.
Writing your code in such way will not make the scroll bounce back. And you will get perfect results.
Hope this helps.
self.tableview.scrollEnable=YES;//Paste this line where initialized UITableView.
I have a mockup that looks like this:
This is all one big Table Controller that you can scroll.
When the section header hits the top of the page it freezes along the top, like so:
Which is working fine. However, when you go back to the top and do a pull to refresh, I want it to do this:
So the pull to refresh dialog appears between the top table header cell and the section header (that is no longer frozen).
Is this possible? I haven't found an implementation like this in my searches.
You can do the following to achieve this,
Add a UIScrollView as the subview of UIViewController's view.
Add a UIView and UITableView as the subview of this scroll view
UIView inside scroll view represents table header cell.
Section header can be the header of UITableview and table contents represents the UITableView's cells.
Add UIRefreshControl as subview of UITableView and set its target method.
Implement the scrollview delegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView for both UITableview and UIScrollview.
When you are scrolling the tableview, move the parent scrollview whenever the table view header moves in the upward direction till the header reaches the top. Add an if condition in scrollview delegate to check for this.
When the table view is moved the downward direction, move the parent scrollview until the UIView table cell header is visible after this stop scrolling of UIScrollview and allow table view to scroll. This will enable the UIRefreshControl.
Here the key thing is the - (void)scrollViewDidScroll:(UIScrollView *)scrollView method and how you implement the scrolling. You can add a check for contentOffset to determine how much tableview and scrollview has been scrolled. In order to restrict the scrolling you can manually set this value in this delegate method to a particular value and it wont scroll after that.
I have 2 table view, with the same number of cells.
Could you please point me the correct way, that I could implement simultaneous scrolling. I mean, when I scroll through one table, the other one is scrolling the same time. Thanks.
As uitable view is derived from uiscrollview you can get the scroll amounts in the delegate method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
You can get content offset of the scrollview which is being scrolled and assign that to the other tableview.
In this method you should be able to access both tableviews.
The property you need to check is contentOffset.
firsttableview.contentOffset = scrollview.contentOffset
Harrr pirates!
I'm trying to make a data entry screen using a UITableViewController. It contains a grouped table view with two sections, each with a few (2 and 4) rows with a UITextField inside them.
When any of the UITextFields become first responder they scroll into view automatically. Great, you would say, but I want to scroll the whole section into view, not just the row containing the UITextField that became first responder.
I don't allow the user to scroll the UITableView by hand and I know to what position it should scroll to display correctly. However, I can't get my UITableViewController to stop automatically scrolling the UITextField into view for me.
Searching StackOverflow I can find a lot of questions about how to resize the UITableView when the keyboard appears, but this doesn't stop the automatic scrolling.
Any suggestions? Your help would be much appreciated!
TableView is basically an extension of scrollView therefore if you want to do the scroll yourself you should use the scrollview API.
Set the contectSize property to the size of the screen without the keyboard and the contentOffset to the location on the table you want to scroll to
The "too long; didn't read" version: Is there any way to disable the automatic scrolling behaviour of UIScrollView when telling a UITextField to becomeFirstResponder?
I have a scroll view with paging enabled and several views as subviews, each subview being controlled by its own view controller. Each subview has a UITextField.
The requirement is that when a page is scrolled into view, it's text field should become first responder.
This is fine when using finger swipes to scroll -- I use the scroll view delegate method scrollViewDidEndDecelerating: to know when scrolling stops and a page is in view, I can tell the text field to become first responder.
However, when the scroll view is "autoscrolled", as in when telling the scrollview to scrollRectToVisible:animated:, the scroll view delegate method for deceleration isn't called. I use this method when scrolling newly created pages into view without the user's interation, or when the user taps the UIPageControl.
My solution was to simply set the first responder status of the text field before telling it to scroll into view - but it seems that telling a text field that is in a scroll view to become first responder causes the scroll view to automatically scroll it into view.
I assume this is behaviour used when putting text fields in table view cells (since table views are scroll view subclasses). If you set up a small test app, with a table view, and a text field within a table cell, if the keyboard would obscure the table view cell when it becomes first responder, the table view will automatically scroll it to be visible.
I don't understand, though, why this behaviour occurs in my example, where I'm not using a table view - just a plain scroll view.
I should also mention that my scroll view has vertical scrolling disabled and only scrolls horizontally.
I have tested in another test app that puts text fields as direct subviews of a scrollview (no view controllers or container views) and the same happens. If you tell a text field that is offscreen to become first responder, the scroll view with automatically scroll it for you.
This wouldn't normally be a problem, but it seems to screw up the paging of the scroll view. When I scroll with my finger, each view bounces and is centred properly. But when I scroll a rect to be visible with animation and tell a text field to become first responder, scroll view seems to become conflicted with itself and the view is only scrolled part of the way into view, and isn't centred.
Then, if I touch a view using my finger (not swipe, or even move), the scroll view jumps back to the first page.
My current work around for all this silly auto scrolling behaviour is to use an NSTimer to determine when to update the first responder.
I do the manual scrolling in code using scrollRectToVisible:animated and then after 0.3 seconds, call my method to update the text field to be first responder. (0.3 seconds was trial and error, trying to see which seemed to be the smallest amount of time to allow for the animation but still be long enough not to cause the conflict with the scrollview.
As you can see, this isn't elegant, and is likely to break.
Is there any way to disable the automatic scrolling behaviour of UIScrollView when telling a UITextField to becomeFirstResponder?
Call becomeFirstResponder, then right away, set the contentOffset of the scrollview to its current position..
[textField becomeFirstResponder];
[scrollview setContentOffset:scrollview.contentOffset animated:NO];
Not an answer to your question, but it should fix the problem:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
// Make the text field first responder...
}