iOS Swift-基于按钮框架的位置子视图(按钮位于垂直堆栈视图内)

iOS Swift-基于按钮框架的位置子视图(按钮位于垂直堆栈视图内),swift,uiview,frame,uistackview,addsubview,Swift,Uiview,Frame,Uistackview,Addsubview,更新 在rect和主视图之间添加转换方法后,Y位置正常,但X坐标在主视图外向右移动: 下面是转换方法前后的按钮框。主视图为414 x 896。下拉菜单会以某种方式向右移动,就像附加的图像一样。 stackView btnRect中的按钮框:(120.666666,0.0,293.3333,30.0) 主视图中的按钮框:cvtRect(241.33331190.01293.3333,30.0) 视图:可选(>) 目标。我想通过在按钮下方显示带有下拉选项的UIView来创建一个下拉列表。按钮位于垂直

更新

在rect和主视图之间添加转换方法后,Y位置正常,但X坐标在主视图外向右移动: 下面是转换方法前后的按钮框。主视图为414 x 896。下拉菜单会以某种方式向右移动,就像附加的图像一样。 stackView btnRect中的按钮框:(120.666666,0.0,293.3333,30.0) 主视图中的按钮框:cvtRect(241.33331190.01293.3333,30.0) 视图:可选(>)

目标。我想通过在按钮下方显示带有下拉选项的UIView来创建一个下拉列表。按钮位于垂直堆栈视图的内部。我将带有下拉选项的TableView添加到此下拉菜单UIView。我想单击一个按钮,并使此带有TableView的UIView显示在按钮的正下方。基本上遵循本教程,除了我的按钮在垂直堆栈视图中

问题。UIView和UIView中的TableView在单击按钮时显示ok。问题在于下拉菜单UIView的位置始终是同一原点X=120,Y=0

我就是这样做的:

  • 我有4行的垂直堆栈
  • 在第四行,我有一个标签(宽度=120,几乎与上面的X坐标相同)和一个触发UIView显示的按钮
  • 我使用按钮来显示下拉列表(基本上是UIView),当点击按钮时,应该出现在按钮的正下方,但它总是出现在原点x=120 Y=0处,基本上固定在垂直堆栈视图中右列的顶部。垂直堆栈视图的第一列带有标签,第二列带有按钮等不同控件
  • 要成功制作下拉列表,我需要UIView显示在按钮框(X、Y、宽度、高度)的正下方。但是,尽管按钮位于第四行,这应该是具有更高Y值的位置,但按钮帧始终位于X=120,Y=0,因此我的UIView始终固定在按钮上方的该位置,该按钮应模拟下拉菜单 问题 1.下拉视图的定位缺少什么?当按钮位于垂直堆栈视图的第4行时,为什么按钮的位置Y=0,Y位置明显更高?我还试图简单地将这个下拉列表放在屏幕中央,但这也不起作用

    2.我从web开发领域过渡到iOS开发,在我的职业生涯中,我经常使用下拉菜单。我应该改用Picker视图吗?还是警觉?在Swift应用程序中,向用户提供互斥选项列表的最常见和最标准的方式是什么


    非常感谢

    您的按钮是stackView的子视图,因此它的框架相对于stackView的框架

    要在视图的坐标空间中获取其帧(rect),需要使用
    .convert
    。将此操作分配给stackView中的一个按钮:

    编辑修复了代码示例。。。我在发帖之前没有检查过

    class ConvertViewController: UIViewController {
    
        @IBOutlet var dropDownView: UIView!
    
        @IBAction func didTap(_ sender: Any) {
            guard let btn = sender as? UIButton else {
                fatalError("Sender is not a button!")
            }
            guard let sv = btn.superview as? UIStackView else {
                fatalError("Sender is not in a stackView!")
            }
    
            let btnRect = btn.frame
            let cvtRect = sv.convert(btn.frame, to: view)
            print("button frame in stackView:", btnRect)
            print("button frame in main view:", cvtRect)
    
            let dropDownRect = dropDownView.bounds
            let cvtCenterX = cvtRect.origin.x + (cvtRect.size.width / 2.0)
            let viewX = cvtCenterX - (dropDownRect.width / 2.0)
            let newOrigin = CGPoint(x: viewX, y: cvtRect.minY + cvtRect.height)
            dropDownView.frame.origin = newOrigin
    
        }
    
    }
    
    如果查看调试控制台中的输出,您应该会看到如下内容:

    button frame in stackView: (0.0, 114.0, 46.0, 30.0)
    button frame in main view: (164.5, 489.5, 46.0, 30.0)
    
    如您所见,我的stackView中第四个按钮的矩形(框架)的原点为
    0.0、114.0
    ,但将其转换到我的
    视图
    坐标空间后,矩形的原点为
    164.5489.5

    现在,您可以相对于转换的rect定位“下拉列表”


    作为旁注,您可能想看看
    uipopopresentationcontroller

    非常感谢,这很有帮助,我现在非常接近了。我添加了let btnRect=btn.frame和let cvtRect=btn.convert(btn.frame,to:view)。现在我在正确的Y位置,只是X坐标现在关闭了。btnRect:(120.666666,0.0和之后。转换cvtRect(241.33331190.0,因此此X=241使下拉列表位于视图之外,即:视图:可选(同样感谢您的建议,PopoverPresentationController看起来很棒,我将来会使用它。我仍然对上面的视图、子视图和帧坐标感兴趣:-)使它们移动的是按钮的左边缘。
    x=241
    。您可以对
    x
    位置执行任何计算…例如,如果您想要“下拉列表”,请执行视图要在按钮下方居中,您可能会得到转换的矩形的中心:
    让cvtCenterX=cvtRect.origin.x+(cvtRect.size.width/2.0)
    然后使用
    让视图x=cvtCenterX-(dropDownView.size.width/2.0)定位视图
    @Bosniak-对不起……我没有测试就输入了那个代码。我更新了我的答案——现在应该是准确的了。
    button frame in stackView: (0.0, 114.0, 46.0, 30.0)
    button frame in main view: (164.5, 489.5, 46.0, 30.0)