UITableView inside UIScrollView, scroll not working - ios

I'm trying to implement the following hierarchy
-- UISCrollView
-- ContainerView
-- UITableView
Initially the UITableView scroll is disabled. When the UICollectionView reaches a particular contentOffset of the UIScrollView, I implement this :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y >= 140)
{
[scrollView setContentOffset:CGPointMake(0, 140) animated:NO];
}
}
All this works as intended, but now the UIScrollView is eating the scroll of the UITableView. The scroll of UITableView is erratic now and doesn't scroll properly. The scroll of UITableView happens only after 7-8 attempts and then it stops again.
What might be the reason of this behaviour? I tried setting myScrollView.scrollEnabled = NO inside scrollViewDidScroll and no luck.

You can delay the main scroll view's touch response, then the sub tableview (scrollview) can be scrolled correctly:
myScrollView.panGestureRecognizer.delaysTouchesBegan = YES;

Related

Pass UITableView scrolling gesture to superview UITableView

I have a SuperUITableView as the main superview; inside that superview, I have another UITableView called SubUITableView.
I want to pass the scrolling gesture from the subview (SubUITableView) to the superview (SuperUITableView)
If the question is not clear, kindly ask me anything in the comments instead of downvoting.
UITableViews will confirms to scrollViewDidScroll delegate.
Inside the delegate of inner tableView, you just programmically scroll super tableView.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
UIScrollView *parentScrollView = (scrollView == self.tableView1) ? self.tableView2 : self.tableView1;
[otherScrollView setContentOffset:[scrollView contentOffset] animated:NO];
}

Forward vertical scrolls from UIScrollView to a sibling UITableView

I have a view controller with this hierarchy:
View Controller:
UIScrollView (scrollable horizontally)
UITableView (scrollable vertically)
I want to forward the vertical scrolls from my UIScrollView to the sibling UITableView, so that when the user scrolls up on the UIScrollView, the UITableView will scroll up instead. What would be the best way to do it?
I have tried these:
Detecting the vertical scroll in scrollViewDidScroll, it doesn't get called because the contentOffset of the scroll view does not change.
Subclassing the UIScrollView and overriding touchesMoved, I can't forward the touches to the table view because I don't have a reference to it in this class.
If the tableview is contained within the scroll view I believe you can set up the scroll view's gesture recognizers to respond only if the table view's gesture recognizers fail. I haven't had a chance to try this, but you should be able to set up a dependency between the gestures for each of the views.
UITableView* tableView = ...;
UIScrollView* scrollView = ...;
for (UIGestureRecognizer* r in scrollView.gestureRecognizers)
{
for (UIGestureRecognizer* tableRecognizer in tableView.gestureRecognizers)
{
[r requireGestureRecognizerToFail:tableRecognizer];
}
}
This will make your scroll simultaneously with UITableView and UIScrollView and apply #Stephen Johnson's block
- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer
{
return YES;
}

Lock handling of scroll event in UIScrollView subview (inside a UIScrollView superview)

I have a complex view hierarchy:
UIScrollView
- UITableView
- UICollectionView
The UICollectionView and UIScrollView both scroll horizontally. Now, I want to capture the swipe gesture exclusively on UICollectionView so that the superview (UIScrollView) ignores it.
User can swipe left to get to the end of UICollectionView. When at the end, the swipe gesture on UICollectionView is ignored and captured by the superview (UIScrollView) and the interface changes. How can I prevent that from happening?
Note: I'm using the default swipe functionality provided by both UIScrollView and UICollectionView i.e. I'm not adding any custom swipe gesture handling.
In your ViewController.m
-(void)viewDidLoad
{
scrollView.delegate = self;
collectionView.delegate = self;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if (the scrollView didn't reached the end){
then collectionView can't scroll
}else{
collectionView can scroll
}
}
You can check to see if the scrollView reached the end with the contentOffset property
Don't forget to declare that you are using the delegate of scrollView
Hope that helps

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

ScrollviewDidScroll not called at each point

There is a button at the bottom of my view controller. When the user scrolls down the button has to be attached to the scrollview at certain height.
I need to attach a button to the scrollview, immediately when the contentOffset.y reaches a particular value. -(void) scrollviewDidScroll doesn't help me as there might be a jump in contentOffset when the user is scrolling fast. Any leads on this are helpful.
Also, whenever I add a subview to the scrollview, -(void) viewDidLayoutSubviews is called. Which in turn sets the contentOffset to {0,0}. How can I achieve the functionality I need?
I needed to do the same thing with a UITableView and for me using scrollViewDidScroll worked.
I created a view called staticBar and added it as a subview of the tableView, but I had to rearrange the tableview subviews for it to appear in the right place. I don't have my code in front of me, but in -scrollViewDidScroll: it looked something like this:
- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
CGFloat staticBarAdjustedY = _staticBarY - scrollView.contentOffset.y;
CGFloat scrollViewYFloor = scrollView.frame.size.height - _staticBar.frame.size.height;
// This way maximum Y the view can have is at the base of the scrollView
CGFloat newY = MIN( staticBarAdjustedY, scrollViewYFloor);
_staticBar.frame = (CGRect){ { _staticBar.frame.origin.x, newY}, _staticBar.frame.size}
}
I will check my code later today and add more details here.
Also, you said the scrollviewDidScroll has jumps in contentOffset, but it's worth mentioning that these jumps are the same that the scrollView uses to scroll its own view. So it's not like you are "losing" frames on this delegate method.
Hope it helps.
PS: So, here is the rest of my code.
//I place my custom view as a subview of the tableView below it's last subview
//The last subview is for scroll indicators.
WTButtonsBar *buttonBar = [[WTButtonsBar alloc] init];
[self.tableView insertSubview:buttonBar belowSubview:self.tableView.subviews.lastObject];
In scrollViewDidScroll:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//In my app I needed my view to stick to the top of the screen
//thats why I use MAX here
//self.buttonsBarOriginalY is the view's position in the scrollView when it isn't attached to the top.
CGFloat newY = MAX(scrollView.contentOffset.y, self.buttonsBarOriginalY)
[_buttonsBar setFrame:(CGRect){{0, newY}, _buttonsBar.frame.size}];
}

Resources