Ios 如何在2个不同的UICollectionViewFlowLayout实例之间切换?

Ios 如何在2个不同的UICollectionViewFlowLayout实例之间切换?,ios,objective-c,cocoa-touch,uicollectionview,uicollectionviewcell,Ios,Objective C,Cocoa Touch,Uicollectionview,Uicollectionviewcell,我已经为此工作了几天了。我正在尝试允许应用程序的客户在购物时在两种显示类型之间切换 现在我正在使用2个UICollectionView,它们有自己的自定义UICollectionViewCell,在这两个视图之间切换很好,但我发现使用2个不同的UICollectionView,正在成为一种痛苦。我为主UICollectionView实现的某些东西在备选UICollectionView中无法正常工作 这就是显示的更改方式。我将UISegmentedControl与自定义方法一起使用: - (voi

我已经为此工作了几天了。我正在尝试允许应用程序的客户在购物时在两种显示类型之间切换

现在我正在使用2个
UICollectionView
,它们有自己的自定义
UICollectionViewCell
,在这两个视图之间切换很好,但我发现使用2个不同的
UICollectionView
,正在成为一种痛苦。我为主
UICollectionView
实现的某些东西在备选
UICollectionView
中无法正常工作

这就是显示的更改方式。我将
UISegmentedControl
与自定义方法一起使用:

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

}

通过stackoverflow,我得到了两个不同的建议,关于如何更好地完成我想做的事情。

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

}
-(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];
}
// Grab cell nib file and give a reuse identifier
[_collectionView registerNib:[UINib nibWithNibName:@"VAGGarmentCell2" bundle:nil] forCellWithReuseIdentifier:@"Cell2"];
  • 使用2
    UICollectionViewFlowLayout
    ,并在它们之间切换,而不是使用2
    UICollectionView
  • 根据选择的段返回相应的自定义
    UICollectionViewCell
  • 我觉得第一种方法会更好。我需要将接口生成器
    UICollectionViewFlowLayout
    设置为IBOutlet,因为连接的
    UICollectionView
    不是以编程方式创建的。然后我将以编程方式创建第二个
    UICollectionViewFlowLayout

    在我的displayTypeSegmentSelected方法中,我将根据所选的段加载两个
    UICollectionViewFlowLayout
    中的一个

    单个文件显示如下所示:

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

    网格样式显示如下所示:

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

    问题:

    - (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];
    
    }
    
    我想我有一个正确的想法,那就是如何按照我最初的问题去做,如何去做。不过,我会从经验丰富的开发人员那里介绍一个观点和示例。 你会如何做到这一点,你能给我一个清晰的例子,我可以去乱搞吗


    亲切的问候

    这就是我最后做事情的方式

    点击特定分段控件后,我更改布局并重新加载单元格。

    - (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]];
        }
    
    }
    
    -(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];
    }
    
    // Grab cell nib file and give a reuse identifier
    [_collectionView registerNib:[UINib nibWithNibName:@"VAGGarmentCell2" bundle:nil] forCellWithReuseIdentifier:@"Cell2"];
    
    在我的
    单元格ForItemAtIndexPath
    中,根据屏幕上显示的布局,我加载了具有正确设置的特定自定义单元格。

    - (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]];
        }
    
    }
    
    -(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];
    }
    
    // Grab cell nib file and give a reuse identifier
    [_collectionView registerNib:[UINib nibWithNibName:@"VAGGarmentCell2" bundle:nil] forCellWithReuseIdentifier:@"Cell2"];
    
    在我的viewDidLoad中,这里是我为单个项目显示的自定义单元格引用nib文件的地方。

    - (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]];
        }
    
    }
    
    -(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];
    }
    
    // Grab cell nib file and give a reuse identifier
    [_collectionView registerNib:[UINib nibWithNibName:@"VAGGarmentCell2" bundle:nil] forCellWithReuseIdentifier:@"Cell2"];
    
    虽然每次我在不同的布局之间切换时,我的内存都会不断增加,但我会遇到崩溃,但它们很难复制。我猜我需要删除一些旧代码。我明天会把它整理好,用仪器检查一下。然而,这已经完成,我可以继续前进


    我可能需要在重复自己的地方重构代码。

    我在切换collectionView显示的动画时遇到一些问题。你的解决方案也帮助了我

    这是我的结果

    这就是解决办法

    在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
    
                })
    
    我正在使用一个collectionViewCell。 覆盖单元的布局子视图

    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
            }
        }
    }
    
    和显示类型

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

    希望它能对一些人有所帮助。

    此时,在github上发布一个精简/基本版本的代码可能是值得的,这样任何人都可以使用它。。。祝你好运。我同意你的决定,第一种方法是在布局之间切换。要做到这一点,没有多少事情要做。看起来您已经构建了这两个布局,只需在分段控件的操作方法中使用setCollectionViewLayout:animated:completion:在它们之间切换即可。试着去实现它,如果你遇到麻烦,再问一个更具体的基于代码的问题。@rdelmar,设置它确实花了5分钟,而且效果很好。这部动画片是一种奖励。我现在唯一的问题是切换到的布局使用了原始布局的单元,默认情况下,该单元比我为单视图布局创建的单元小得多。切换时,我获得了单文件视图,由于布局设置(项目插入300x500),单元格被放大,但由于使用了其他布局单元格,图像视图仍然很小。解决这个问题的最佳方法是什么?我想我可以检查cellForItemAtIndex中的当前布局,但事实证明这很困难。只需使用collectionView:layout:SizeForItemIndeXPath:。布局已为您传入,请检查它是哪一个,并返回该布局所需的大小。@rdelmar,这将调整单元格的大小,但不会调整包含项目图像的“我的图像”视图的大小。图像视图保持不变。最终崩溃与此无关。我真的很感谢你在这里所做的一切和你编写的代码。我正在做一些类似的事情,但是我的问题是动画看起来不太好,如果我在布局之间快速切换,所有的单元格都会消失。不太好。