UITableView, make footer not bounce when table view scrolled till the end - ios

When I scroll to the bottom of my table view, the last element (intended to be a footer) bounces with the tableview object.
Is there a way I can make this last item / footer item, pin to the bottom of the screen when it is reached?

You can use below Method, in this way, when you go down in UITableView ,
at that time Stop or turn off bouncing all together?
e.g. .bounces=NO; .alwaysBounceVertical=NO
otherwise Set Yes To all.
this way may be helpful to you.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(#"scrollView.contentOffset.y-%f",scrollView.contentOffset.y);
NSLog(#"tblView.contentSize.height=%f",tblView.contentSize.height-tblView.frame.size.height);
if ([scrollView isKindOfClass:[UITableView class]])
{
if(scrollView.contentOffset.y == tblView.contentSize.height-tblView.frame.size.height)
{
// we are at the end
//Sp do wahtever want to do here.
//set bounce no
}
else
{
//not at END.
//set bounce Yes
}
}
}

Related

How to animate views according to tableview scrolling directions without content scrolling

i'm trying to implement a specific tableview behaviour (Like on Facebook app).
I want to have a dynamic header that will be magnified every time the user scrolls up and will be shrieked when the user scroll down.
In addition i want the tableview to cause the effect of pushing the header and than scrolling the tableview cells.
I used the method:
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
in this method i calculated the offset and the direction and called a method that shrink or magnify the header accordingly
so far so good.
The thing is that the animation is being performed with the tableview scrolling.
To avoid it, I created a custom scrollview on to of the top of my tableview, I taged the two scrollviews differently.
In the scrollview i created a weak reference of the tableview and a boolean value that indicated if the scrollview should return the tableview touch.
When the shrinking\magnifying animation was finished i changed the boolean value so it will signal the custom scrollview to return the tableview in my HitTest methods that i implemented inside the scrollview.
But hitTest not called when the user keep scrolling (without leafing the finger), in additions now my buttons inside my tableViewCell aren't reacting.
Here is my HitTest Method:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if (_recieveTouchOnTable)
{
return _table;
}
else
return result;
}
Here is my scrollViewDidScroll method:
(onProgress means that the animation is being performed, so keep returning the custom scrollview)
Tag = 2 = the custom scrollview
Tag = 1 = the tableview
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
CGFloat yVelocity = [aScrollView.panGestureRecognizer velocityInView:aScrollView].y;
CGFloat offset = lastCustomScrollViewContentOffset.y-aScrollView.contentOffset.y;
lastCustomScrollViewContentOffset =aScrollView.contentOffset;
if (yVelocity<0)
offset = fabs(offset)*-1;
else if(yVelocity>0)
offset = fabs(offset);
if (offset!=0 && aScrollView.tag == 2)
[self layoutViewAccorrdingToTableviewScorlingVelocity:offset];
if (!onProgress ){
customScrollView.recieveTouchOnTable=YES;
}
}
Am i missing something, or maybe there's a more simple way to do it?

iOS UIScrollView scrolling detection

I'm developing kind of UITextView copy with customizations. For now I need to implement selection cursors (see screenshot of original UITextView below)
As I discovered from Debug View Hierarchy Apple developers draw these dots on separate Window to avoid clipping, and when UIScrollView starts dragging they move these dots inside UITextView, when it stops dragging they move it back to separate window. The only problem with this approach is how can I detect when some of my TextView superview's are UIScrollView and they start/end scrolling? Setting delegate for each of UIScrollView-type superviews looks bad and will bring a lot of headache, cause I will need to manage several delegates if needed (and even detect there change). Any ideas?
/*
In your viewDidLoad or where ever you create the UITextView call this :[self checkParentViewOfTextView:textField];
*/
-(void)checkParentViewOfTextView:(UITextView*)txv {
if ([txv.superview isKindOfClass:[UIScrollView class]]) { // Check if the superview if UIScrollView
UIScrollView *superScroll =(UIScrollView*) txv.superview;
superScroll.delegate = self;// In order to call the delegate methods below
superScroll.tag = 5; // Set a tag to access the current scrollView at these delegate methods
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//Any scrollView did begin scrolling
if (scrollView.tag == 5) {
//Actions for your scrollView
}
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
//Any scrollView did end scrolling
if (scrollView.tag == 5) {
//Actions for your scrollView
}
}
You can use the same scroll view delegate for all UIScrollViews.
scrollView1.delegate = self
scrollView2.delegate = self
etc...
Just implement the delegate methods and take different action if necessary for each scroll view. Either do this by referencing properties in the class or setting the tag.
func scrollViewDidScroll(scrollView: UIScrollView!) {
if scrollView.tag == 0 {
// Do stuff
} else {
// Do other stuff
}
}

UITableView viewForFooterInSection only shows after scrolling

I've got a UITableView with one section and enough rows that the tableView needs to be scrolled to get to the bottom. I want to add a footer view which will stick to the bottom of the tableView and always be visible, so I have implemented viewForFooterInSection. Here's my code:
- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
NSLog(#"Get footer view");
if (tableView == [self tableView]) {
return [self footerRowRightView];
}
else if (tableView == [self fixedColumnTableView]) {
return [self footerRowLeftView];
}
return nil;
}
The problem I am having is that the footer view only shows after the tableView has been scrolled, but I want it to be visible from the outset (i.e. always floating whether the user scrolls or not).
As soon as the controller appears and the tableView loads its data, I see "Get footer view" in the log, so I know that viewForFooterInSection is being called straight away. What I can't work out is why it doesn't display immediately, and how to get it to do so.
Thanks in advance for any help!
It is probably your height for the footer not being returned correctly.
Check what you return from heightForFooterInSection
What you need is not a tableview's footer.
Simply add the view corresponding to this header in the superview of your tableview and put it at the bottom of it. Then simply reduce the height of the frame of your tableview to fit the remaining space. And it should do it !
You can no use footer view if you want to stick the footer. Or try with grouped tableview.
Quite a few options by the looks of the other answers. Just to add a hacky workaround I have just come up with, I created duplicates of the views I will be using as footers and added them as subviews of my main view, placed exactly over the position of where the real footer views. The views are retained in properties, so that in scrollviewDidScroll I can do the following:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if ([self preScrollFooterLeftView]) {
[[self preScrollFooterLeftView] removeFromSuperview];
}
if ([self preScrollFooterRightView]) {
[[self preScrollFooterRightView] removeFromSuperview];
}
}
This way the footer appears to be displayed immediately. The fake footer is removed as soon as the user scrolls the tableView, revealing the real footer beneath it. If the tableView is scrolled below the last row, the real header sticks to the bottom of the section and bounces back to the bottom of the tableView when the user lets go.

scrollViewDidScroll getting called for uiscrollview inside tablecell while scrolling tableview up and down

I have a custom uiscrollview inside each table cell. It works great except one condition. When you scroll the scrollview and it do autoscroll/decelerate. At same time if you scroll table view quickly up and down it also moves the scrollview in the table cell which will result in scrollViewDidScroll getting called for scrollview and messed up with my logic.
You need to check which UIScrollView is actually scrolling:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == yourScrollView)
{
// Do something
}
else
{
// Do something amazing
}
}

Making two UIScrollView's scroll as one, or transferring inertia between scroll views

In our app you can build a question by searching for options from multiple third party sources. Most of these search results are displayed as full-width tableview cells, as their data suits that format (has a bunch of metadata text I can display next to the thumbnail).
In the case of images however, a collection view makes much more sense. But now I run into the problem of a vertical scrolling tableview containing a vertical scrolling collection view.
http://www.screencast.com/t/7Z48zkkW
I can make it work somewhat by capturing the viewDidScroll on the collection view and updating the parent scroll view instead at the appropriate offsets, but it only works well when the user is actively dragging the collection view.
self.collectionVC.scrollViewDidScroll = ^(UIScrollView *scrollView) {
#strongify(self);
if (self.tableView.contentOffset.y < self.scrollingHeightOffset && scrollView.contentOffset.y > 0) {
CGFloat maxheight = MIN(self.scrollingHeightOffset, self.tableView.contentOffset.y + scrollView.contentOffset.y);
self.tableView.contentOffset = CGPointMake(0, maxheight);
scrollView.contentOffset = CGPointMake(0, 0);
} else if (scrollView.contentOffset.y < 0 && self.tableView.contentOffset.y > -topGuide) {
CGFloat minheight = MAX(-topGuide, self.tableView.contentOffset.y + scrollView.contentOffset.y);
self.tableView.contentOffset = CGPointMake(0, minheight);
scrollView.contentOffset = CGPointMake(0, 0);
}
};
When 'flinging' the collection view, the scrolling stops abruptly, losing the inertia of the collection view. Touching the tableview to scroll has a different problem, as I'm not capturing that when it hits the end and scrolling the collection view instead.
Right now the collection view lives in a cell of the tableview, but it could also be a peer if necessary. I'm trying to determine the best way to make these two scrollviews appear as one.
As far as I know you did the right thing. viewDidScroll should be called several times even after user lift the finger and scroll view is returning to some position.
I use exact same approach to scroll couple scrollViews in sync when user is dragging one of them. Works perfectly.
You might want to check your calculation logic inside this method. See if it calls for all changes after user lift a finger, but you're positioning other scroll view in a wrong way.
I did this, let me know if it works for you
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView1.panGestureRecognizer addTarget:self action:#selector(didRecognizePanGesture:)];
[self.tableView2.panGestureRecognizer addTarget:self action:#selector(didRecognizePanGesture:)];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.selectedTableView == scrollView)
{
if (scrollView == self.tableView1)
{
self.tableView2.contentOffset = scrollView.contentOffset;
}
else if (scrollView == self.tableView2)
{
self.tableView1.contentOffset = scrollView.contentOffset;
}
}
}
- (void)didRecognizePanGesture:(UIPanGestureRecognizer*)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan)
{
if (self.selectedTableView != nil) //this is gonna make stop the previous scrollView
{
[self.selectedTableView setContentOffset:self.selectedTableView.contentOffset animated:NO];
}
self.selectedTableView = (UITableView*)gesture.view;
}
}

Resources