【问题标题】:Set UIView frame equal to the frame of another view from a different superview将 UIView 框架设置为等于来自不同父视图的另一个视图的框架
【发布时间】:2019-11-24 21:45:34
【问题描述】:

我正在创建位于不同超级视图中的 UIView,但我想将框架设置为彼此相等。

这是我迄今为止尝试过的

let globalPoint = self.view.convert(subViewOfOuterView.frame.origin, to: nil)
let frame = CGRect(x: globalPoint.x, y: globalPoint.y, width: self.subViewOfOuterView.frame.width, height: self.subViewOfOuterView.frame.height)
subViewOfInnerUIView.frame = frame

但我的观点最终看起来像这样

【问题讨论】:

  • 不要乱用框架。使用自动布局。只要 OuterUIView 和 InnerUIView 在链的某处有一个共同的超级视图,您就可以简单地将两个视图的边缘相互约束
  • @Paulw11 我正在使用帧,因为我正在制作动画
  • 好的,但是您可以使用约束设置动画。
  • @Paulw11 如何使用自动布局解决这个问题
  • 正如我所说,假设两个视图在层次结构中的某处有一个共享的父级,您只需将一个视图的前导锚约束到另一个视图。与顶部、底部和尾随锚点相同

标签: ios swift frame


【解决方案1】:

使用您提供的对象名称,这是一个创建第二个视图的示例,也是一个 UIButton (subViewOfInnerUIView),它将与第一个按钮 (drawButton) 具有相同的框架。这两个按钮都是主视图中不同超级视图的子视图。我使用了一个 UIButton,因此我可以标记视图,但任何其他可以设置框架的 UIView 子类也可以工作。

请注意,由于它们具有相同的帧,除了具有相同的大小之外,它们相对于其父视图的位置也相同。

即使有问题的对象位于几层深或浅的子视图中,这也应该有效。应该没关系。

可以在最新 XCode 的单一视图游乐场中重新创建该示例。希望这会有所帮助!

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white
        self.view = view

        let subView1 = UIView(frame: CGRect(x: 40, y: 250, width: 300, height: 300))
        subView1.backgroundColor = .red
        view.addSubview(subView1)

        let subView2 = UIView(frame: CGRect(x: 20, y: 50, width: 340, height: 100))
        subView2.backgroundColor = .green
        view.addSubview(subView2)

        let drawButton = UIButton(frame: CGRect(x: subView1.frame.width / 2 - 50, y: 25, width: 150, height: 50))
        drawButton.backgroundColor = .blue
        drawButton.setTitle("DRAW BTN", for: .normal)
        subView1.addSubview(drawButton)

        let subViewOfInnerUIView = UIButton()
        subViewOfInnerUIView.setTitle("DRAW BTN2", for: .normal)
        subViewOfInnerUIView.backgroundColor = .brown
        subView2.addSubview(subViewOfInnerUIView)

        let frame = view.convert(drawButton.frame, to: nil)
        subViewOfInnerUIView.frame = frame
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

这是使两个视图重叠的更新代码。我对更改进行了动画处理,因此很清楚,并且还评论了特定的框架以尝试解释它是如何完成的:

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white
        self.view = view

        let subView1 = UIView(frame: CGRect(x: 40, y: 250, width: 300, height: 300))
        subView1.backgroundColor = .red
        view.addSubview(subView1)

        let subView2 = UIView(frame: CGRect(x: 20, y: 50, width: 340, height: 100))
        subView2.backgroundColor = .green
        view.addSubview(subView2)

        let drawButton = UIButton(frame: CGRect(x: subView1.frame.width / 2 - 50, y: 25, width: 150, height: 50))
        drawButton.backgroundColor = .blue
        drawButton.setTitle("DRAW BTN", for: .normal)
        subView1.addSubview(drawButton)

        let subViewOfInnerUIView = UIButton()
        subViewOfInnerUIView.setTitle("DRAW BTN2", for: .normal)
        subViewOfInnerUIView.backgroundColor = .brown
        subView2.addSubview(subViewOfInnerUIView)

        let frame1 = drawButton.frame
        let frame2 = subView1.convert(drawButton.frame, to: view)
        let frame3 = view.convert(frame2, to: subView2)

        print(frame1) // original drawButton frame in its superview
        print(frame2) // drawButton frame relative to the main view (self.view)
        print(frame3) // drawButton frame relative to subView2 (this is the frame you want)

        subViewOfInnerUIView.frame = view.convert(drawButton.frame, to: nil)

        UIView.animate(withDuration: 5.0, delay: 0.0, options: [.autoreverse, .repeat], animations: {
            subViewOfInnerUIView.frame = frame3
        }, completion: nil)

        subViewOfInnerUIView.frame = frame3


    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

将 subViewOfInnerUIView.frame 设置为 frame3 的最后一行基本上就是你想要的。您可能可以创建一个函数来完成这 3 行的工作以使其更容易(将 2 个子视图作为参数),尽管如果视图层次结构很深,它可能不会那么简单:

    let frame2 = subView1.convert(drawButton.frame, to: view)
    let frame3 = view.convert(frame2, to: subView2)
    subViewOfInnerUIView.frame = view.convert(drawButton.frame, to: nil)

希望这会有所帮助!

【讨论】:

  • 我发布了您解决方案的输出,两个按钮不重叠
  • @Sam 我认为输出是您想要的效果。让我看看,让按钮重叠。应该是快速编辑。
  • @Sam 我已经更新了我的答案。希望这是您想要的行为:)
  • 所以一切都可以解决这个问题,但在我的实际程序中,只有在应用程序启动时才能使帧数相等。这是一张描述它的图片imgur.com/a/oB20OFI,这是我在 github 上的项目github.com/stackoverflowsam93/set。这只会在应用程序启动时发生,甚至不会在新游戏启动时发生。我做这里讨论的东西的代码在 ViewController 的第 120 和 131 行
  • 严格来说,这个问题与其他问题有关,主要是当应用启动和单击 newGame 时,您的视图和变量的状态不同。我通过在此方法中复制您的代码解决了您的问题:@IBAction func newGame(_ sender: UIButton) 并将其移动到 viewDidAppear,以在有人单击 newGame 时复制您的应用程序的状态,而该错误不会发生。我还删除了 viewDidLoad 中的 updateViewFromModel 调用。我还注意到,在 didLoad 和 didAppear 中,一些与视图的框架和位置相关的属性不同,这就是我将代码放在后者中的原因。
猜你喜欢
  • 1970-01-01
  • 2019-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多