视图是黑色的,当返回到导航控制器堆栈视图时,在实现自定义转换后

Posted

技术标签:

【中文标题】视图是黑色的,当返回到导航控制器堆栈视图时,在实现自定义转换后【英文标题】:View is black, when going back in the navigationcontrollers stack of views, after implementing custom transition 【发布时间】:2018-05-18 10:31:25 【问题描述】:

我有一个包含元素列表的表格视图。在点击表格视图中的单元格时,我尝试实现到详细视图的缩放转换。 过渡按预期工作 - 但是当我按“返回”时,我被带到一个黑色视图。

我是使用自定义过渡的新手,所以也许我缺少一些东西 - 我只是不确定是什么。我按照这篇文章: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 以“prepare for segue”方法将数据发送到详细视图。

谁能解释/帮助我出了什么问题? :-) 只有在返回时才提到,视图变黑了。

【问题讨论】:

您的问题解决了吗?我有完全一样的...... 我找到了解决方案,代码在这里:***.com/questions/51617051/… 【参考方案1】:

我认为您需要在动画完成后设置呈现才能处理切换。

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

【讨论】:

那没有任何区别 :/ 但我想,问题是,当我回去的时候,主视图被缩小了..所以它实际上变得越来越小时间我去细节和回来..我只是不知道在哪里编辑主视图的收缩:/

以上是关于视图是黑色的,当返回到导航控制器堆栈视图时,在实现自定义转换后的主要内容,如果未能解决你的问题,请参考以下文章

如何实现“向右拖动以关闭”导航堆栈中的视图控制器?

iOS在导航堆栈中的视图控制器之间循环

如何从堆栈中弹出视图控制器而不导航到它们

以模态方式呈现视图控制器时,导航栏与黑色而不是白色混合

当视图控制器弹出或推入导航控制器堆栈时如何获得通知

将带有可见导航栏的视图控制器弹出到带有隐藏导航栏的视图控制器时,带有 interactivePopGestureRecognizer 的黑色区域