Swift:更改UIView帧但显示不更新

时间:2016-06-07 14:29:52

标签: ios swift uiview uiimageview frame

我试图动态调整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(),也没有任何变化。

帮助?感谢。

3 个答案:

答案 0 :(得分:3)

首先,您有一些值得注意的错误:

  • 实例变量(例如VUBarCoverMainView应始终以小写字母开头(如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更新在动画中进行)。