在实现自定义转换后,在返回导航控件堆栈视图时,视图为黑色

时间:2018-05-18 10:31:25

标签: ios uinavigationcontroller swift4

我有一个包含元素列表的tableview。当我在桌面视图中点击一个单元格时,我试图实现到detailview的缩放过渡。 过渡按预期工作 - 但当我按下"返回"时,我被带到黑视图。

我是处理自定义过渡的新手,所以也许我缺少了一些东西 - 我只是不确定是什么。我按照这篇文章:https://blog.rocketinsights.com/how-to-create-a-navigation-transition-like-the-apple-news-app/进行缩放转换,并将代码转换为Swift 4。

这是我的zoomtransition类:

class ZoomTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {

    private let duration: TimeInterval = 0.5
    var operation: UINavigationControllerOperation = .push
    var thumbnailFrame = CGRect.zero

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let presenting = operation == .push

        // Determine which is the master view and which is the detail view that we're navigating to and from. The container view will house the views for transition animation.
        let containerView = transitionContext.containerView
        guard let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) else { return }
        guard let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from) else { return }
        let storyFeedView = presenting ? fromView : toView
        let storyDetailView = presenting ? toView : fromView

        // Determine the starting frame of the detail view for the animation. When we're presenting, the detail view will grow out of the thumbnail frame. When we're dismissing, the detail view will shrink back into that same thumbnail frame.
        var initialFrame = presenting ? thumbnailFrame : storyDetailView.frame
        let finalFrame = presenting ? storyDetailView.frame : thumbnailFrame

        // Resize the detail view to fit within the thumbnail's frame at the beginning of the push animation and at the end of the pop animation while maintaining it's inherent aspect ratio.
        let initialFrameAspectRatio = initialFrame.width / initialFrame.height
        let storyDetailAspectRatio = storyDetailView.frame.width / storyDetailView.frame.height
        if initialFrameAspectRatio > storyDetailAspectRatio {
            initialFrame.size = CGSize(width: initialFrame.height * storyDetailAspectRatio, height: initialFrame.height)
        }
        else {
            initialFrame.size = CGSize(width: initialFrame.width, height: initialFrame.width / storyDetailAspectRatio)
        }

        let finalFrameAspectRatio = finalFrame.width / finalFrame.height
        var resizedFinalFrame = finalFrame
        if finalFrameAspectRatio > storyDetailAspectRatio {
            resizedFinalFrame.size = CGSize(width: finalFrame.height * storyDetailAspectRatio, height: finalFrame.height)
        }
        else {
            resizedFinalFrame.size = CGSize(width: finalFrame.width, height: finalFrame.width / storyDetailAspectRatio)
        }

        // Determine how much the detail view needs to grow or shrink.
        let scaleFactor = resizedFinalFrame.width / initialFrame.width
        let growScaleFactor = presenting ? scaleFactor: 1/scaleFactor
        let shrinkScaleFactor = 1/growScaleFactor

        if presenting {
            // Shrink the detail view for the initial frame. The detail view will be scaled to CGAffineTransformIdentity below.
            storyDetailView.transform = CGAffineTransform(scaleX: shrinkScaleFactor, y: shrinkScaleFactor)
            storyDetailView.center = CGPoint(x: thumbnailFrame.midX, y: thumbnailFrame.midY)
            storyDetailView.clipsToBounds = true
        }

        // Set the initial state of the alpha for the master and detail views so that we can fade them in and out during the animation.
        storyDetailView.alpha = presenting ? 0 : 1
        storyFeedView.alpha = presenting ? 1 : 0

        // Add the view that we're transitioning to to the container view that houses the animation.
        containerView.addSubview(toView)
        containerView.bringSubview(toFront: storyDetailView)

        // Animate the transition.
        UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 1.0, options: [.curveEaseInOut], animations: {
            // Fade the master and detail views in and out.
            storyDetailView.alpha = presenting ? 1 : 0
            storyFeedView.alpha = presenting ? 0 : 1

            if presenting {
                // Scale the master view in parallel with the detail view (which will grow to its inherent size). The translation gives the appearance that the anchor point for the zoom is the center of the thumbnail frame.
                let scale = CGAffineTransform(scaleX: growScaleFactor, y: growScaleFactor)
                let translate = storyFeedView.transform.translatedBy(x: storyFeedView.frame.midX - self.thumbnailFrame.midX, y: storyFeedView.frame.midY - self.thumbnailFrame.midY)
                storyFeedView.transform = translate.concatenating(scale)
                storyDetailView.transform = .identity
            }
            else {
                // Return the master view to its inherent size and position and shrink the detail view.
                storyFeedView.transform = .identity
                storyDetailView.transform = CGAffineTransform(scaleX: shrinkScaleFactor, y: shrinkScaleFactor)
            }

            // Move the detail view to the final frame position.
            storyDetailView.center = CGPoint(x: finalFrame.midX, y: finalFrame.midY)
        }) { finished in
            transitionContext.completeTransition(finished)
        }
    }

}

在我的主视图控制器中,我使用以下代码实现了UINavigationControllerDelegate:

extension SearchVC: UINavigationControllerDelegate {

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

            //Pass the thumbnail frame to the transition animator.
            guard let transitionThumbnail = transitionThumbnail, let transitionThumbnailSuperview = transitionThumbnail.superview else { return nil }

            thumbnailZoomTransitionAnimator = ZoomTransitionAnimator()
            thumbnailZoomTransitionAnimator?.thumbnailFrame = transitionThumbnailSuperview.convert(transitionThumbnail.frame, to: nil)
        }
        thumbnailZoomTransitionAnimator?.operation = operation

        return thumbnailZoomTransitionAnimator
    }

}

最后在桌面视图中点击一个单元格时,这是我的代码:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)

    let cell = tableView.cellForRow(at: indexPath as IndexPath) as? MovieTableViewCell
    transitionThumbnail = cell?.movieImageView

    self.performSegue(withIdentifier: "searchToDetails", sender: indexPath.row)
}

我的segue将数据发送到详细信息视图中,以及#34;准备segue" -method。

任何人都可以解释/帮助我出错了吗? :-)只有在返回时才会提到,视图变黑了。

enter image description here

1 个答案:

答案 0 :(得分:0)

我认为您需要在动画完成后设置演示以便能够处理切换。

    { finished in
        transitionContext.completeTransition(finished)
        presenting = !presenting
    }