UICollectionView if will scroll recognize - ios

I need some help.
I have UIcollectionView, I am using scrollToItemAtIndexPath:atScrollPosition:animated: Method. I need somehow to recognize if collection view will scroll to position or if item on needed position and will no scroll.
Another words, if scrolling will not start, scroll view delegate methods will not be called.
Thanks for help

How about checking if the indexPath you're interested in is in [UICollectionView indexPathsForVisibleItems]?
You can also use layoutAttributesForItemAtIndexPath to get the exact frame of the cell to determine if its partially shown.

You can use
CGRect cellFrame = [collectionView.visibleCells.lastObject frame];
CGRect collectionViewVisibleRect = collectionView.bounds;
collectionViewVisibleRect.origin.y = collectionView.contentOffset.y;
if (CGRectContainsRect(collectionViewVisibleRect, cellFrame))
//no scroll
else
//scroll
That does not takes into account contentInset that you might have.

Related

How to know if UICollectionView will actually scroll after scrollToItemAtIndexPath: is called?

I use scrollToItemAtIndexPath:atScrollPosition:animated to scroll UICollectionView. I have to disable some functionality while this automatic scrolling is happening and then re-enable it, when scrolling ends. The problem occurs, when I try to scroll to some cell which is already visible and there is no scroll necessary (for example, it's the last cell and collection view is already scrolled until the very end). In this case scrollViewDidEndDragging nor scrollViewDidEndDecelerating are called.
Is there a way to know if scrollToItemAtIndexPath will actually scroll UICollectionView?
I Think you can save the latest scroll view offset & track changes in it every time the scrollView scrolls & apply actions after significant changes only.
func scrollViewDidScroll(scrollView: UIScrollView) {
let scrollOffset = scrollView.contentOffset.y;
if scrollOffset < (previousValue-100) || scrollOffset > (previousValue+100)
{
// Scrolled up or down with 100 points which you can change
previousValue = scrollOffset
}
}
You can determine whether scrollToItemAtIndexPath will scroll based on the cell's frame before calling scrollToItemAtIndexPath. For example, if you just want the cell to be visible (UICollectionViewScrollPositionNone):
UICollectionViewLayoutAttributes* attrs = [collectionView layoutAttributesForItemAtIndexPath:indexPath];
CGRect frame = [collectionView convertRect:attrs.frame toView:self.view];
BOOL willScroll = !CGRectContainsRect(collectionView.frame, frame);
It's unfortunate that scrollToItemAtIndexPath doesn't simply tell you whether it will scroll.

Move TableViewCell down a little when the UIView is expanded

I want to move the tableViewCell down a little when the UIView is expanded.
I have some detail information initially hidden inside the view. Now if the users are interested in the detail information, they can click the button on the view to show the detail information, but the frame of detail intrudes onto the tableViewCells, so I want to change the location of tableViewCells to move it down a little to fit the view's frame.
Is possible to change the frame of the cell in the cellForRowAtIndexPath?
I have tried it, but I get an error.
The following picture says when I click the arrow image, it shows the detail information.
Thanks.
Note: My UIView is inside the UITableView, so changing the frame of UITableView doesn't work.
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x,self.detailView.frame.origin.y + self.detailView.frame.size.height,self.tableView.frame.size.width,self.tableView.size.height - x);//set value of x according to your need
I hope this would help.Thankyou
You should change contentInset of the UITableView:
youtableview.contentInset = UIEdgeInsetsMake(x, 0, 0, 0);
You should fix that x value to deal with your custom view height.
Good luck.
You could change the ContentOffset of the UITableView.
self.tableView.contentOffset = CGPointMake(0, self.tableView.contentOffset.y + 44);

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

UICollectionView scrollToItemAtIndexPath: and get fresh cell position

I would like to scroll collection view to some offscreen cell without animation and get position of that cell after scrolling. The problem is that collection view scrolls correctly (visually) but cell frame remains offscreen. Here is my code:
NSIndexPath *path = [fetchedResultsController indexPathForObject:objectInCollection];
[collectionView scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
[collectionView layoutSubviews]; // or 'layoutIfNeeded', doesn't matter
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:path];
cellFrame = [cell.superview convertRect:cell.frame toView:nil]; // still not refreshed
I can propose that collection view applies scrolling not immediately, so I would like to find approach to apply the scrolling.
--- UPDATE ---
The collection view is in previous view controller (so I scroll it from code and then pop visible view controller).
Cell frame remains offscreen even in viewDidAppear: method of previous view controller. To be exact, [cell.superview convertRect:cell.frame toView:nil]; returns frame without contentOffset of collection view. So CGRectOffset([cell.superview convertRect:cell.frame toView:nil], 0, -collectionView.contentOffset.y) returns correct cell frame on screen.
As i can understand from your problem statement, you want to set the some cell which is out of the view to visible state.
The cells are placed at the same position when the UICollectionView calculates
(void)prepareLayout
(void)layoutAttributes.. methods.
The frames of the collection cells are fixed till the invalidateLayout or reloaddata is called. Just you have to work around with the contentOffset of the collectionview.
Just get the frame of cell and set the contentOffset so the your frame of cell is visible on the screen. Hope it helps.
The cell frame should be correct and I don't think you need to use convertRect at all.
cellFrame = cell.frame;
However, you probably have to do this after the collection view loads. Call [collectionView reloadData] first.
There is also a layoutAttributesForItemAtIndexPath: method that has the attributes for that cell. You can call this on the indexPath and get the attributes that way.
Try changing scroll position to UICollectionViewScrollPositionBottom, this works for me -
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:NO];

slide all scrollViews from tableView when one is scrolling iOS

Is it possible to recognise gesture from scrollView so when one scrollView is dragged to simulate same dragging on another scrollView? For example I have tableView with custom cell that have scrollView in it, and I want to simulate dragging on every item in list.
EDIT
I succeeded to recognize movement of scrollView, but now I cant set other scrollViews from table to do same amount of scrolling.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
int position_x = scrollView.contentOffset.x;
int i=0;
int indexPath = [self.tableView indexPathForSelectedRow].row;
static NSString *hlCellID = #"EPGCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:hlCellID];
UIScrollView *scrollView = (UIScrollView *)[cell viewWithTag:16];
for(i=0; i<EPGList.count;i++){
if(i!=indexPath){
scrollView.contentOffset = CGPointMake(position_x, scrollView.frame.size.height);
}
}
}
Problem is that indexPath is not returning correct value when i am clicking on scrollView. It returns correct value only when I am clicking on cell space outside of scrollview.
Yes, yes it is possible. You need to have a delegate assigned to the scrollViews within the cells. Preferrably the same class that implements hour tableview data source and table view delegate protocols. You must implement UIScrollViewDelegate and the delegate must implement the scrollViewDidScroll: method.
Within that scrollViewDidScroll delegate method, you check the contentOffset property for its x and/or y values. Normally people go for the vertical scrolling value, but if you're implementing them in a UITableViewCell, you're probably doing horizontal scrolling.
The you use the value, I am assuming contentOffset.x, to update other scroll views within the other cells of your table! Make sense?
I have just posted an answer to another UIScrollView question yesterday. Please read what I wrote there, it might help you more.
Animation in UIScrollView iOS app

Resources