UIModalTransitionStylePartialCurl с UITabBarController - PullRequest
6 голосов
/ 29 июля 2011

Этот вопрос часто задавался, например, здесь но, насколько я вижу, еще предстоит ответить полностью.

У меня есть UITabBarController с UINavigationController в качестве корневого vc для одной из вкладок, которая сама имеет MKMapView в качестве корневого vc. Я хочу, чтобы карта частично скручивалась вверх, , оставляя панель вкладок на месте (аналогично приложению Карты).

Пока все, что мне удалось получить, - это свернуть весь вид, что не так приятно.

Решения, которые я видел, заключаются в том, чтобы установить для свойства hidesBottomBarWhenPushed значение NO, что имело бы смысл, однако, похоже, это не сработало (если только я что-то не так делаю).

Для ясности мой код выглядит следующим образом:

MyVC *aView = [MyVC init];
aView.modalTransitionStyle = UIModalTransitionStylePartialCurl;
aView.hidesBottomBarWhenPushed = NO;

В данной части я попробовал две альтернативы ниже, ни одна из которых не работает:

[self presentModalViewController:updateStatus animated:YES];
[[self navigationController] presentModalViewController:updateStatus animated:YES];

Любая помощь высоко ценится.

Ответы [ 2 ]

4 голосов
/ 10 июля 2012

Я искал StackOverflow (и Интернет) для решения этой проблемы. Вопрос задавался много раз, но, как вы заметили, так и не получил достаточного ответа. Многие решения дают приемлемое решение, если неважно, свернется ли, например, нижняя панель инструментов.

Другие предоставили решение, использующее UIView animations / CoreAnimation вместо UIModalTransitionStylePartialCurl в качестве стиля модального перехода; в худшем случае это решение не разрешено в App Store, и в лучшем случае это не совсем тот же эффект, который можно получить от UIModalTransitionStylePartialCurl (например, форма завитка отличается).

Ни одно из этих решений не дало ответа, который имитирует решение Apple в приложении "Карты" (т. Е. С использованием UIModalTransitionStylePartialCurl, но с не скрученным UIToolbar в нижней части экрана).

Я продолжу эту традицию неполных ответов, поскольку вы спрашиваете о UITabBarController, и мое решение конкретно не касается этого случая. Это, однако, решает проблему, с которой я столкнулся: получить завиток на полстраницы с не скрученной панелью инструментов внизу.

Должен быть более элегантный способ сделать это, но так я справился.

rootViewController моего AppDelegate - это подкласс UIViewController, который я назову TAContainerViewController. TAContainerViewController управляет а) фактическим содержимым экрана («материал для скручивания»), TAContentViewController и б) содержимым «за» TAContentViewController (например, настройками), которое я назову TAUnderCurlViewController.

Мой экземпляр TAContainerViewController имел свойства для TAContentViewController и TAUnderCurlViewController. UIView, который был моим контентом, был подпредставлением свойства TAContentViewController view; аналогично, то, что пользователь видит под завитком, это свойство view TAUnderCurlViewController.

В методе init из TAContainerViewController я выполняю следующие действия:

    _underCurlVC.modalTransitionStyle = UIModalTransitionStylePartialCurl;

И чтобы свернуть содержимое для отображения под страницей, я настроил действие, которое вызывает этот код:

    [self.contentVC presentModalViewController:self.underCurlVC animated:YES];`

, где self - это TAContainerViewController, contentVC - это экземпляр TAContentViewController, а underCurlVC - это экземпляр TAUnderCurlViewController.

Чтобы отклонить представление, просто [self.contentVC dismissModalViewControllerAnimated:YES];.

Кажется, что некоторая странность возникает с рамкой contentVC, когда модальный вид отклоняется, поэтому я вручную сбрасываю кадр, когда модальный вид отклоняется.

Я опубликовал пример проекта с более подробной информацией о Github . Надеюсь, кто-то может взять это и превратить в более элегантное решение или расширить его для работы с UINavigationController или UITabBarController. Я думаю, что хитрость заключается в том, чтобы вытащить контроллеры вида из четко определенных отношений в подклассах Какао, поэтому, возможно, подклассы этих специализированных контроллеров вида сделают это.

1 голос
/ 10 июня 2013

Ответ Тима Арнольда отлично сработал для меня, спасибо!

Одна ловушка, на которую стоит обратить внимание: ваш модальный переход страницы-скручивание займет весь экран, если ваш контроллер представления контента добавлен какдочерний элемент контроллера представления контейнера .Вы можете просто не добавлять его как дочерний элемент, но тогда ни один из методов жизненного цикла представления не будет вызван на вашем контроллере контента (например, viewDidLoad, viewWillAppear), что может быть проблемой.

К счастью,Есть способ обойти это.В вашем контроллере контейнера:

  • Добавьте ваш контроллер контента как дочерний в viewDidLoad
  • Удалите его как дочерний в viewDidAppear
  • Повторно добавьте егокак ребенок в viewWillDisappear.

Таким образом, ваш контроллер содержимого получает вызовы методов своего жизненного цикла, в то же время имея возможность выполнять модальное переключение скручивания страницы, не занимая весь экран.

Вот весь код простого решения:

@interface XXContainerController : UIViewController
@property (strong, nonatomic) UIViewController *contentController;
@property (nonatomic) BOOL curled;
@end

@implementation XXContainerController

@synthesize contentController = _contentController;
@synthesize curled = _curled;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.contentController = [self.storyboard
        instantiateViewControllerWithIdentifier:@"SomeControllerInStoryboard"];

    // Add content controller as child view controller.
    // This way, it will receive all the view lifecycle events
    [self addChildViewController:self.contentController];
    self.contentController.view.frame = self.view.bounds;
    [self.view addSubview:self.contentController.view];
    [self.contentController didMoveToParentViewController:self];    
}

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

    // Remove the content controller as child view controller.
    // This way, the modal page curl transition will
    // not take over the whole screen.
    // NOTE: need to wait until content controller has appeared
    // (which will happen later).
    // Achieve this by running the code at the end of the animation loop
    [UIView animateWithDuration:0 animations:nil completion:^(BOOL finished) {
        [self.contentController removeFromParentViewController];
    }];
}

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

    // Add the content controller as child view controller again
    // so it receives the view lifecycle events
    [self addChildViewController:self.contentController];
}

- (void)setCurled:(BOOL)curled
{
    if (curled == _curled) return;

    _curled = curled;

    // Curl up the content view and show underneath controller's view
    if (curled) {
        // Note you can specify any modal transition in storyboard
        // E.g. page curl, flip horizontal
        [self.contentController
            performSegueWithIdentifier:@"SomeModalSegueDefinedInStoryboard"
            sender:self];

    // Uncurl and show the content controller's view again
    } else {
        [self.contentController dismissModalViewControllerAnimated:YES];

        // Have to do this, otherwise the content controller's view
        // gets messed up for some reason 
        self.contentController.view.frame = self.view.bounds;
    }
}

@end
...