ios 7 view with transparent content overlaps previous view

百般思念 提交于 2019-11-29 21:21:51

I solved the problem by implementing the new UINavigationControllerDelegate Method animationControllerForOperation.

For example:

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

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

return transition;
}

PushTransition is a class that implements the UIViewControllerAnimatedTransitioning protocol and the two methods transitionDuration and animateTransition from that protocol. Additionally, i have added a property to pass the operation (tells me if it is a push or pop transition).

Just put the animation code for moving the views into the animateTransition as follows:

// 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];
                 }];

described it and you can you are done. Additionally you can make any push or pop animation you like.

I did this.

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

Do not forget re set alpha when come back.

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

I fixed it by doing this when initialising the view:

self.view.clipsToBounds = YES;

You might want to look into a new iOS7 feature that allows you to define your own custom UIViewController transitions. Look in the docs for UIViewControllerTransitioningDelegate. Also, here's a link to an article about it: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

Ah, now I understand the issue. You were right, seems to be caused by the previous UIViewController not being hidden after the transition (because of the new transition effect).

There doesn't seem to be any SDK method to control this behavior. Short of redesigning the app to not requiring the background be static, you'll probably have to roll your own navigation. OSNavigationController is a complete reimplementation of UINavigationController that might help you out. If they haven't updated to the iOS 7 transition, you'll probably be good to go. If they have you can always use an older version.

giuseppe

I had the same problem. Try to load your background image in the init method. For me, it worked (sometimes): For example:

- (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;
}

However, you could see glimpses.. The best solution I found, beside implementing the new iOS7 transition protocol, is to implement a category, and use that category whenever you need it. You can find the answer here

user3010978

Setting the image to the background color solved the issue:

self.view.backgroundColor = 
            [UIColor colorWithPatternImage:[UIImage imageNamed:@"mainback.png"]];
Eran Katsav

Take a look at the UINavigationController category in that post (it solved me problem) :

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

Props to @snoersnoer.


Here is the code in 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)
                }

            })

        }

    }

}

Cheers.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!