将新的viewcontroller推送到导航控制器时,将一个子视图保留在屏幕上的同一位置?

时间:2012-05-12 20:43:37

标签: iphone objective-c ios cocoa-touch uinavigationcontroller

我有一个带有许多图像按钮的“主屏幕”。在点击其中一个按钮后,细节视图控制器被推到导航控制器上。但是,在视觉上,我希望按钮中的图像保持在屏幕上的同一位置,同时新的视图控制器转换到它后面的位置。

模态控制器的一个示例是将照片添加到电子邮件或消息中。您在图库中选择的照片会变大(就像它向您移动一样),而撰写邮件视图会在背景中滑动到位,然后照片会缩小到消息视图的位置。

我想到了几个选项:

  • 点击按钮后,将图像放在屏幕上的同一位置,作为UIWindow的子视图。执行动画/过渡,然后将图像作为新viewcontroller视图的子视图。

  • 与上述相同,但模态视图控制器具有清晰的背景

  • 让UINavigationController成为子视图并使用UINavigationController的父视图执行上述操作

上面的所有选项都是类似的,但我很好奇是否有更好的方法来做到这一点,代码将存在于何处。我应该将UINavigationController子类化并将转换代码放在那里吗?或者也许AppDelegate(虽然看起来不对)?

3 个答案:

答案 0 :(得分:2)

我会在导航控制器或窗口中添加子视图,但是需要一些视图层次结构体操。

您需要为masterdetail视图控制器提供一种方法,以便对每个imageView上的ivar进行引用。

// PSMasterViewController.m
@interface PSMasterViewController ()

@property (nonatomic, strong) UIImageView *imageView;

@end

@implementation PSMasterViewController

@synthesize imageView = _imageView;

// ...
@end

我把它放在实现中,因为我不关心它是否为主视图控制器公开,但你的需求可能不同。

detailViewController

再次相同
// PSDetailViewController.h
@interface PSMasterViewController : UIViewController

@property (nonatomic, strong) UIImageView *imageView;

@end

// PSDetailViewController.m
@implementation PSDetailViewController

@synthesize imageView = _imageView;

// ...
@end

现在假设已经在主视图控制器中创建并显示了imageView,我们需要在我们即将推出时实现一些视图体操

- (void)methodThatPushesTheNextViewController;
{
    CGRect destinationFrame = [self.view convertRect:self.imageView.frame toView:self.navigationController.view];
    [self.imageView removeFromSuperview];
    [self.navigationController.view addSubview:self.imageView];
    self.imageView.frame = destinationFrame;

    PSDetailViewController *detailViewController = [[PSDetailViewController alloc] init];
    detailViewController.imageView = self.imageView;
    self.imageView = nil; // The detailViewController should own this now
    [self.navigationController pushViewController:detailViewController animated:YES];
}

现在在详细视图控制器中,我们需要做的与我们刚刚做的相反,viewDidAppear:是一个好地方,尤其是你提到的你可能想要移动和扩展

- (void)viewDidAppear:(BOOL)animated;
{
    [super viewDidAppear:animated];

    CGRect startFrame = [self.view convertRect:self.imageView.frame fromView:self.navigationController.view];
    [self.imageView removeFromSuperview];
    [self.view addSubview:self.imageView];
    self.imageView.frame = startFrame;

    [UIView animateWithDuration:0.25f
                     animations:^{
                         self.imageView.frame = [self someNewFrame];
                     }];
}

答案 1 :(得分:0)

选项1

你也可以在没有ModalViewController的情况下做到这一点。首先要记住的是,您必须删除图像并再次移动到pushViewController,因为如果发生视图转换,则会再次添加新的viewController,并且您之前的视图将消失。   所以这样做是通过向被推送的viewController发送NSNotification并使用相同的框架创建视图。还要记得在推送新的ViewController之前从superview中删除视图。

<强>选项2

如果需要拥有相关视图的所有视图控制器都是从单个ViewController子类继承的,则可以调用[super init]方法创建视图并将其添加到viewDidLoad方法中。

答案 2 :(得分:-1)

您可以根据自己的想法在视图上执行“UIView动画”,也可以使用iCarousel进行更清晰的动画icarousel SourceCode