约束问题:sizeToFit不起作用 [英] Problems of constraints: sizeToFit doesn't work

查看:92
本文介绍了约束问题:sizeToFit不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是iOS开发的新手,我开始使用自动布局和约束.我来自Web设计,因此某些行为令我感到困惑.我正在尝试获取所有页面(以X和Y为中心)的垂直菜单. 我已经为此菜单创建了一个自定义类.目的是在需要时轻松创建任何菜单,就像这样:

I'm very new to iOS developement, I'm starting to use auto layout and constraint. I come from Web design so some behaviour are very confusing to me. I'm trying to do a vertical menu taking all the page (centered X and Y). I have made a custom class just for this menu. The goal is to create any menu easily when I need it just like that:

myMenu = MyMenu([
            MyMenu.ButtonInfo("Galerie","icon_gallery",onclick:{return}),
            MyMenu.ButtonInfo("Camera","icon_camera",onclick:{return})
]);
myMenu.show()

此代码将创建并显示一个占据所有窗口的大菜单(其后为黑色的0.5透明度布局).这基本上是我要创建的内容:

This code would create and show a big menu taking all the window (with a black 0.5-opacity layout behind it). Here is basically what I want to create:

菜单说明(图像):

Illustration of the menu (image):

我想以编程方式创建所有内容.因此,我首先创建了一个垂直UIStackView,然后向其中添加了自定义UIView(我称为菜单按钮"的自定义类.每个"MenuButtom"在左侧都是一个图标,在右侧是一个标签. 这是MenuButton自定义视图的代码

I want to create everything programmatically. Therefore, I created first a vertical UIStackView, and I add custom UIViews into it (custom class that I call "Menu button". Each "MenuButtom" is an icon on the left and a label on the right. Here is the code of the MenuButton custom view

class MenuButton: UIView {

var labelView = UILabel()
var iconView:UIImageView

public var title:String
public var icon:String
public var callback: ()->Void

init(_ title:String, _ icon:String,_ callback:@escaping ()->Void )
{
    self.title = title
    self.icon  = icon
    self.callback = callback

    self.iconView = UIImageView(image:UIImage(named: icon)!)

    super.init(frame: CGRect.zero)

    self.frame = CGRect.zero
    self.translatesAutoresizingMaskIntoConstraints = false
    self.layoutIfNeeded()

    self.addSubview(iconView)
    self.addSubview(labelView)

    iconView.translatesAutoresizingMaskIntoConstraints = false
    labelView.translatesAutoresizingMaskIntoConstraints = false
    labelView.backgroundColor = UIColor.green


    iconView.trailingAnchor.constraint(equalTo: labelView.leadingAnchor).isActive = true

    labelView.text = title
    labelView.textColor = UIColor.white

    self.backgroundColor = UIColor.purple

// self.heightAnchor.constraint(equalToConstant:50.0).isActive = true
// self.widthAnchor.constraint(equalToConstant:50.0).isActive = true

    self.layer.borderWidth = 1
    self.layer.borderColor = UIColor.red.cgColor

   // this changes nothing so i commented it .. 
   //self.sizeToFit()




}



required init(coder aDecoder: NSCoder) {
    fatalError("This class does not support NSCoding")
}
}

以下是创建stackview并将MenuButtons添加到其中的代码:

Here is the code that creates the stackview and adds the MenuButtons into it:

func show()
{
    win.addSubview(modalView)
    // code for the 0.5-opacity dark layout behind the menu : this works well 
    modalView.addGestureRecognizer(UITapGestureRecognizer(
        target:self,action : #selector(dismiss)
    ))
    self.modalView.alpha = 0
    UIView.animate(withDuration:0.2){
        self.modalView.alpha = 1
    }

    // i create the vertical stackview : 
    let parentButtons = UIStackView()
    parentButtons.translatesAutoresizingMaskIntoConstraints = false
    parentButtons.distribution = .fillEqually
    parentButtons.axis = .vertical
    parentButtons.alignment = .fill

    parentButtons.sizeToFit() // ***2*** doesnt work ...
    parentButtons.layoutIfNeeded() // ***3*** do we need to call this only once after creating the view or everytime we need it to update?

    win.addSubview(parentButtons)

    // center my uistackview in the middle of the screen
    parentButtons.centerYAnchor.constraint(equalTo: win.centerYAnchor).isActive = true
    parentButtons.centerXAnchor.constraint(equalTo: win.centerXAnchor).isActive = true


    var btn1 = MenuButton("camera", "icon_camera",{ return })
    var btn2 = MenuButton("gallery", "icon_gallery",{ return })

    parentButtons.addArrangedSubview(btn1)
    parentButtons.addArrangedSubview(btn2)

}

这是结果,完全不是我所期望的...: 结果1:

And here is the result, not at all what I expected...: Result 1:

我发现两个MenuButton实际上重叠了(我不明白为什么).然后,从逻辑上讲,我想确定MenuButton的尺寸,使其至少可以包装它包含的所有子级.我在文档中找到了魔术"方法:.sizeToFit().但是,当我在MenuButton类中取消注释self.sizeToFit时,什么也不会发生.没有紫色背景,没有红色边框(MenuButton样式) 因此,我的第一个问题是:我不明白为什么在我调用self.sizeToFit()时,菜单按钮的内容不适合标签和包含的图标之间的最大值.我想要的就像一个大的父div中的两个孩子"div"(在网络中是等效的);此处,父级会自动调整大小以完全适合其子级:

I figured out that the two MenuButton were actually overlapped (I don't understand why). Then, logically, I wanted to make the dimensions of the MenuButton such as it can wrap at least all the children it contains. I find the "magic" method in the documentation: .sizeToFit(). But, nothing happen when I uncomment self.sizeToFit in MenuButton class. No purple background and no red border (MenuButton style) So my first question is: I don't understand why the content of my menu button does not expend to fit the max between the label and the icon that it contains when I call self.sizeToFit(). What I want is just like 2 children "div" in a big parent div (equivalent in web) ; here, the parent will automatically resize to fit exactly its children:

<div class="menuButtonEquivalent">
   <div class="icon" style="float:left"><img ... /></div>
   <div class="label"> label ... </div>
</div>

然后,无论如何,我还是想通过为MenuButton设置约束来尝试解决此问题:我取消了对MenuButton类中宽度和高度的约束的注释.结果如下:

Then, I wanted anyway to try to fix the problem by setting a constraint to the MenuButton: I uncomment the constraints on the width and height in the MenuButton class. Here is the result:

具有ButtonMenu约束的结果:

Result with the constraints on ButtonMenu:

所以更好一些,但是我在这里有一个问题:为什么MenuButton X从标签而不是图标开始.为什么不把所有的孩子都包裹在里面呢?为什么只选择标签,而不是图标,或者两者都选(我想要的).

So it's a little better, but I have a question here: why does my MenuButton X start at the label and not at the icon. Why it does not wrap all the children in it? Why only the label and not only the icon or the both (what I want).

我还有另一个问题,每次创建孩子时都要强制写冗长的".translatesAutoresizingMaskIntoConstraints = false"来使用自动布局吗?

I have another third question, is it always mandatory to write the verbose ".translatesAutoresizingMaskIntoConstraints = false" every time a child is created, to use autolayout?

我尝试以编程方式而不是使用nib编辑器来做所有事情(我想在使用任何高级工具之前确切地知道一切如何工作).

I try to do everything programmatically and not using nib editor (I want to know exactly how everything works before using any higher-level tool).

推荐答案

自动布局约束背后的理论

根据iOS的快捷方式,(0,0),即x和y位于屏幕的左上角.在保持约束的同时,您必须小心,因为每个iPhone屏幕都有其自己的尺寸.为了满足这些需求,我们首先需要知道屏幕的尺寸,然后根据它来设置对齐方式.

According to the iOS swift the (0,0) i.e., x and y are at the top left corner of the screen. While keeping the constraints you must be careful becoz every iphone screen has its own dimensions. In order to meet those needs first of all we need to know the dimension of the screen and based upon that we can set the alignment.

例如:

x=50, y=50, width=z-(x+x) height=a-(y+y)

x=50, y=50, width=z-(x+x) height=a-(y+y)

a是屏幕的高度,z是屏幕的宽度

were a is the height of the screen and z is the width of the screen

在实际添加UIview然后设置约束的同时,不要忘记添加图像或任何可能的图像并为它们建立子关系.祝您编码愉快!!

While doing practically add a UIview and then set constraints don't forget to add the your images or whatever may be and give them a child relationship. HAPPY CODING!!!!

这篇关于约束问题:sizeToFit不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆