在做项目的过程中突然遇到要在keywindow上添加一个全屏View来实现一个ViewController从底部present出来的一个效果,当然只是把View添加到keywindow上很简单,但我现在布局用的是自动布局,这个动画就不好实现了。
我突然想到了用SnapKit这个自动布局库来实现一下试试,经历了好几个版本的实验都以失败而告终,不是没有动画就是动画效果不对,总结了一下失败的原因主要有两个,如下:
– 使用动画的方法不对,代码如下
UIView.animate(withDuration: 0.5, animations: { [weak self] in
self.mRootView.snp.updateConstraints {[weak self] (make) in
guard let aSelf = self else { return }
make.bottom.equalTo(aSelf).offset(0)
}
}) { (complete) in
}
只是简单调用了一下在UIView的Animation的block里边,这样完全没有效果的。
- 布局的初始化做的不到位
只进行了初始化,让整个View移动到底部不可见,代码如下
mRootView.snp.updateConstraints {[weak self] (make) in
let height = UIScreen.main.bounds.size.height
make.height.equalTo(height)
guard let aSelf = self else { return }
make.bottom.equalTo(aSelf.snp.bottom).offset(height)
}
这样做完全不够,我们需要对UI强制刷新,应该调用
self.layoutIfNeeded() //对View的初始化进行强制刷新
然而上边第一个问题,我们用下面代码来解决
self.mRootView.snp.updateConstraints {[weak self] (make) in
guard let aSelf = self else { return }
make.bottom.equalTo(aSelf).offset(0)
}
UIView.animate(withDuration: 0.5, animations: { [weak self] in
self?.layoutIfNeeded()
}) { (complete) in
}
这种写法就是把动画SnapKit操作View的代码放到UIView的Animation Block外部,然后强制刷新UI的代码放到UIView的动画block内部这样动画效果就出来了,完整的代码如下:
func show()
{
UIApplication.shared.keyWindow?.addSubview(self)
mRootView.snp.updateConstraints {[weak self] (make) in
let height = UIScreen.main.bounds.size.height
make.height.equalTo(height)
guard let aSelf = self else { return }
make.bottom.equalTo(aSelf.snp.bottom).offset(height)
}
self.layoutIfNeeded()
self.mRootView.snp.updateConstraints {[weak self] (make) in
guard let aSelf = self else { return }
make.bottom.equalTo(aSelf).offset(0)
}
UIView.animate(withDuration: 0.5, animations: { [weak self] in
self?.layoutIfNeeded()
}) { (complete) in
}
}
注意在xib里边做View(动画容器)的约束的时候一定要定义正确了,做底部向上滑动的动画需要只定义左右距离父View的间距,底部距父View的间距,还有动画容器的高度,千万不能做顶部对父容器的间距。只要遵循我给出方式动画就能完美出来了,其他方向动画同理,希望这篇文档对你帮助!
昨天我又遇到写类似动画的功能,写的过程中发现了动画怎么也不出来,后来经过排查发现是因为调用动画的地方是写在了容器类的初始化方法里,当时容器类还没有加到window上所有造成动画没有表现出来,所以得出结论就是动画View在动画之前一定要确保它已经被显示到屏幕上了
animation跟snapkit的block不需要弱引用