在iPad上的popover中推送导航视图控制器时动画popoverContentsize

时间:2012-09-26 16:01:11

标签: ios ipad uitableview uipopovercontroller

当包含的UINavigationController推送新控制器时,如何让我的UIPopoverController为其大小设置动画?

我的iPad应用中UIPopover显示UIBarButtonItem。它包含一个UINavigationViewController,它有一种设置窗口作为其根视图控制器。设置窗口是UITableViewController的子类(样式设置为分组),并且点击其任何单元格会在导航控制器上推送不同的“选择器”视图控制器,这些控制器也是UITableViewController的子类。

对于每个选择器视图,在viewDidAppear中,我正确地设置contentSizeForViewInPopover

self.contentSizeForViewInPopover = CGSizeMake(320, self.items.count * 44);

但它没有动画变化;导航动画完成后,弹出窗口将捕捉到新的高度(宽度永远不会从320更改)。向后导航可以调整大小的变化(使用this answer中的技术完成),但前进从未进行过。

我尝试使用setPopoverContentSize:animated:获取对其中的popover的引用,但它不起作用。我看过other questions无济于事。

如何让它始终为尺寸变化设置正确的动画?

更新:我已经设置了一个简单的测试项目来试试这个。这是在Xcode中设置iPad的标签栏应用程序。我在其中一个视图控制器的导航栏中添加了一个标签栏项。按下该按钮时,控制器会显示一个包含导航控制器的弹出窗口,该导航控制器具有一个非常简单的UITableViewController子类,称为TestContentViewController,作为其根视图控制器。

在该子类的viewDidLoad中,我随机生成了许多项目:

self.numItems = arc4random() % 10 + 3;

这是我的行数;部分的数量是1.在cellForRowAtIndexPath我只是设置单元格的标签文本并将其返回。当选择一行时,我生成同一个类的另一个实例并将其推送到堆栈上。

在没有对任何VC上的contentSizeForViewInPopover属性做任何事情的情况下,无论我的表视图中有多少行,弹出窗口都会达到其最大高度并保持不变。

如果我在viewDidAppear中设置大小,就像这样:

-(void)viewDidAppear:(BOOL)animated
{
  self.contentSizeForViewInPopover = CGSizeMake(320, self.numItems * 44);
  [super viewDidAppear:animated];
{
  • 当弹出窗口首次出现时,它会快速闪烁至全高,然后按下我设定的高度。
  • 当在导航控制器上按下新控制器时,它会捕捉到没有动画的高度。
  • 当我向后导航时,如果我弹出的VC高于我弹出的VC,它会动画到正确的大小。如果我弹出的东西更小,它什么都不做。

如果我在viewWillAppear中做同样的事情:

  • 首次出现弹出窗口时,它是全高
  • 当我第一次点击一行并在堆栈上获得一个新控制器时,它会动画至最低约400px高。当一个新的控制器被推入堆栈时,如果它需要更多的高度,它就会得到它。如果没有,它会保持原状。

如果我在viewDidLoad中执行相同的操作,它与viewWillAppear基本相同,不过它首先显示的是正确的大小。

我已经尝试将导航控制器的委托设置为呈现弹出窗口的VC,然后在setPopoverContentSize:animated:中设置弹出窗口的高度(navigationController:didShowViewController:animated:),但结果高度稍微偏离位。我认为我在那里设置的尺寸需要考虑内置在弹出窗口顶部的导航栏的额外高度。在堆栈上推送新控制器时的动画很奇怪。

再次更新:有关使用较新的UIPopoverPresentationController解决的同一问题,请参阅here

3 个答案:

答案 0 :(得分:8)

尝试对所有 UITableViewController 执行以下操作,我尝试了它,它对我有用!

- (void)setSize:(BOOL)fake
{
    CGSize view_size;
    int sections_height, rows_height;

    //if you dynamically change the number of visible rows
    //for example overriding numberOfRowsInSection:section
    //this can help you to evaluate the correct popover height
    int sections = [self.tableView numberOfSections];
    int rows = 0;
    for(int i = 0; i < sections; i++){
        rows += [self.tableView numberOfRowsInSection:i];
    }
    sections_height = sections * 30 /*section height*/;
    rows_height = rows * 44 /*row height*/;

    view_size = CGSizeMake(320 /*fixed width*/, sections_height + rows_height);

    if(fake){
        view_size.width -= 1;
        view_size.height -= 1;
    }

    [self setContentSizeForViewInPopover:view_size];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    //...    
    [self setSize:FALSE];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self setSize:TRUE];
}

- (void)viewDidAppear:(BOOL)animated
{
    [self setSize:FALSE];
    [super viewDidAppear:animated];
}

答案 1 :(得分:2)

如果您尝试保留对popoverController的引用并使用setPopoverContentSize:animated:

,我认为您很接近

对我来说有用的是setPopoverContentSize:animated:contentSizeForViewInPopover在特定顺序中的组合,对于放在堆栈中的每个控制器:

-(void)viewDidAppear:(BOOL)animated
{
    [self.popoverController setPopoverContentSize:whateverSize animated:true];
    self.contentSizeForViewInPopover = whateverSize;
    [super viewDidAppear:animated];
}

在这种情况下,self.popoverController是我在每个控制器中保留的引用,它被推入堆栈中,使用单例变量可能更清晰。

答案 2 :(得分:0)

如果您正在寻找动画,可以尝试以下代码。老实说,我没有iPad开发的经验,但我用它来为几乎所有项目中的帧和alpha变化设置动画。 参数很简单,您可以按顺序查看动画发生的持续时间,时间延迟,动画选项,指定视图中更改的块以及指定后果的另一个块对象。

[UIView animateWithDuration:1.0
                      delay:0.0
                    options: UIViewAnimationCurveEaseOut
                 animations:^{
               self.contentSizeForViewInPopover = CGSizeMake(320, self.items.count * 44);
                 }
                 completion:^(BOOL finished){
                //Insert what you need to do after the animation is over
                 }];

您可以尝试将其放入 - (void)viewDidAppear:(BOOL)动画

尝试一下,让我知道它是否有效。