动画视图跳转到最终位置而不是缓慢移动
Posted
技术标签:
【中文标题】动画视图跳转到最终位置而不是缓慢移动【英文标题】: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 高度约束和框架。
如果我用它的高度约束来改变它,它会很快到达它的最终位置。
如果我使用 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。
【问题讨论】:
【参考方案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 高度约束没有移动,它像子弹一样移动,这是不可接受的。以上是关于动画视图跳转到最终位置而不是缓慢移动的主要内容,如果未能解决你的问题,请参考以下文章
使用 javascript 暂停 CSS 动画并跳转到动画中的特定位置
动画 UIView 帧更改而不移动动画(即位置之间的交叉溶解)