使用带有 2 个可切换视图和一个分段控件的导航

Posted

技术标签:

【中文标题】使用带有 2 个可切换视图和一个分段控件的导航【英文标题】:Using UINavigation with 2 toggleable views and a UISegmented control 【发布时间】:2014-04-22 01:39:49 【问题描述】:

我有一个UISegmentedControl 和两个UICollectionViews

这个UISegmentedControl 可以在我的两个集合视图之间切换。

看看这张图片。在 UISegmentedControl 的左侧,您会看到分段控件上的单个项目视图显示视图按钮,该按钮的右侧是网格显示按钮。

网格显示按钮链接到 _collectionView 单个文件显示按钮链接到_collectionView2

默认情况下,我的应用会显示首次访问的 _collectionView。假设我点击了优化按钮。我的 UINavigation 将我带到另一个页面,然后如果我点击该页面上的后退按钮,它将带我回到 _collectionView 页面。

现在假设我点击单个文件显示按钮将我带到下图所示的 _collectionView2 页面。如果我然后点击优化按钮,然后点击返回以带我回到 _collectionView2 页面,它会显示 _collectionView 页面。

_collectionView 是在界面生成器中创建的,我猜它会在每次 viewWillAppear 运行时重新创建并替换 _collectionView2。我试图将它隐藏在 viewWillAppear 例如[_collectionView setHidden:YES]; 隐藏它并显示 _collectionView2。

单个文件显示:

这是 UISegmentedControl 的代码:

- (void)displayTypeSegmentSelected

    _selectedDisplayTypeIndex = [_displayTypeControl selectedSegmentIndex];


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

    [_fromCollectionView removeFromSuperview];

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


问题:

有没有办法让 UINavigation 实例知道它是从单个文件显示视图导航到的,这样当我单击返回时它不会重新加载 _collectionView?但将 make 带回 _collectionView?

更新 - 根据要求查看代码:

- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];

    NSLog(@"view will appear");



    // Create flow layout
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

    // Set up margins, sizes etc
    [layout setHeaderReferenceSize:CGSizeMake(50,93)];
    [layout setItemSize:CGSizeMake(300, 500)];
    [layout setMinimumLineSpacing:0];
    [layout setMinimumInteritemSpacing:0];
    [layout setSectionInset:UIEdgeInsetsMake(1, 0, 40, 0)];
    [layout setScrollDirection:UICollectionViewScrollDirectionVertical];

    // Initialise collection view 2 with frame, attach layout
    _collectionView2 = [[UICollectionView alloc] initWithFrame:[[_thisController view] frame] collectionViewLayout:layout];

    // Set background colour, delegate and dataSource
    [_collectionView2 setBackgroundColor:[UIColor whiteColor]];
    [_collectionView2 setDelegate:_thisController];
    [_collectionView2 setDataSource:_thisController];

    // Grab nib header nib file and give it a reuse identifier
    [_collectionView2 registerNib:[UINib nibWithNibName:@"VAGHeaderLabelReusableView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView2"];

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

    // Add as subview of this controller
    [_collectionView2 setFrame:[[_thisController view] bounds]];
   // [[_thisController view] addSubview:_collectionView2];



    [_thisController setTitle:@"S  H  O  P"];

    // Set to yes so back button isn't hidden and disabled. Note that back title is set to blank on controller that pushes to this one
    [[_thisController navigationItem] setLeftItemsSupplementBackButton: YES];

    // Create nav bar buttons
    UIBarButtonItem *searchButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"magnify_glass.png"] style:UIBarButtonItemStylePlain target:_thisController action:@selector(searchButtonTapped)];
    [[_thisController navigationItem] setLeftBarButtonItem:searchButton];

    UIBarButtonItem *shoppingCartButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"shopping_cart.png"] style:UIBarButtonItemStylePlain target:_thisController action:@selector(shoppingCartButtonTapped)];

    UIBarButtonItem *addFavouriteButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"add_fav_heart.png"] style:UIBarButtonItemStylePlain target:_thisController action:@selector(addFavouriteButtonTapped)];

    [[_thisController navigationItem] setRightBarButtonItems:@[shoppingCartButton, addFavouriteButton] animated: YES];

    // Reset refine button colour back to clear after returning from refineButtonTableViewController
    [_refineButton setBackgroundColor:[UIColor clearColor]];

    [_navigationBar setBarTintColor:[UIColor whiteColor]];
    [_navigationBar setTranslucent:NO];

    // Create filter bar
    [self createFilterBar];

【问题讨论】:

你不应该这样做——当你回到视图控制器时,它的子视图应该和你离开时一样。 _collectionView 不应该在每次 viewDidAppear 执行时都重新创建,除非你告诉它这样做。您要使用“返回”按钮返回吗?您应该在 viewDidAppear 中显示带有 2 个集合视图的控制器的代码。 是的,使用“返回”按钮返回。我添加了 viewWillAppear 的代码。问题是我在 viewWillAppear 中没有做任何与 _collectionView 相关的事情。该集合视图是在界面生成器中创建的。我有一个已连接到界面生成器中的 _collectionView 的商店按钮。默认情况下 _collectionView 是点击该按钮时显示的内容。我不知道发生了什么与我添加和删除集合视图的方式有关。这就像导航不知道 _collectionView2 在屏幕上,只是在我点击返回后加载 _collectionView。 导航控制器在加载视图方面没有做任何事情,它正在加载视图控制器。到目前为止,我在您发布的代码中没有看到任何会导致您出现问题的内容。如果你能把你的项目上传到某个地方,或者直接发给我,我很乐意看看。 【参考方案1】:

我在一个项目中遇到过类似的情况,我们决定简单地更改一个集合视图的单元格并重新加载集合视图,而不是使用两个单独的集合视图。我认为这将解决您的问题,并且由于您继续只管理一个集合视图,因此您可以减少实施的麻烦。您只需在 cellForItemAtIndexPath 方法中查看当前的可视化选择。从概念上讲,您将其实现为:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
    if (self.currentSelection == kSingleView) 
        return [self cellForSingleView];
     else 
        return [self cellForGridView];
    

如果您有多种可视化样式,您显然需要检查更多值。然后在您的 viewWillAppear 中,您只需重新加载集合视图。或者,您可能只想在 viewDidLoad 中加载集合视图,因为当视图控制器“弹出”到时不会调用它。这也是使用枚举来定义样式的好时机,因为枚举比常量更具可扩展性。

编辑

为此,您还必须检查您当前的选择并在sizeForItemAtIndexPath 中设置所需的单元格大小:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
    if (self.currentSelection == kSingleView) 
        // return size of Single View Cell
     else 
        // return size of Grid View Cell
    

另外,请确保您为每个单元格使用不同的单元格标识符。

【讨论】:

所以基本上检测一个段何时被点击,然后为该段返回适当的单元格,例如网格还是单个文件? 检测何时点击段,通过段的索引将选择设置为保持当前选择的 ivar(例如kSingleView),重新加载您的集合视图,然后在您的 cellForItemAtIndexPath 方法中检查对于当前的可视化选择并返回相应的单元格。 我最终通过模态显示视图解决了这个问题。【参考方案2】:

我通过模态显示视图并使用取消按钮将其关闭来解决此问题。对新控制器进行子类化,并在该文件中创建了一个连接到我的取消按钮的操作,其中包含在点击取消按钮时关闭控制器的代码。

#import "VAGRefineResultsTableViewController.h"

@interface VAGRefineResultsTableViewController ()


@end

@implementation VAGRefineResultsTableViewController

- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];

    // Do stuff here


- (IBAction)cancelButtonTapped:(id)sender 
    [self dismissViewControllerAnimated:YES completion:NULL];

【讨论】:

以上是关于使用带有 2 个可切换视图和一个分段控件的导航的主要内容,如果未能解决你的问题,请参考以下文章

在带有分段控件的 UITabBarController 中模态显示导航视图控制器

使用分段控件切换 NavigationItem 标题

带有选取器(分段控件)子视图和选择手势的列表项

带有 TableView 的 UINavigationBar 和 UITabBar 内的分段控件

如何在分段点击时隐藏 UItoolbar

使用分段控件的默认 UIView?