Pergunta

Been working on this for a few days now. I'm trying to allow customers of an app to switch between 2 display types when shopping.

Right now I'm using 2 UICollectionView's with their own custom UICollectionViewCell and the switching between the two works fine but I'm finding that working with 2 different UICollectionView's is becoming a pain. Certain things I've implemented for my main UICollectionView don't work properly in the alternative UICollectionView.

This is how the display is changed. I use a UISegmentedControl with a custom method:

enter image description here

- (void)displayTypeSegmentSelected
{
    _selectedDisplayTypeIndex = [_displayTypeControl selectedSegmentIndex];


    if (_selectedDisplayTypeIndex == 0) {
        NSLog(@"Single file item view selected");
        _fromCollectionView = _collectionView;
        _toCollectionView = _collectionView2;


    } else if (_selectedDisplayTypeIndex == 1) {
        NSLog(@"Grid style view selected");
        _fromCollectionView = _collectionView2;
        _toCollectionView = _collectionView;
    }

    [_fromCollectionView removeFromSuperview];

    [_toCollectionView setFrame:[_superView bounds]];
    [_superView addSubview:_toCollectionView];

}

I've had two different suggestions via stackoverflow about a better way to do what I'm trying to do.

  1. Use 2 UICollectionViewFlowLayout's and switch between them instead of 2 UICollectionView's.
  2. Return the appropriate custom UICollectionViewCell depending on what segment is selected.

I feel the first way would be better. I would need to make the interface builder UICollectionViewFlowLayout an IBOutlet because the connected UICollectionView wasn't created programmatically. Then I'd create the second UICollectionViewFlowLayout programmatically.

In my displayTypeSegmentSelected method I'd load one of the two UICollectionViewFlowLayout's depending on the selected segment.

Single File Display would look like this:

enter image description here

Grid Style Display would look like this:

enter image description here

Question:

I think I have the right idea on the best way to go about doing what my original question asks and how to do it. However I'd profile an opinion and example from a more experience developer. How would you do this and can you show me a clear example I can go and mess around with?

Kind Regards

Foi útil?

Solução

This is how I did things in the end.

Upon tapping of specific segmented control I changed the layout and reloaded the cells.

- (void)displayTypeSegmentSelected
{
    _selectedDisplayTypeIndex = [_displayTypeControl selectedSegmentIndex];

    if (_selectedDisplayTypeIndex == 0) {
        NSLog(@"Single file item view selected");
        [_collectionView setCollectionViewLayout:_flowLayout2 animated:YES];
        [_collectionView reloadItemsAtIndexPaths:[_collectionView indexPathsForVisibleItems]];


    } else if (_selectedDisplayTypeIndex == 1) {
        NSLog(@"Grid style view selected");
        [_collectionView setCollectionViewLayout:_flowLayout animated:YES];
        [_collectionView reloadItemsAtIndexPaths:[_collectionView indexPathsForVisibleItems]];
    }

}

In my cellForItemAtIndexPath depending on which layout was present on screen I loaded a specific custom cell with correct settings.

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{

        NSLog(@"collectionview 1 loaded");

        static NSString *CellIdentifier = @"Cell";
        VAGGarmentCell *cell = [_collectionView dequeueReusableCellWithReuseIdentifier: CellIdentifier forIndexPath:indexPath];
        static NSString *CellIdentifier2 = @"Cell2";
        VAGGarmentCell2 *cell2 = [_collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier2 forIndexPath:indexPath];


    if ([[_collectionView collectionViewLayout] isEqual: _flowLayout]) {
        [[cell activityIndicator] startAnimating];

        PFFile *userImageFile = [object valueForKey:@"image"];
        [[cell imageView] setFile: userImageFile];
        [[cell imageView] loadInBackground];

        [[cell activityIndicator] stopAnimating];

        [[cell title] setText:[object valueForKey:@"title"]];
        [[cell price] setText:[NSString stringWithFormat: @"£%@ GBP", [object valueForKey:@"price"]]];
        return cell;

    } else if ([[_collectionView collectionViewLayout] isEqual: _flowLayout2]) {
        [[cell2 activityIndicator] startAnimating];

        PFFile *userImageFile = [object valueForKey:@"image"];
        [[cell2 imageView] setFile: userImageFile];
        [[cell2 imageView] loadInBackground];

        [[cell2 activityIndicator] stopAnimating];

        [[cell2 title] setText:[object valueForKey:@"title"]];
        [[cell2 price] setText:[NSString stringWithFormat: @"£%@ GBP", [object valueForKey:@"price"]]];
        return cell2;
    }

     return 0;

    //_addToFavouritesButton = [cell addFavouriteButton];

    [_addToFavouritesButton addTarget:_thisController action:@selector(addToFavouritesButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}

In my viewDidLoad here's where I reference the nib file for the custom cell for single item display.

// Grab cell nib file and give a reuse identifier
[_collectionView registerNib:[UINib nibWithNibName:@"VAGGarmentCell2" bundle:nil] forCellWithReuseIdentifier:@"Cell2"];

I get crashes but they're very hard to replicate, although every time I toggle between the different layouts my memory rises and rises. I'm guessing there's some old code that I need to remove. I'll sort this out tomorrow and check it out with instruments. However this is done and I can move on.

I may need to refactor the code where I repeat myself.

Outras dicas

I had some problems in the toggling animation of a collectionView display. Your solution also helped me.

Here is my result.

enter image description here

And here is the solution

Toggle action in ViewController

            if self.displayType == .grid {
                self.displayType = .table
            }else {
               self.displayType = .grid
            }

            // Only update item size here
            self.updateFlowLayout()

            self.collectionView.performBatchUpdates({

                self.collectionView.setCollectionViewLayout(self.flowLayout, animated: true)

            }, completion: { (finished) in

            })

I'm using one collectionViewCell. Override the layoutSubviews of cell

override func layoutSubviews() {
    super.layoutSubviews()
    if (self.bounds.width / self.bounds.height) > 1.4 {
        if self.displayType != .table {
            self.displayType = .table
        }
    }else {

        if self.displayType != .grid {
            self.displayType = .grid
        }
    }
}

And in displayType

var displayType : CastDisplayType = .grid {
        didSet {
            //Update constraints of subviews between cell
            updateLayout()
        }
    }

Hopes it could be helpful to some people.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top