我试图动态调整UIView的框架。我可以更新代码中的帧并查看值已更改,但实际显示永远不会更改,即使我运行setNeedsDisplay()。
我跟随this post,我通过CGRectMake定义一个新帧,然后将UIView的帧设置为这个新帧。也就是说,我这样做......
co(function *() {
let errors = yield someCheck(process.argv);
if (!errors) {
console.log('Ok');
} else {
console.log('Bad');
}
})(function(e) {
if (e) {
console.log(e);
}
});
如果我打印出UIView框架的价值,我会发现它随着我的喜好而改变。但显示(在模拟器中)从不反映这些变化。
知道如何解决这个问题吗?
更新:更详细:我尝试以编程方式掩盖一个UIView与另一个UIView。它是一个水平的" VU Meter",由显示颜色渐变的基础UIImageView组成,部分动态地覆盖"覆盖"由具有黑色背景的UIView。 UIImageView" VUBarImageView"在StoryBoard中定义,并受AutoLayout的约束。黑色UIView" VUBarCover"纯粹以编程方式定义,没有AutoLayout约束。
以下是完整性代码的相关部分......我遇到的问题是在updateVUMeter()......
let newFrame = CGRectMake(minX,minY, width, height)
VUBarCover.frame = newFrame
样本结果如下:
@IBOutlet weak var VUBarImageView: UIImageView!
var VUBarCover : UIView!
// this gets called after AutoLayout is finished
override func viewDidLayoutSubviews() {
// cover up VU Meter completely
let center = VUBarImageView.center
let width = VUBarImageView.frame.width
let height = VUBarImageView.frame.height
let frame = VUBarImageView.frame
VUBarCover = UIView(frame: frame)
MainView.addSubview(VUBarCover)
VUBarCover.backgroundColor = UIColor.blueColor() // use black eventually. blue lets us see it for testing
}
// partially cover up VUBarImage with black VUBarCover coming from the "right"
func updateVUMeter(inputValue:Float) { //inputValue is in dB
//let val = pow(10.0,inputValue/10) // convert from dB
let val = Float( Double(arc4random())/Double(UInt32.max) ) //for Simulator testing, just use random numbers between 0 and 1
print("val = ",val)
let fullWidth = VUBarImageView.frame.width
let maxX = VUBarImageView.frame.maxX
let width = fullWidth * CGFloat(1.0-val)
let minX = maxX - width
let minY = VUBarImageView.frame.minY
let height = VUBarImageView.frame.height
let newFrame = CGRectMake(minX,minY, width, height)
VUBarCover.frame = newFrame
VUBarCover.setNeedsDisplay()
print("fullWidth = ",fullWidth,"width = ",width)
print(" newFrame = ",newFrame,"VUBarCover.frame = ",VUBarCover.frame)
}
...即,我们看到VUBarCover.frame正在内部改变,但在屏幕上它永远不会改变。我们所看到的是全尺寸封面,完全覆盖下面的图像(约300像素宽),即使它的宽度应该只有大约12个像素)。
即使我在VUBarCover的超级视图上执行setNeedsDisplay(),也没有任何变化。
帮助?感谢。
答案 0 :(得分:3)
首先,您有一些值得注意的错误:
VUBarCover
和MainView
应始终以小写字母开头(如mainView
)。super.viewDidLayoutSubviews()
其次,viewDidLayoutSubviews()
可以被调用任意次,因此你对这个方法的实现应该是幂等,这意味着它无论被调用多少次都具有相同的效果。但是当你打电话时:
VUBarCover = UIView(frame: frame)
MainView.addSubview(VUBarCover)
您正在创建 new UIView
并将其添加到视图层次结构中,以及您过去可能添加的其他内容。所以它看起来就像帧没有在屏幕上更新一样。实际上,您无法分辨,因为旧视图位于您正在更新的视图后面,它们没有更改。
相反,您可能想要创建一次:
var vuBarCover = UIView()
将其添加为viewDidLoad()
中的子视图:
mainView.addSubview(vuBarCover)
并在viewDidLayoutSubviews()
中修改其框架:
vuBarCover.frame = vuBarImageView.frame
您无需致电setNeedsDisplay()
。
答案 1 :(得分:1)
我正在制作一个像你一样的自定义UIView,也许我可以提供帮助。
首先, viewDidLayoutSubviews()就像你的评论一样:在AutoLayout完成后调用它。在完成每个布局设置之后,你开始为你的UIView和UIImage设置新的框架,也许bug就在这里。请尝试将viewDidLayoutSubviews()中的代码移动到 layoutSubviews()。并且不要忘记在覆盖功能中添加super.layoutSubviews(),它可以帮助您远离数百个错误:]。
其次,只有当你覆盖 drawRect:方法时,才应该调用 setNeedsDisplay(),这告诉系统我需要重绘我的视图和系统将适当地调用drawRect:方法。
希望你能搞清楚。
答案 2 :(得分:1)
在我的情况下,图层上还剩下动画,删除它们后,更新了帧更改:
myView.layer.removeAllAnimations()
iOS在屏幕上显示presentationLayer
中的UIView
,动画在该层上播放(frame
更新在动画中进行)。