如何在UIPageViewController中为循环图像设置动画?

时间:2018-02-12 19:39:53

标签: swift uipageviewcontroller uiviewanimation

我正在为我的应用构建演练,我遇到了一些奇怪的行为。

设置的一些上下文:在我的演练故事板中,我有一个名为TutorialViewController的视图控制器,它有一个欢迎消息,一个“教程”按钮和一个“跳过”按钮。 “教程”按钮会触发我WalkthroughViewController的segue,其中包含下一个/后退/关闭按钮以及一个UIPageIndicator浮动UIContainerView。嵌入在UIContainerView中的是WalkthroughPageViewController。最后,我有WalkthroughContentViewController个带有两个UIImageViews - contentImageViewcontentImageViewMask - 用作WalkthroughPageViewController的数据源。通过滑动或按下导航按钮,可以实例化下一个或上一个视图控制器(尽管它实际上只是重用了我的WalkthroughContentViewController)。

目标:理想情况下,我希望通过一系列图像字符串为演练的每个页面循环播放动画。例如,如果第1页包含3个图像字符串的数组,contentImageViewcontentImageViewMask将从imageArray[0] - >交替制作动画(通过Alpha值)。 imageArray[1] - > imageArray[2] - > imageArray[0] - > imageArray[1]等。

每个页面的imageArray都有不同数量的图像字符串,我还没想出如何顺利遍历所有这些图像字符串。到目前为止,我所拥有的代码在数组中的前两个图像字符串之间设置了动画,来自this answer,它位于我的WalkthroughContentViewController.swift文件中:

override func viewDidLoad() {
    super.viewDidLoad()

    contentImageViewMask.alpha = 0
    contentImageView.image = UIImage(named: imageArray[0])

    UIView.animate(withDuration: 1.5, delay: 1.5, options: [UIViewAnimationOptions.autoreverse, UIViewAnimationOptions.repeat], animations: {
        self.contentImageViewMask.image = UIImage(named: self.imageArray[1])
        self.contentImageViewMask.alpha = 1
    }, completion: nil)

}

上述类型的工作,按下教程按钮后,第1页立即设置为imageArray[1](行为不正确),而第2页在imageArray[0]imageArray[1]之间平滑动画(正确的行为)。但是,在第2页之后滑动多个页面会停用第2页上的动画。每隔一段时间,第1页将在此时开始正确动画,但我似乎无法找到一种可靠的方法来重现这一点。 Here's a video showing the behavior。我在连接UIPageIndicator和按钮操作之前拍了这个视频,所以忽略它,但奇怪的是页面2动画只通过滑动到页面来实现。如果您通过下一个按钮进入第2页,则动画无效。

可能相关的两件事:1。)在我的WalkthroughPageViewController.swift文件中,我为UIPageViewControllerDataSourceviewControllerBeforeviewControllerAfter实施了两种必需的方法,以及2 。)在我的WalkthroughPageViewController.swift文件中,我有以下代码在滑动动画结束并完整显示下一页时提醒代表:

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

    if completed {
        if let contentViewController = pageViewController.viewControllers?.first as? WalkthroughContentViewController {
            currentIndex = contentViewController.index
            walkthroughDelegate?.didUpdatePageIndex(currentIndex: contentViewController.index)
        }
    }

}

非常感谢任何见解。

2 个答案:

答案 0 :(得分:2)

在我看来,你正在与框架作斗争。如果你想要一个永久循环的自替换图像,为什么不使用那个用于此目的的UIImage功能,即animatedImage

答案 1 :(得分:0)

对于任何想要做类似但有一点额外过渡灵活性的人(比如将图像淡入下一个),this answer帮助我实现了我的动画目标,即以不同的方式在图像之间转换震动。

@IBOutlet weak var contentImageView: UIImageView!

var index = 0
let animationDuration: TimeInterval = 0.5
let switchingInterval: TimeInterval = 2.0

var imageStringArray: [String] = [""]
var images = [UIImage]()

override func viewDidLoad() {
    super.viewDidLoad()

    for string in imageStringArray {
        images.append(UIImage(named: string)!)
    }

    contentImageView.image = images[index]
    animateImageView()

}

func animateImageView() {

    CATransaction.begin()

    CATransaction.setAnimationDuration(animationDuration)
    CATransaction.setCompletionBlock {
        DispatchQueue.main.asyncAfter(deadline: .now() + self.switchingInterval) {
            self.animateImageView()
        }
    }

    let transition = CATransition()
    transition.type = kCATransitionFade

    contentImageView.layer.add(transition, forKey: kCATransition)
    contentImageView.image = images[index]

    CATransaction.commit()
    index = index < images.count - 1 ? index + 1 : 0
}

值得注意的是,该问题的原始答案表示,“将其作为自定义图像视图实现会更好。”

如果您只需要在图像之间制作动画并且转换无关紧要,那么animatedImage可能是一个更智能的解决方案(正如亚马特上面说的那样)。

    contentImageView.image = UIImage.animatedImage(with: images, duration: 3)