更改背景图像时容器视图动画无法正常工作

Container View animations not working properly when changing out a background image

我在 IB 中有 3 个视图。 View One(1) 有一个视图和一个 UIImage,我将其用作此 ViewController 的背景。视图二(2)(详细信息视图)和视图三(3)(选项视图)是容器视图,两者都放置在彼此之上。我在 View 2 中有一个按钮,它使 View 2 向左移动并从右侧移动 View 3。我可以从 View 3 向右移动并从左侧返回 View 2。

我的文档大纲如下所示:

White BG,只是标题栏下面的背景,以防万一有人想知道。

这是我用来制作这些动画的代码:

func showOptions(){
    println("show options")

    optionsView.center.x = self.view.bounds.width + self.view.bounds.width / 2
    optionsView.hidden = false

    UIView.animateWithDuration(0.5, animations: {

        self.blurView.alpha = 1

        // slide containers around
        // println(self.view.bounds.width)

        self.detailsView.center.x = -self.view.bounds.width * 2
        self.optionsView.center.x = self.view.bounds.width / 2
    })
}
func showDetails(){
    println("show detials")

     optionsView.center.x = self.view.bounds.width / 2

    UIView.animateWithDuration(0.5, animations: {

        self.blurView.alpha = 0

        // slide containers around
        // println(self.view.bounds.width)

        self.detailsView.center.x = self.view.bounds.width / 2
        println("\(self.optionsView.center.x) this is center X value 1")

        self.optionsView.center.x = self.view.bounds.width * 2
        println("\(self.optionsView.center.x) this is center X value 2")

    }, completion: {
            (value: Bool) in
            println("\(self.optionsView.center.x) this is center X value 3")
    })
}

那些对我从打印语句中得到什么感到好奇的人

当我不尝试更改背景照片并且事情像这样工作时,我应该得到这个:

当我更改照片时,我得到这些值:

当我尝试更改此视图控制器的背景视图图像时不起作用。

let par3 = UIImage(named: "par3.png")
backgroundImage.image = par3
   // println("par three")
    showDetails()

当我更改背景照片时,视图 2 和视图 3 都从左侧动画到屏幕上。我只是不确定为什么。是否与切换出背景图片时修改View Controller的宽度有关?

感谢您的帮助!

感觉你对 Auto Layout 还只是半信半疑。您最初使用它来布置您的视图,但是当您为视图设置动画时您没有使用它。您正在修改中心 x 位置,这是旧的动画方式。它有点工作,但后来我认为当你换掉背景图像时,一切都被重置为你的初始约束,因为这会导致在引擎盖下调用 layoutIfNeeded() ,它使用约束将所有东西重新定位最初是。

您无需修改​​视图的中心 x 位置,而是需要更改修改约束的方法。这意味着即使你换掉图像,你的约束仍然是准确的,一切都应该按预期工作。这需要以特定方式设置约束,我将尝试演示。

首先,我设置了一个带有几个子视图控制器的父视图控制器。每个子项都有一个按钮,可以调用父项中的委托方法。

我的故事板是这样的:

检查员长这样:

关于故事板设置的几点:

  • 我有一个主容器视图,它是父视图的子视图。这个主容器视图将 clipSubviews 设置为 YES,这样当我们左右移动视图时,它们不会出现在主容器的边界之外。
  • 选项和详细容器视图都设置了约束以匹配主容器视图的宽度和高度。
  • 详细信息容器视图的左侧设置为紧靠选项容器视图的右侧,即 [选项][详细信息]。它们并不直接重叠。
  • 详细容器视图有一个约束,因此它的顶边与选项容器视图的顶边对齐。
  • 选项容器视图设置了约束,与主容器视图的左上角对齐。这与前面的 2 个项目符号相结合意味着最初详细信息容器视图位于屏幕右侧。我在父视图控制器中引用了约束,该约束将选项容器视图的左侧与 mainContainerView 的左侧(在上面的屏幕截图中选择的那个)对齐,这就是我用来为所有内容设置动画的方法.

这是父 class 的样子:

class ParentViewController: UIViewController, OptionsViewControllerDelegate, DetailViewControllerDelegate {

    struct Constants {
        static let optionsEmbedSegue = "optionsEmbedSegue"
        static let detailEmbedSegue = "detailEmbedSegue"
    }

    @IBOutlet weak var mainContainerView: UIView!

    @IBOutlet weak var optionsLeadingSpaceConstraint: NSLayoutConstraint!

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == Constants.optionsEmbedSegue {
            let childViewController = segue.destinationViewController as OptionsViewController
            childViewController.delegate = self
        } else if segue.identifier == Constants.detailEmbedSegue {
            let childViewController = segue.destinationViewController as DetailViewController
            childViewController.delegate = self
        }
    }

    func optionsViewControllerDidSelectToShowDetail(optionsViewController: OptionsViewController) {
        animateOptionsToNewXPosition(-CGRectGetWidth(mainContainerView.bounds))
    }

    func detailViewControllerDidSelectToGoBack(detailViewController: DetailViewController) {
        animateOptionsToNewXPosition(0)
    }

    func animateOptionsToNewXPosition(xPosition: CGFloat) {
        optionsLeadingSpaceConstraint.constant = xPosition

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.mainContainerView.layoutIfNeeded()
        })
    }
}

如果您查看 optionsViewControllerDidSelectToShowDetail 方法,您会看到行 animateOptionsToNewXPosition(-CGRectGetWidth(mainContainerView.bounds))。这是将选项视图控制器向左移动主容器视图的宽度。这意味着它会消失在屏幕的左侧,并且由于所有其他约束,它会拖动详细视图控制器,在 mainContainerView 中显示详细视图控制器。相反的情况发生在 detailViewControllerDidSelectToGoBack 方法中,只需将该约束中的常量设置回 0,这会将选项视图控制器带回,并将 detailViewController 推到右侧。

希望对您有所帮助。