Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View with continuous scroll; both horizontal and vertical

I have been struggling with this assignment for quite some time now. What I would like to develop is a scrollview or collectionview which scrolls continuously both vertical and horizontal.

Here is an image of how I think this should look like. The transparent boxes are the views/cells which are re-loaded from the memory. As soon as a view/cell gets outside of the screen, it should be reused for upcoming new cell.. just like how a UITableViewController works.

Continuous scroll

I know that a UICollectionView can only be made to infinite scroll horizontal OR vertical, not both. However, I don't know how to do this using a UIScrollView. I tried the code attached to an answer on this question and I can get it to re-create views (e.g. % 20) but that's not really what I need.. besides, its not continuous.

I know it is possible, because the HBO Go app does this.. I want exactly the same functionality.

My Question: How can I achieve my goal? Are there any guides/tutorials that can show me how? I can't find any.

like image 844
Paul Peelen Avatar asked Mar 21 '13 13:03

Paul Peelen


People also ask

What is horizontal and vertical scrolling?

A horizontal scroll bar enables the user to scroll the content of a window to the left or right. A vertical scroll bar enables the user to scroll the content up or down.

What is endless scrolling called?

Infinite scroll is a user experience (UX) practice in which content continually loads when a user reaches the bottom of the page. This creates the experience of an endless flow of information on a single, seemingly never-ending page.

What is continuous scroll?

Announced in October 2021, continuous scroll replaced Google's traditional, paginated search results pages for mobile users. Instead of presenting users with a list of pages at the bottom of the first results page, Google now loads the next page of results automatically. Continuous scroll in the mobile search results.

What is horizontal scrolling?

What is horizontal scrolling? Horizontal scrolling is a page navigation method in which the user scrolls left and right to reveal content from the sides of the window or container.


1 Answers

You can get infinite scrolling, by using the technique of re-centering the UIScrollView after you get a certain distance away from the center. First, you need to make the contentSize big enough that you can scroll a bit, so I return 4 times the number of items in my sections and 4 times the number of sections, and use the mod operator in the cellForItemAtIndexPath method to get the right index into my array. You then have to override layoutSubviews in a subclass of UICollectionView to do the re-centering (this is demonstrated in the WWDC 2011 video, "Advanced Scroll View Techniques"). Here is the controller class that has the collection view (set up in IB) as a subview:

#import "ViewController.h" #import "MultpleLineLayout.h" #import "DataCell.h"  @interface ViewController () @property (weak,nonatomic) IBOutlet UICollectionView *collectionView; @property (strong,nonatomic) NSArray *theData; @end  @implementation ViewController  - (void)viewDidLoad {     self.theData = @[@[@"1",@"2",@"3",@"4",@"5"], @[@"6",@"7",@"8",@"9",@"10"],@[@"11",@"12",@"13",@"14",@"15"],@[@"16",@"17",@"18",@"19",@"20"]];     MultpleLineLayout *layout = [[MultpleLineLayout alloc] init];     self.collectionView.collectionViewLayout = layout;     self.collectionView.showsHorizontalScrollIndicator = NO;     self.collectionView.showsVerticalScrollIndicator = NO;     layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;     self.view.backgroundColor = [UIColor blackColor];     [self.collectionView registerClass:[DataCell class] forCellWithReuseIdentifier:@"DataCell"];     [self.collectionView reloadData]; }   - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {     return 20; }  - (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {     return 16; }  - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView  cellForItemAtIndexPath:(NSIndexPath *)indexPath {      DataCell *cell = [collectionView  dequeueReusableCellWithReuseIdentifier:@"DataCell" forIndexPath:indexPath];     cell.label.text = self.theData[indexPath.section %4][indexPath.row %5];     return cell; }  - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {    // UICollectionViewCell *item = [collectionView cellForItemAtIndexPath:indexPath];     NSLog(@"%@",indexPath);  } 

Here is the UICollectionViewFlowLayout subclass:

#define space 5 #import "MultpleLineLayout.h"  @implementation MultpleLineLayout { // a subclass of UICollectionViewFlowLayout     NSInteger itemWidth;     NSInteger itemHeight; }  -(id)init {     if (self = [super init]) {         itemWidth = 60;         itemHeight = 60;     }     return self; }  -(CGSize)collectionViewContentSize {     NSInteger xSize = [self.collectionView numberOfItemsInSection:0] * (itemWidth + space); // "space" is for spacing between cells.     NSInteger ySize = [self.collectionView numberOfSections] * (itemHeight + space);     return CGSizeMake(xSize, ySize); }  - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path {     UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];     attributes.size = CGSizeMake(itemWidth,itemHeight);     int xValue = itemWidth/2 + path.row * (itemWidth + space);     int yValue = itemHeight + path.section * (itemHeight + space);     attributes.center = CGPointMake(xValue, yValue);     return attributes; }   -(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {     NSInteger minRow =  (rect.origin.x > 0)?  rect.origin.x/(itemWidth + space) : 0; // need to check because bounce gives negative values  for x.     NSInteger maxRow = rect.size.width/(itemWidth + space) + minRow;     NSMutableArray* attributes = [NSMutableArray array];     for(NSInteger i=0 ; i < self.collectionView.numberOfSections; i++) {         for (NSInteger j=minRow ; j < maxRow; j++) {             NSIndexPath* indexPath = [NSIndexPath indexPathForItem:j inSection:i];             [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];         }     }     return attributes; } 

And finally, here is the subclass of UICollectionView:

-(void)layoutSubviews {     [super layoutSubviews];     CGPoint currentOffset = self.contentOffset;     CGFloat contentWidth = self.contentSize.width;     CGFloat contentHeight = self.contentSize.height;     CGFloat centerOffsetX = (contentWidth - self.bounds.size.width)/ 2.0;     CGFloat centerOffsetY = (contentHeight - self.bounds.size.height)/ 2.0;     CGFloat distanceFromCenterX = fabsf(currentOffset.x - centerOffsetX);     CGFloat distanceFromCenterY = fabsf(currentOffset.y - centerOffsetY);      if (distanceFromCenterX > contentWidth/4.0) { // this number of 4.0 is arbitrary         self.contentOffset = CGPointMake(centerOffsetX, currentOffset.y);     }     if (distanceFromCenterY > contentHeight/4.0) {         self.contentOffset = CGPointMake(currentOffset.x, centerOffsetY);     } } 
like image 132
rdelmar Avatar answered Oct 04 '22 07:10

rdelmar