Вид iOS 7 с прозрачным содержимым перекрывает предыдущий вид

Недавно я обновил свой проект xcode для работы с iOS 7, но столкнулся с большой проблемой. Поскольку все мое приложение имеет только одно фоновое изображение (UIImageView добавлен в ключевое окно) и все представления прозрачны, я сталкиваюсь с проблемой при нажатии UIViewController, потому что отправленный контроллер представления перекрывает предыдущее представление (вы можете видеть это на картинке здесь: http://grab.by/qp0k). Я могу предсказать, что это связано с тем, что в iOS 7 был изменен push-переход, потому что теперь он скользит на полэкрана. Может кто знает как решить эту проблему?

Вот как я устанавливаю свои ключевые окна

  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
 UIImageView *background = [[UIImageView alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
 background.image = [UIImage imageNamed:@"background.png"]; 
UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:self.viewController];
self.window.rootViewContro‌​ller = navi;
 [self.window makeKeyAndVisible];

После этого, когда пользователь нажимает кнопку «Начать тренировку», я, как обычно, нажимаю следующий вид:

workoutView *w = [[workoutView alloc]initWithNibName:@"workoutView" bundle:nil];
        [self.navigationController pushViewController:w animated:YES];

person Edvardas    schedule 18.09.2013    source источник
comment
Можете ли вы добавить код, который вы используете для установки ключевого окна и первого контроллера представления?   -  person Kevin    schedule 19.09.2013
comment
@Kevin Обновил мой вопрос!   -  person Edvardas    schedule 19.09.2013
comment
@Edvardas, вы решили эту проблему, сохранив фоновое изображение с одним изображением? У меня та же проблема.   -  person Tom Redman    schedule 21.09.2013
comment
@Edvardas, я тоже ищу здесь решение   -  person Zhao Xiang    schedule 24.09.2013


Ответы (9)


Я решил проблему, внедрив новый UINavigationControllerDelegate метод animationControllerForOperation.

Например:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController     *)navigationController
                              animationControllerForOperation:(UINavigationControllerOperation)operation
                                           fromViewController:(UIViewController *)fromVC
                                             toViewController:(UIViewController *)toVC
{

PushTransition* transition = [PushTransition new];
[transition setNavigationControllerOperation: operation];

return transition;
}

PushTransition — это класс, который реализует протокол UIViewControllerAnimatedTransitioning и два метода transitionDuration и animateTransition из этого протокола. Кроме того, я добавил свойство для передачи операции (сообщает мне, является ли это переходом push или pop).

Просто поместите код анимации для перемещения представлений в animateTransition следующим образом:

// the containerView is the superview during the animation process.
UIView *container = transitionContext.containerView;

UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

UIView *fromView = fromVC.view;
UIView *toView = toVC.view;
CGFloat containerWidth = container.frame.size.width;

// Set the needed frames to animate.

CGRect toInitialFrame = [container frame];
CGRect fromDestinationFrame = fromView.frame;

if ([self navigationControllerOperation] == UINavigationControllerOperationPush)
{
    toInitialFrame.origin.x = containerWidth;
    toView.frame = toInitialFrame;
    fromDestinationFrame.origin.x = -containerWidth;
}
else if ([self navigationControllerOperation] == UINavigationControllerOperationPop)
{
    toInitialFrame.origin.x = -containerWidth;
    toView.frame = toInitialFrame;
    fromDestinationFrame.origin.x = containerWidth;
}

// Create a screenshot of the toView.
UIView *move = [toView snapshotViewAfterScreenUpdates:YES];
move.frame = toView.frame;
[container addSubview:move];

[UIView animateWithDuration:TRANSITION_DURATION delay:0
     usingSpringWithDamping:1000 initialSpringVelocity:1
                    options:0 animations:^{
                        move.frame = container.frame;
                        fromView.frame = fromDestinationFrame;
                    }
                 completion:^(BOOL finished) {
                     if (![[container subviews] containsObject:toView])
                     {
                         [container addSubview:toView];
                     }

                     toView.frame = container.frame;
                     [fromView removeFromSuperview];
                     [move removeFromSuperview];
                     [transitionContext completeTransition: YES];
                 }];

описал это, и вы можете вы сделали. Кроме того, вы можете сделать любую анимацию push или pop, которая вам нравится.

person snoersnoer    schedule 22.10.2013
comment
Где этот код анимации для перемещения представлений в метод animateTransition, как описано в JX2, о котором вы говорите? - person race_carr; 19.03.2014
comment
Пожалуйста, посмотрите на обновление. Я добавил код для вас. - person snoersnoer; 20.03.2014
comment
Я не вижу необходимости создавать снимок для анимации. Почему бы не анимировать реальные виды напрямую? - person Daniel Rinser; 31.03.2015
comment
Если я правильно помню, можно было взаимодействовать с элементами пользовательского интерфейса UIViewController до завершения анимации. - person snoersnoer; 07.04.2015
comment
@snoersnoer Если бы это было так, вы могли бы просто установить userInteractionEnabled в false, пока не будет вызвано завершение - person keji; 17.06.2016
comment
Вот просеянная версия: gist.github.com/k3zi/9ab2e57381349dcd7fd9abd6e029430b - person keji; 17.06.2016
comment
Привет, спасибо за этот ответ, однако, если вы подождете, прежде чем вызвать всплывающее окно, представление будет удалено, и поэтому анимация будет между прозрачным (несуществующим представлением) и текущим представлением. У вас есть идеи, почему? Большое спасибо - person Clad Clad; 24.02.2017

Я сделал это.

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [self.view setAlpha:0];
}

Не забудьте сбросить альфу, когда вернетесь.

- (void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.view setAlpha:1];
}
person Alexandre    schedule 23.09.2013
comment
Это имеет некоторое значение для перехода к предыдущему ViewController, но не работает для перехода к новому ViewController. Старые VC -viewWillDisappear: и -viewWillAppear: не вызываются при переходе к новому. - person Zhao Xiang; 24.09.2013
comment
И когда вы возвращаетесь к предыдущему VC, другой VC можно увидеть на секунду. - person Zhao Xiang; 24.09.2013
comment
Ваш первый комментарий странный, но: И когда вы возвращаетесь к предыдущему VC, другой VC можно увидеть на секунду, к сожалению, это правильно ... Если у кого-то есть лучшее решение, оно должно быть полезно. - person Alexandre; 24.09.2013
comment
Это самый простой способ решить проблему. Apple, не делающая хороших переходов на прозрачном фоне, просто нелепа! - person Ethan Allen; 12.02.2014

Я исправил это, сделав это при инициализации представления:

self.view.clipsToBounds = YES;
person Enrico Susatyo    schedule 01.11.2014
comment
Это сработало и для меня, спасибо. Есть идеи, почему это работает? - person Alex Terreaux; 11.02.2015
comment
@AlexTerreaux На самом деле понятия не имею. - person Enrico Susatyo; 11.02.2015

Возможно, вы захотите изучить новую функцию iOS7, которая позволяет вам определять свои собственные пользовательские переходы UIViewController. Посмотрите в документации UIViewControllerTransitioningDelegate. Кроме того, вот ссылка на статью об этом: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

person John Jacecko    schedule 24.09.2013

А, теперь я понимаю проблему. Вы были правы, похоже, это вызвано тем, что предыдущий UIViewController не скрывался после перехода (из-за нового эффекта перехода).

Кажется, нет никакого метода SDK для управления этим поведением. Если не считать редизайна приложения, чтобы фон не был статичным, вам, вероятно, придется перевернуть собственную навигацию. OSNavigationController — это полная повторная реализация UINavigationController, которая может вам помочь. Если они не обновились до перехода на iOS 7, вы, вероятно, будете в порядке. Если они есть, вы всегда можете использовать более старую версию.

person Kevin    schedule 19.09.2013

У меня такая же проблема. Попробуйте загрузить фоновое изображение в методе init. Для меня это работало (иногда): Например:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        self.view.backgroundColor = [UIColor whiteColor];
        [self.imageBack setImage:[UIImage imageNamed:@"mayBack.png"]];
    }
    return self;
}

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

person gdm    schedule 08.10.2013

Установка изображения на цвет фона решила проблему:

self.view.backgroundColor = 
            [UIColor colorWithPatternImage:[UIImage imageNamed:@"mainback.png"]];
person user3010978    schedule 19.11.2013

Взгляните на категорию UINavigationController в этом посте (это решило мою проблему):

https://stackoverflow.com/a/18882232/2826409

person Eran Katsav    schedule 28.09.2013

Реквизит для @snoersnoer.


Вот код в Swift 3.

func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {

    let pushTransition = SUPushTransition()
    pushTransition.navigationControllerOperation = operation
    return pushTransition
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    // the containerView is the superview during the animation process.
    let container = transitionContext.containerView

    let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
    let toVC = transitionContext.viewController(forKey:UITransitionContextViewControllerKey.to);

    if let from = fromVC,
        let fromView = from.view,
        let to = toVC,
        let toView = to.view {

        let containerWidth = container.frame.size.width

        // Set the needed frames to animate.

        var toInitialFrame = container.frame
        var fromDestinationFrame = fromView.frame

        if self.navigationControllerOperation == .push {
            toInitialFrame.origin.x = containerWidth;
            toView.frame = toInitialFrame;
            fromDestinationFrame.origin.x = -containerWidth;
        }
        else if self.navigationControllerOperation == .pop {
            toInitialFrame.origin.x = -containerWidth;
            toView.frame = toInitialFrame;
            fromDestinationFrame.origin.x = containerWidth;
        }

        // Create a screenshot of the toView.
        if let move = toView.snapshotView(afterScreenUpdates: true) {

            move.frame = toView.frame
            container.addSubview(move)

            UIView.animate(withDuration: Constants.MainPage.navControllerDuration, delay: 0.0, usingSpringWithDamping: 1000, initialSpringVelocity: 1, options: .curveEaseInOut, animations: {
                move.frame = container.frame;
                fromView.frame = fromDestinationFrame;
            }, completion: { (finished) in

                if finished {

                    if !container.subviews.contains(toView) {
                        container.addSubview(toView)
                    }

                    toView.frame = container.frame

                    fromView.removeFromSuperview()
                    move.removeFromSuperview()

                    transitionContext.completeTransition(true)
                }

            })

        }

    }

}

Ваше здоровье.

person Brandon A    schedule 24.12.2016
comment
Как это использовать? - person Elsammak; 27.10.2017