我正在尝试为视图中的子视图的帧更改设置动画。在动画块中,我将子视图的大小设置为原始宽度和高度的一半。但是,当我运行代码时,子视图意外地以更大的尺寸开始并缩小到其原始大小,而不是原始大小的一半。我使用下面的代码:
我的自定义视图:
import UIKit
class TestView: UIView {
var testSubview: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.yellow
testSubview = UIView(frame: .zero)
testSubview.backgroundColor = UIColor.red
addSubview(testSubview)
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
testSubview.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
}
func testAnimate() {
UIView.animate(withDuration: 3, delay: 0, options: [], animations: { [unowned self] in
self.testSubview.bounds.size = CGSize(width: 50, height: 50)
}, completion: nil)
}
}
我的视图控制器:
import UIKit
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let testView = TestView()
view.addSubview(testView)
testView.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
testView.center = view.center
testView.layoutIfNeeded()
testView.testAnimate()
}
}
我做错了吗?
答案 0 :(得分:1)
问题是您的视图布局了两次,您可以通过在layoutSubviews()中打印调试消息来检查。
我会建议像这样的东西,设置一个大小变量并在layoutSubviews()和testAnimate()中使用它:
class TestView: UIView {
var testSubview: UIView!
var mySize = CGSize(width: 100, height: 100)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.yellow
testSubview = UIView(frame: .zero)
testSubview.backgroundColor = UIColor.red
addSubview(testSubview)
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
testSubview.frame = CGRect(x: 0, y: 0, width: mySize.width, height: mySize.height)
}
func testAnimate() {
UIView.animate(withDuration: 3, delay: 0, options: [], animations: { [unowned self] in
self.mySize = CGSize(width: 50, height: 50)
self.testSubview.bounds.size = self.mySize
}, completion: nil)
}
}
答案 1 :(得分:0)
编辑:重新制定我的整个答案,因为我觉得有很多事情应该在这里改变。
首先设置视图边界与框架之间的区别。
let view = UIView()
view.frame = CGRect(x: 0, y: 0, width: 200, height: 200) // This will set the position and size this view will take relative to it's future parents view
view.bounds = CGRect(x: 50, y: 50, width: 100, height: 100) // This will set position and size of it's own content (i.e. it's background) relative to it's own view
然后是你的testView类变量。除非您确定变量不会为零,否则不要使用UIView!
作为输入,否则您最终会错过一些初始化程序,因此您的课程将无法一致地工作。
将init方法视为变量的默认值,然后您可以简单地更改它们。
import UIKit
class TestView: UIView {
var testSubview: UIView
override init(frame: CGRect) {
// Initialise your variables before calling super
testSubview = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
testSubview.backgroundColor = UIColor.red
super.init(frame: frame)
// Once super is called you can start using class methods or variable such as addSubview or backgroundColor
backgroundColor = UIColor.yellow
addSubview(testSubview)
}
required init?(coder aDecoder: NSCoder) {
testSubview = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
testSubview.backgroundColor = UIColor.blue
super.init(coder: aDecoder)
backgroundColor = UIColor.yellow
addSubview(testSubview)
}
}
现在终于到了动画部分
import UIKit
class TestView: UIView {
var testSubview: UIView
func testAnimation() {
UIView.animate(withDuration: 3, animations: {
self.testSubview.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) // Simply make the view half its size over 3 seconds
}) { (_) in
UIView.animate(withDuration: 3, animations: {
self.testSubview.transform = CGAffineTransform(scaleX: 1, y: 1) // Upon completion, resize the view back to it's original size
})
}
}
}
或者如果你真的想用CGRect在它的位置做动画
import UIKit
class TestView: UIView {
var testSubview: UIView
func testAnimation() {
UIView.animate(withDuration: 3, animations: {
self.testSubview.frame = CGRect(x: 0, y: 0, width: 50, height: 50) // use frame not bounds to resize and reposition the frame
}) { (_) in
UIView.animate(withDuration: 3, animations: {
self.testSubview.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
})
}
}
}
您可以测试更改bounds属性的效果
import UIKit
class ViewController: UIViewController {
var testView: TestView!
override func viewDidLoad() {
testView = TestView(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 200)))
testView.bounds = CGRect(x: 50, y: 50, width: 100, height: 100)
testView.clipsToBounds = true
view.addSubview(testView)
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
testView.testAnimation()
}
}
只需使用clipsToBounds
,testView.bounds
,testView.subView.frame
和testView = TestView(frame: CGRect(x:y:width:height)
即可查看所有内容