【问题标题】:Animating View jumps to final position instead of slow movement动画视图跳转到最终位置而不是缓慢移动
【发布时间】:2017-04-21 12:05:57
【问题描述】:

我正在制作包含 ImageView 和 Label 的视图动画。 请参见图 1。当在 tableView 上滚动完成时,我正在尝试为 upperView 设置动画。最终的结果应该如图 2 所示。其中 imageView 的高度和宽度减小了,并且位于左角,并且在 imageView 前面具有最小高度和标签。动画工作正常,imageView 从原始位置顺利到达最终位置,Label 也是如此。但是根据动画,upperView 不起作用。

我尝试了使用 upperViews 高度约束和框架。

  1. 如果我用它的高度约束来改变它,它会很快到达它的最终位置。

  2. 如果我使用 upperView.frame.size.height 给出高度,那么视图会上升,但表格视图仍保留在原位。

这是我尝试过的

func scrollViewDidScroll(scrollView: UIScrollView) {
  if scrollView.contentOffset.y > 0
        {
         UIView.animateWithDuration(1.5, delay: 0.0, options: .CurveEaseOut, animations:
                    {
                        self.imageView.frame = CGRect(x: 5.0, y: 0.0, width: 30, height: 40)

                    }, completion: { finished in
                        UIView.animateWithDuration(1.5, delay: 1.0, options: UIViewAnimationOptions.AllowUserInteraction,animations: {

                            self.selectedProgramNameLabel.center = CGPoint(x: self.selectedProgramNameLabel.center.x, y: self.imageView.center.y)

                            }, completion: { finished in
                                UIView.animateWithDuration(1.5, delay: 2.0, options: UIViewAnimationOptions.AllowUserInteraction, animations: {

                              self.upperViewHeightConstraint.constant = 50

                                    }, completion: { finished in

                                })
                        })
                })
        }
        else if scrollView.contentOffset.y == 0
        {
          UIView.animateWithDuration(1.5, delay: 0.0, options: .CurveEaseOut, animations:
                {
                    self.selectedProgramNameLabel.center = CGPoint(x: self.selectedProgramNameLabel.center.x, y: self.imageView.center.y + self.imageView.frame.height - 45)


                }, completion: { finished in
                    UIView.animateWithDuration(1.5, delay: 0.0, options: UIViewAnimationOptions.AllowUserInteraction,animations: {

                        self.imageView.frame = CGRect(x: self.upperView.frame.origin.x, y: self.upperView.frame.origin.y, width: 100.0, height: 134)


                        }, completion: { finished in
                            UIView.animateWithDuration(1.5, delay: 1.0, options: UIViewAnimationOptions.AllowUserInteraction, animations: {


                                }, completion: { finished in


                            })
                    })
            })

       }

TIA。

图 1。 图 2。

【问题讨论】:

    标签: ios iphone swift swift2.3


    【解决方案1】:

    在为任何布局约束设置动画时,如果您想要想要的动画效果,必须在动画块中使用layoutIfNeeded。所以只需在动画块中添加这个。

    self.view.layoutIfNeeded()
    self.upperViewHeightConstraint.constant = 50
    

    还可以使用任何标志来检查视图是否已动画化,否则您的动画块将执行多次。

    【讨论】:

    • 我之前尝试过 self.view.layoutIfNeeded() ,但它的作用仍然相同。跳转到最终位置。
    • 你的动画块被执行了多次,让它们动画一次。
    • 是的,我让它执行一次,但它仍然没有动画。它跳了:(
    • 你是说上视图没有动画对吧?
    • 是的,伙计。它直接跳转到高度 50
    【解决方案2】:

    尝试使用:UIViewAnimationOptions.beginFromCurrentState、CABasicAnimation。 How to animate the frame of an layer with CABasicAnimation?

    这不是你要找的东西,但我希望它能帮助你。

    var cntTopViewT: NSLayoutConstraint!
    var cntTopViewH: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
        navigationController?.navigationBar.shadowImage = UIImage()
        navigationController?.navigationBar.isTranslucent = true
    
        let scrollView = UIScrollView()
        scrollView.delegate = self
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
    
        let topView = UIView()
        topView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(topView)
    
        let topViewBackgroundImageView = UIImageView()
        topViewBackgroundImageView.translatesAutoresizingMaskIntoConstraints = false
        topView.addSubview(topViewBackgroundImageView)
    
        let bottomView = UIView()
        bottomView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.insertSubview(bottomView, at: 0)
    
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        bottomView.addSubview(v)
    
    
        let views: [String: Any] = ["view": view,
                                    "scrollView": scrollView,
                                    "topView": topView,
                                    "topViewBackgroundImageView": topViewBackgroundImageView,
                                    "bottomView": bottomView,
                                    "v": v]
        var cnts: [NSLayoutConstraint] = []
    
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: nil, views: views)
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: [], metrics: nil, views: views)
    
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:[topView(scrollView)]", options: [], metrics: nil, views: views)
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:[scrollView]-0@1-[topView]", options: [.alignAllCenterX], metrics: nil, views: views)
        cntTopViewT = NSLayoutConstraint(item: topView, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1, constant: 0)
        cntTopViewH = NSLayoutConstraint(item: topView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 0)
        cnts += [cntTopViewT, cntTopViewH]
    
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:|[topViewBackgroundImageView]|", options: [], metrics: nil, views: views)
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[topViewBackgroundImageView]|", options: [], metrics: nil, views: views)
    
        cnts += [NSLayoutConstraint(item: bottomView, attribute: .width, relatedBy: .equal, toItem: scrollView, attribute: .width, multiplier: 0.9, constant: 0)]
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:[scrollView]-0@1-[bottomView]|", options: [.alignAllCenterX], metrics: nil, views: views)
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[bottomView(999)]|", options: [], metrics: nil, views: views)
    
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:|[v(50)]", options: [], metrics: nil, views: views)
        cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[v(50)]", options: [], metrics: nil, views: views)
    
        NSLayoutConstraint.activate(cnts)
    
        topView.backgroundColor = .red
        bottomView.backgroundColor = .green
        v.backgroundColor = .blue
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let minH = (navigationController?.navigationBar.frame.height ?? 0) + UIApplication.shared.statusBarFrame.height
        let maxH = view.frame.height * 0.35
    
        cntTopViewT.constant = scrollView.contentOffset.y
        cntTopViewH.constant = max(-scrollView.contentOffset.y, minH)
        scrollView.contentInset.top = maxH
        scrollView.scrollIndicatorInsets.top = (cntTopViewH.constant - minH) + (minH * ((cntTopViewH.constant - minH) / (maxH - minH))) + 5
    
        //let kTransform = min(max(cntTopViewH.constant / maxH + 0.1, 0.5), 1)
        //topViewFioLabel.transform = CGAffineTransform(a: kTransform, b: 0, c: 0, d: kTransform, tx: 0, ty: 0)
    }
    

    【讨论】:

    • 谢谢你的回答,但我以前试过这个。这只有在表格视图上有足够的数据可以滚动时才有效,否则我的 imageView 和标签会卡在它们之间,看起来很丑陋。因此必须使用 UIAnimation 以便即使表上的数据较少,它也会移动到目的地。但是,当我制作动画时,upperView 高度约束没有移动,它像子弹一样移动,这是不可接受的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 2016-09-17
    相关资源
    最近更新 更多