【问题标题】:Subviews frame not updating after view.center commandview.center 命令后子视图框架未更新
【发布时间】:2020-02-21 21:56:07
【问题描述】:

我拥有的是这些不同的视图,如图所示:主视图是container,里面有boxSentence,里面有boxSentence,里面有subView,里面有subView带有灰色框boxWord 的不同文本标签。然后是另一个视图boxAnswer,这是我创建的一个可拖动元素,只能放在boxWord 内(我将boxWord 传递给boxAnswer 的自定义类以检查他的位置(框架) )。

在这种情况下一切正常,boxAnswer 只能放置 盒子里面的字

然后为了调整整个视图的图形,我想把我的subView 和他所有的实际子视图放在boxSentence 的中心。为此,我使用了subView.center = boxSentence.center,得到了我想要的。

现在,当我尝试将boxAnswer 拖放到boxWord 的新位置时,问题就来了,它不起作用,但是如果我尝试将它拖放到boxWord 的位置,然后再移动它到中心它确实有效。

似乎当您执行subView.center = boxSentence.center 时,它只会影响subView 的框架,但不会影响其子视图的框架。有关如何解决问题的任何建议?

代码:

// creo box dove inserire la frase
let boxSentence = UIView(frame: CGRect(x: 0, y: 0, width: container.frame.width, height: container.frame.height/2))
container.addSubview(boxSentence)
boxSentence.backgroundColor = hexStringToUIColor(hex: "#49eb34")

let subView = UIView(frame: CGRect(x: 0, y: 0, width: container.frame.width, height: 70))


let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
label1.text = esercizio.ctsex![0].first_sentence
label1.backgroundColor = UIColor.yellow
label1.sizeToFit()

let boxWord = UIView(frame: CGRect(x: label1.frame.maxX, y: 0, width: 100, height: 60))
boxWord.backgroundColor = UIColor.gray

let label2 = UILabel(frame: CGRect(x: boxWord.frame.maxX, y: 0, width: 100, height: 100))
label2.text = esercizio.ctsex![0].second_sentence
label2.backgroundColor = UIColor.yellow
label2.sizeToFit()

subView.addSubview(label1)
subView.addSubview(boxWord)
subView.addSubview(label2)
subView.backgroundColor = UIColor.purple
boxSentence.addSubview(sottoView)
subView.frame = CGRect(x: 0, y: 0, width: label2.frame.maxX-label1.frame.minX, height: 80)
subView.center = boxSentence.center


let coordrisposta = CGRect(x: boxFrase.frame.minX, y: boxFrase.frame.maxY, width: 80.0, height: 40.0)
let boxAnswer = DragObject(frame: coordrisposta, vistap: boxWord)
boxAnswer.backgroundColor = UIColor.red

container.addSubview(rispostaBox)

CLASS DragObject OF boxAnser:

import UIKit

// CLASSE CHE CREA UNA VISTA CHE PUO ESSERE SPOSTATA SOLO ALL'INTERNO DI UNA VISTA PASSATA DA PARAMETRO

class DragObject: UIView {

    var vista: UIView
    var initcoord: CGRect

    init(frame: CGRect, vistap: UIView){
        self.vista = vistap
        self.initcoord = frame
        super.init(frame: frame)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touch began")
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
       var touch : UITouch! = touches.first as UITouch?
       self.center = touch.location(in: self.superview)        
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        var coorv = vista.frame
        print(coorv)

        let coord1 = (touches.first?.location(in: self.superview))!
        let destinazione1 = CGPoint(x: coorv.minX, y: coorv.minY)
        let destinazione2 = CGPoint(x: coorv.maxX, y: coorv.maxY)

        if coord1.x > destinazione1.x && coord1.y > destinazione1.y && coord1.x < destinazione2.x && coord1.y < destinazione2.y {
            print("OK")
            self.frame = vista.frame
        } else {
            print("fuori")
            self.frame = initcoord
        }
    }
}

【问题讨论】:

    标签: ios swift uiview coordinates cgrect


    【解决方案1】:

    UIView 的框架是相对于其父边界的坐标(UIView 的内部坐标系,即该视图的子视图的坐标系)。 例如我们有 2 个视图的 UIViewController:

    let redView = UIView()
    redView.backgroundColor = .red
    redView.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
    self.view.addSubview(redView)
    
    let greenView = UIView()
    greenView.backgroundColor = .green
    greenView.frame = CGRect(x: 25, y:25, width:50, height: 50)
    redView.addSubview(greenView)
    
    print(redView.frame)
    /*
    (20.0, 20.0, 100.0, 100.0)
    redView is placed self.view.bounds.origin.x + 20 and self.view.bounds.origin.y + 20
    */
    print(greenView.frame)
    /*
    (25.0, 25.0, 50.0, 50.0)
    green is placed redView.bounds.origin.x + 25 and redView.bounds.origin.y + 25
    */
    print(redView.convert(greenView.frame, to: self.view))
    /*
    (45.0, 45.0, 50.0, 50.0)
    converted frame of greenView from redViews bounds to of self.view bounds.
    */
    
    

    所以 DragObject 内部的问题是,您传递的框架和视图坐标反映了它们相对于子视图视图原点的位置。 同时 DragObject 是容器视图的子视图,当您收到触摸坐标时,您将获得相对于容器视图的坐标。
    您可以通过将 vista.frame 转换为 DragObject 超级视图坐标系来修复它。 这是 DragObject 中覆盖 func touchesEnded(_ touches: Set, with event: UIEvent?) 的完整代码

    var coorv = vista.superview!.convert(vista.frame, to: self.superview!)
    print(coorv)
    
    let coord1 = (touches.first?.location(in: self.superview))!
    let destinazione1 = CGPoint(x: coorv.minX, y: coorv.minY)
    let destinazione2 = CGPoint(x: coorv.maxX, y: coorv.maxY)
    
    if coord1.x > destinazione1.x && coord1.y > destinazione1.y && coord1.x < destinazione2.x && coord1.y < destinazione2.y {
        print("OK")
        self.frame = coorv
    } else {
        print("fuori")
        self.frame = initcoord
    }
    

    【讨论】:

    • 哦,好吧,我明白了,不同的坐标与不同的超级视图相关。非常清楚和详尽的谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-09-19
    • 2015-05-04
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    相关资源
    最近更新 更多