【问题标题】:ios 7 view with transparent content overlaps previous view具有透明内容的 ios 7 视图与以前的视图重叠
【发布时间】:2013-09-23 18:08:06
【问题描述】:

最近我更新了我的 xcode 项目以使用 iOS 7,但我遇到了一个大问题。因为我的整个应用程序只有一个背景图片(UIImageView添加到关键窗口)并且所有视图都是透明的,所以我在推送UIViewController时遇到了一个问题,因为推送的视图控制器与之前的视图重叠(您可以在图片中看到它:http://grab.by/qp0k )。我可以预测这是因为在 iOS 7 中推送过渡已经改变,因为现在它滑动了半个屏幕。也许有人知道如何解决这个问题?

这就是我设置关键窗口的方式

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

【问题讨论】:

  • 你能添加你用来设置关键窗口和第一个视图控制器的代码吗?
  • @Kevin 更新了我的问题!
  • @Edvardas 你在保持单一图像背景的同时解决了这个问题吗?我也有同样的问题。
  • @Edvardas,我也在寻找解决方案

标签: uinavigationcontroller ios7 pushviewcontroller xcode5


【解决方案1】:

@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)
                }

            })

        }

    }

}

干杯。

【讨论】:

  • 这个怎么用?
【解决方案2】:

我在初始化视图时通过这样做来修复它:

self.view.clipsToBounds = YES;

【讨论】:

  • 这对我也有用,谢谢。知道它为什么起作用吗?
  • @AlexTerreaux 实际上不知道。
【解决方案3】:

我通过实现新的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 的类。此外,我添加了一个属性来传递操作(告诉我它是推送还是弹出转换)。

只需将移动视图的动画代码放入 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];
                 }];

描述了它,你就完成了。此外,您可以制作任何您喜欢的推送或弹出动画。

【讨论】:

  • 您所说的“将视图移动到 animateTransition 方法中的动画代码,如 JX2 所述”在哪里?
  • 请看更新。我为你添加了一些代码。
  • 我认为不需要为动画创建快照视图。为什么不直接为真实视图制作动画?
  • 如果我没记错的话,可以在动画完成之前与 UIViewController 的 UI 元素进行交互。
  • @snoersnoer 如果是这种情况,您可以将 userInteractionEnabled 设置为 false 直到调用完成
【解决方案4】:

将图像设置为背景色解决了这个问题:

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

【讨论】:

    【解决方案5】:

    我遇到了同样的问题。尝试在 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 转换协议之外,我发现的最佳解决方案是实现一个类别,并在需要时使用该类别。 你可以找到答案here

    【讨论】:

      【解决方案6】:

      看看那篇文章中的 UINavigationController 类别(它解决了我的问题):

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

      【讨论】:

        【解决方案7】:

        您可能想研究一个新的 iOS7 功能,该功能允许您定义自己的自定义 UIViewController 转换。在文档中查找 UIViewControllerTransitioningDelegate。另外,这里有一篇关于它的文章的链接:http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

        【讨论】:

          【解决方案8】:

          我这样做了。

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

          回来的时候别忘了重新设置alpha。

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

          【讨论】:

          • 这对导航回以前的 ViewController 有一些影响,但不适用于导航到新的 ViewController。旧 VC 的 -viewWillDisappear:-viewWillAppear: 在导航到新的时不会被调用。
          • 当导航回上一个VC时,可以看到另一个VC一秒钟
          • 您的第一条评论很奇怪,但是:“当导航回上一个 VC 时,可以看到另一个 VC”不幸的是正确的......如果有人有更好的解决方案,应该是有帮助。
          • - (void)viewWillAppear:(BOOL)animated { self.tableView.alpha = 1.0; } - (void)viewWillDisappear:(BOOL)animated { [UIView animateWithDuration:0.3 animations:^(){ self.tableView.alpha = 0.0; }]; }
          • 这是解决问题的最简单方法。苹果在透明背景视图上没有做出好的过渡是荒谬的!
          【解决方案9】:

          啊,现在我明白了这个问题。你说得对,好像是之前的 UIViewController 在转场后没有隐藏造成的(因为新的转场效果)。

          似乎没有任何 SDK 方法可以控制此行为。如果不重新设计应用程序以不要求背景是静态的,您可能必须滚动自己的导航。 OSNavigationController 是对 UINavigationController 的完全重新实现,可能会对您有所帮助。如果他们还没有更新到 iOS 7 过渡,你可能会很高兴。如果有,您可以随时使用旧版本。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-04
            • 1970-01-01
            • 1970-01-01
            • 2013-09-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-29
            相关资源
            最近更新 更多