Giter Site home page Giter Site logo

njdehoog / nhbalancedflowlayout Goto Github PK

View Code? Open in Web Editor NEW
1.3K 1.3K 106.0 9.11 MB

UICollectionViewLayout subclass for displaying items of different sizes in a grid without wasting any visual space. Inspired by: http://www.crispymtn.com/stories/the-algorithm-for-a-perfectly-balanced-photo-gallery

License: MIT License

Ruby 2.00% Objective-C 98.00%

nhbalancedflowlayout's People

Contributors

almerlucke avatar jgraff avatar njdehoog avatar rvi avatar sneakyness avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nhbalancedflowlayout's Issues

Bug on reload

When scrolling up and down again this weird bug happens:
img_8684
img_8683

Crash of NHLinearPartition

while (k >= 0) {
        NSMutableArray *currentAnswer = [NSMutableArray array];
        for (NSInteger i = [solution[n-1][k] integerValue] + 1, range = n+1; i < range; i++) {

the last line crashes quite often for me, due to n being 0 and therefore accessing solution[-1]
I made a screenshot: https://www.dropbox.com/s/8o0cxgh5ez213es/Screenshot%202013-12-06%2009.06.06.png

Background:
I'm running through a loop to download new images. After every image download I add the new image to my array of images and call [self.collectionView reloadData] on the main thread.

I don't know much about the algorithm you're using, but adding a simple break in the while loop when i equals 0 does the job for me.

Performance on large camera roll

Running into memory issues and/or really slow performance on a large camera roll (10k items). Not really an issue per say, as I'm aware of the heavy computation going on, but I was wonder if you are seeing a significant performance improvement with the Swift rewrite?

Adding new items to the collection rearranges old cells

Hi there.
In my Photozeen iOS app I'm loading more images to the photo feed as user scrolls it down. Every time I have new portion of images from server I add them to the collection by calling insertItemsAtIndexPaths.
I see that items are getting rearranged every time. What can I do to make previously loaded items stay still except adding new section for every new portion of images?

Subclass from UICollectionViewFlowLayout?

For my needs I am really needing to subclass your control directly from UICollectionViewFlowLayout rather than having it be UICollectionViewLayout. I have gotten it to work by just commenting out the sectionInset, minimumLineSpacing, etc. setters, but am not sure if there is a reason why I need to have it subclass from UICollectionViewLayout rather than changing it? Would it be safe to use it this way?

Change back layout from UICollectionFlowLayout to NHBalancedFlowLayout cause crashes

In my project I start the collection view with NHBalancedFlowLayout. Then, when switch to edit mode, I change the layout to standard UICollectionFlowLayout. After finish editing, as soon I try to switch back to NHBalancedFlowLayout I got the following crash:

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* setObjectForKey: object cannot be nil (key: <NSIndexPath: 0xcf40130> {length = 2, path = 0 - 0})'

Any thought?

maximumRowHeight or item height?

If I try and layout one or two items I cannot seem to restrict the height. For example, if the image is really tall (say 1000px and only 10px wide) and I return a scaled estimated item size of 100px the layout manager still lays it out at 1000px.

Is there any way of preventing this problem? For example by providing a maximumRowHeight or perhaps have the estimated size layout closer to what Im returning?

Lots of free space between images

If sizes of images vary a lot - there is a lot of free space between images.

This can be tested by modifying demo project's method prefferedSizeForItemAtIndexPath like this

CGSize rect = [[self.images objectAtIndex:indexPath.item] size];
rect.width += arc4random()%2000;
rect.height += arc4random()%2000;

return rect;

screen shot 2013-11-14 at 12 04 27 am

Update. Also similar effect can be achieved with square images of same size.

Crash

Hi,

Thanks for this awesome layout !

It crash sometimes for me :

  • If no header and no footer while reloading, deleting or adding cells, and if collectionView.contentOffsetis (0,0)

Is there a special reason for NOT subclassing UICollectionViewFlowLayout ?

I'm going to investigate and push a pull request if I find a good solution, if you have any thought on this, I'll be glad to here them :)

Images are upscaled during the layout

I'm loading images from the server and naturally the thumbnails are pretty small, much smaller then the screen size. I noticed that only dimension ratios is taken into account, not sizes of the images themselves, thus images are often getting upscaled which is undesirable. Is there any workaround?

How can I highlight a picture when its selected?

I would like to use this cool collection view in my project. How can I put a border of blue color around the image when its selected? I tried this code and it didn't do anything. Any help please?

@interface ViewController ()

@Property (nonatomic, strong) NSArray *images;
@Property (nonatomic, strong) NSArray *itemSizes;
@Property (nonatomic, strong) NSMutableArray *imgsArray;

@EnD

@implementation ViewController

@synthesize imgsArray;

  • (id)initWithCoder:(NSCoder *)aDecoder
    {
    self = [super initWithCoder:aDecoder];
    if (self) {

    NSMutableArray *images = [[NSMutableArray alloc] init];
    imgsArray = [[NSMutableArray alloc] init];
    for (int i = 1; i <= NUMBER_OF_IMAGES; i++) {
        NSString *imageName = [NSString stringWithFormat:@"photo-%02d.jpg", i];
        [images addObject:[UIImage imageNamed:imageName]];
        [imgsArray addObject:imageName];
    }
    _images = [images copy];
    

    }

    return self;
    }

pragma mark - UICollectionViewFlowLayoutDelegate

  • (CGSize)collectionView:(UICollectionView *)collectionView layout:(NHBalancedFlowLayout *)collectionViewLayout preferredSizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    return [[self.images objectAtIndex:indexPath.item] size];
    }

pragma mark - UICollectionView data source

  • (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
    {
    return 1;
    }

  • (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;
    {
    return [self.images count];
    }

  • (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
    {
    ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ImageCell" forIndexPath:indexPath];
    cell.imageView.image = nil;

    /**

    • Decompress image on background thread before displaying it to prevent lag
      */
      NSInteger rowIndex = indexPath.row;
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

      UIImage *image = [UIImage decodedImageWithImage:[self.images objectAtIndex:indexPath.item]];

      dispatch_async(dispatch_get_main_queue(), ^{
      NSIndexPath *currentIndexPathForCell = [collectionView indexPathForCell:cell];
      if (currentIndexPathForCell.row == rowIndex) {
      cell.imageView.image = image;
      }
      });
      });

    return cell;
    }

  • (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
    {
    //NSLog(@"%s ..", PRETTY_FUNCTION);

    NSString *nameSelected = [imgsArray objectAtIndex:indexPath.row];
    NSLog(@"nameSelected: %@ ...", nameSelected);

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
    }

  • (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", PRETTY_FUNCTION);

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor clearColor]; // highlight selection
    }

  • (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
    {
    NSLog(@"%s", PRETTY_FUNCTION);
    return YES;
    }

Crash

2015-03-12 11:34:31.523 App[56367:1208348] *** Assertion failure in -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes:], /SourceCache/UIKit_Sim/UIKit-3318.93/UICollectionView.m:1360
2015-03-12 11:34:31.538 App[56367:1208348] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath (UICollectionElementKindSectionFooter,<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) was not retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: or is nil ((null))'

I don't use supplementary views.

Wrong collectionViewContentSize

I use UICollectionView with NHBalancedFlowLayout inside another UICollectionView because I must get the height of content in NHBalancedFlowLayout by this code:

[((NHBalancedFlowLayout *) self.filesList.collectionViewLayout) prepareLayout];
CGFloat collectionSize = [((NHBalancedFlowLayout *) self.filesList.collectionViewLayout) collectionViewContentSize].height;

But this function returns 0. How can I get the real size of content?

How to use NHBalancedFlowLayout

I know that this shouldn't be posted as an issue, but i really liked your work and would love to use it in my application. Im having trouble using the NHBalancedFlowLayout. In the example project you create an instance of the NHBalancedFlowLayout called "layout". How and where do you use this object exactly? I dont see it anywhere in the code.

Add supplementary views

Hi, I'm using this library for a social media app to display photos. It would be nice to be able to add a view to the photo to show comments, likes, etc...

Asynchronously loading preferredSizeForItemAtIndexPath

In the method collectionView:layout:preferredSizeForItemAtIndexPath I am needing to load the size of an image asynchronously from my server. The problem is that you can't return a value from inside a block.

This delegate method is called prior to the collectionView:cellForItemAtIndexPath and that is why I can't just directly access the image size. Is there a way to set the preferred size for an image after the collectionView:cellForItemAtIndexPath method?

Not working without Xib file

I always prefer working without xib file or storyboard. For some reasons, NHBalancedFlowLayout does not work properly. I downloaded sample project and modified it so that there is no storyboard file needed. Here is what I added after deleting Main.storyboard file, could you please tell me what I am doing wrong?

In AppDelegate.m:
ViewController *viewController = [[ViewController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
self.window.rootViewController = viewController;

In ImageCell.m:

-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
_imageView.clipsToBounds = YES;
_imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.contentView addSubview:_imageView];
}
return self;
}

In ViewController.m:
-(id)init{
self = [super init];
if (self) {

    NSMutableArray *images = [[NSMutableArray alloc] init];
    for (int i = 1; i <= NUMBER_OF_IMAGES; i++) {
        NSString *imageName = [NSString stringWithFormat:@"sample%d.jpg", i];
        [images addObject:[UIImage imageNamed:imageName]];
    }

    NHBalancedFlowLayout *flowLayout = [[NHBalancedFlowLayout alloc] init];
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
    [self.collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:@"ImageCell"];
    _images = [images copy];
}
return self;

}

Huge amount of items

If you apply it for example 10k+ items it get stuck on:
linearPartitionTable:(NSArray *)sequence numPartitions:(NSInteger)numPartitions

Performance issue with large image galleries

Thanks for this layout implementation. I found a performance problem, however, that I think is related to the Objective-C implementation of the linear partitioning algorithm.

I tried pulling this into a project displaying particularly large image galleries (say >500 images) on an iPad, aiming to have the images be ~150pt tall, giving on the order of 90 partitions.

When laying out the galley, the collection layout spent about 20 seconds each time it hit NHLinearPartition +linearPartitionForSequence:numberOfPartitions:, and Instruments particularly identified line 64:

m[x] = @{@"0": @(MAX([table[x][j-1] integerValue], [table[i][0] integerValue] - [table[x][0] integerValue])), @"1": @(x)};

nhbalancedflowlayout

This implementation of Linear Partitioning does a lot of Objective-C object-creation and method-calls in a very tight loop (the algorithm should be O(k•n^2) ). I doubt the sort is required—the Skiena algorithm this is based on doesn't perform a sort.

Randomize cell size

Hi,

How I can randomize size of cells? Images are downloaded from a server and I don't know the size when I create the layout.

Thanks!

Load images remotely

Hello, this may not be an issue. Will the balanced layout work if the images are loaded from a remote location? Im using afnetworking to retrieve an array of image URLs. Thanks for your help.

Images does not fill cell frame

Hi,

I've got this bug while building with xcode 6, with iOS 8 SDK, running the app on iOS 7.1.

screen shot 2014-09-26 at 12 08 50

Going to investigate if I've got enough time.

R.

Layout issue with xcode 6 GM

Hi,

Layout is not correct with xCode 6 GM on simulator as well as on device. Her are screenshot with the demo project :

capture d ecran 2014-09-15 a 09 45 05

Would be nice if you can post a fix since i have an application using your library actually on app store and that need to be updated due to iOS 8 release.

Thank for your support

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.