i have a collection view, with cells in a size of the all screen.
i'm trying to add spacing between the cells, so when ever i scroll between the cells there will be some space between - as in the iOS photo gallery, when you scroll between full screen images.
obviously i have paging enabled.
but for some reason when i scroll between the cells, the spacing is staying on the screen.
i.e. if the cell width is 320, and the space between the next cell is 20px, so when i scroll to the next cell, the space is reaching to x=0, and the new cell starts at x=20.
why is that?
how do i get the exact iOS photo gallery scrolling full screen images effect?
increase the width of the collection to the space value and shift collection left to the half space value. then change right and left section insets to the half space value
or you can make your own paging that will works even if cell size are less then collection view:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
CGPoint contentOffset = scrollView.contentOffset;
CGSize size = scrollView.frame.size;
CGPoint locationInView = CGPointMake(contentOffset.x + size.width/2, contentOffset.y + size.height/2);
if (scrollView == _collectionView) {
NSIndexPath *indexPath = [_collectionView indexPathForItemAtPoint:locationInView];
[_collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
[self collectionView:_collectionView didSelectItemAtIndexPath:indexPath];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
[self scrollViewDidEndDecelerating:scrollView];
}
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
}
Related
I have a UITextView in a UITableViewCell. They both dynamically size itself to fit. The problem I have is that when the texview reaches below the bottom of the screen (from making new lines), the tableView does not scroll to its location.
I tried this code, but it didn't work.
- (void)textViewDidChangeSelection:(UITextView *)textView {
[textView scrollRangeToVisible:textView.selectedRange];
}
You can find the cell containing the textView and tell the table view to scroll to that cell:
UIView *parentView = textView.superview;
while(![parentView isKindOfClass:[UITableViewCell class]]) {
parentView = parentView.superview;
}
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell*)parentView];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
You should add code below to scroll the tableView too:
- (void)textViewDidChangeSelection:(UITextView *)textView {
[textView scrollRangeToVisible:textView.selectedRange];
// since you are only scrolling the table a little bit and not by a whole cell, then change the scrollView.offset
CGPoint offset = tableView.contentOffset;
offset.x += 20; // an example. You need to change this based on the new size of the textview.
tableView.contentOffset = offset;
}
I'm trying to modify a UICollectionView using a UICollectionViewFlowLayout to support some parallax effects when scrolling. I am able to do this on the UICollectionViewCells by implementing something like:
- (void)scrollViewDidScroll:(UIScrollView *)mainScrollView
{
CGPoint offset = [mainScrollView contentOffset];
for (UIView *cell in [self.mainCollectionView visibleCells])
if ([cell conformsToProtocol:#protocol(KSParallaxCell)])
[((UIView <GSParallaxCell> *)cell) parallaxInScrollView:mainScrollView toX:offset.x toY:offset.y];
}
Is it possible to iterate over the supplementary views (UICollectionElementKindSectionHeader and UICollectionElementKindSectionFooter) to check if they support the same parallax delegate?
Forgot to check obvious of looping through subviews instead of calling the visible cells:
- (void)scrollViewDidScroll:(UIScrollView *)mainScrollView
{
CGPoint offset = [mainScrollView contentOffset];
for (UIView *cell in self.mainCollectionView.subviews)
if ([cell conformsToProtocol:#protocol(KSParallaxCell)])
[((UIView <GSParallaxCell> *)cell) parallaxInScrollView:mainScrollView toX:offset.x toY:offset.y];
}
hi iam developing a social networking application using UICollectionview horizontal layout, when ever my app launches collection view loads up to 5 cells then if i swipe 5th cell then that time only 6th cell memory will allocates. same way swipe 6th cell to 7 th cell like that.So,how can i implement this process
thanks in advance for any advices
You need to add a swipe gesture recognizer to your collectionView:
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGesture:)];
swipeGesture.direction = UISwipeGestureRecognizerDirectionUp;
[collectionView addGestureRecognizer:swipeGesture];
Then, handle the swipe in handleSwipeGesture: to allocate the cell.
-(void) handleSwipeGesture:(UISwipeGestureRecognizer *) sender
{
...
}
You can make the swipe direction whatever you want to use, this one is configure for up.
That's pretty much all there is to it. Main thing is you don't want the direction to conflict with the scrolling direction swipe, as I don't think there is a clean way to deal with that. When you are scrolling horizontally, that is a swipe, so you would need to use up/down swipe direction.
To attach to the cell instead (to capture gesture on an individual cell) I do it most times for simple collectionviews in the following method:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
...
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
[cell addGestureRecognizer:longPressGestureRecognizer];
...
}
(This is a long press, but it works the same way). In the case of putting it in the cell, you'll need to put a tag on the cell then reference that tag int the handler to figure out which cell it came from:
Here's one for the above:
- (void) handleLongPress: (UILongPressGestureRecognizer *) sender
{
if (sender.state != UIGestureRecognizerStateBegan)
return;
CGPoint p = [sender locationInView: collectionView];
NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:p];
if (indexPath != nil)
{
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell)
{
int indexOfItem = cell.tag;
NSLog(#"Selected item = %d", indexOfItem);
}
}
At least something along this line...
You can achieve this by implement the UIScrollViewDelegate method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollView.contentOffset;
CGRect bounds = scrollView.bounds;
CGSize size = scrollView.contentSize;
UIEdgeInsets inset = scrollView.contentInset;
float y = offset.x + bounds.size.width - inset.right;
float h = size.width;
float reload_distance = 75; //distance for which you want to load more
if(y > h + reload_distance) {
// write your code getting the more data
NSLog(#"load more rows");
}
}
in this when you go at the last cell of the collection then this scroll view delegate method will called.
and you may change the distance vale according to your requirement.
I need to have the possibility to put the selected line on the middle of frame. So if I select the first or the last row, this row needs to be on the center and not clipped to the top (or to the bottom) of the tableview (something like an UIPickerView).
This is my code on scrollViewWillEndDragging:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset {
CGFloat rowHeight = [delegate rowHeightForMyPickerView:self];
CGFloat floatVal = targetContentOffset->y / rowHeight;
NSInteger rounded = (NSInteger)(lround(floatVal));
targetContentOffset->y = rounded * rowHeight;
NSLog(#"Offset: %f Float: %f Row: %d",targetContentOffset->y,floatVal,rounded);
[delegate myPickerView:self isOverRow:rounded];
}
With this code, I create snap effect but rounded is not the correct row. Changing the first and last cell height with a double height makes the problem disappear but I don't like that solution.
The UITableView class can scroll to the selected indexPath, with animations as well, using scrollToRowAtIndexPath:atScrollPosition:animated method. Preferably in the tableView:didSelectRowAtIndexPath:indexPath method, add:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; //scrolls the selected cell to middle
}
I currently have a collection view with a grid of images on it, when selecting an image this segues to another collection view with a full screen image on it.
To do this I am using:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"collectionView"])
{
QuartzDetailViewController *destViewController = (QuartzDetailViewController *)segue.destinationViewController;
NSIndexPath *indexPath = [[self.collectionView indexPathsForSelectedItems] objectAtIndex:0];
destViewController.startingIndexPath = indexPath;
[destViewController.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
[self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
}
}
and then in my detail view:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (_startingIndexPath) {
NSInteger currentIndex = floor((scrollView.contentOffset.x - scrollView.bounds.size.width / 2) / scrollView.bounds.size.width) + 1;
if (currentIndex < [self.quartzImages count]) {
self.title = self.quartzImages[currentIndex][#"name"];
}
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
layout.itemSize = self.view.bounds.size;
[self.collectionView scrollToItemAtIndexPath:self.startingIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
when I rotate to landscape the image disappears and the title at the top changes, if I go back to the grid and then select a cell again it will segue again to the detail view but the title is for a different cell and the image shows half and half between two different images.
I am getting the following message as well on the log when I rotate the device:
2013-06-04 17:39:53.869 PhotoApp[6866:907] the behavior of the UICollectionViewFlowLayout is not defined because:
2013-06-04 17:39:53.877 PhotoApp[6866:907] the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.
How can I correct this so it will support orientation.
Thanks
You need to invalidate collection view's layout since sizes of cells in portrait orientation are too big for landscape orientation.
Writing something like this in your parent UIViewController should fix your issue:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self.collectionView.collectionViewLayout invalidateLayout];
}