简体   繁体   English

Xcode swift 查看包装内容

[英]Xcode swift view wrap content

I'm an Android developer trying my hand at Xcode and it's been unpleasant so far.我是一名 Android 开发人员,正在尝试使用 Xcode 进行尝试,但到目前为止一直很不愉快。 What I'm trying to do is have a custom view that has three sub views:我想要做的是拥有一个包含三个子视图的自定义视图:

  • UIImageView (for an icon) UIImageView(图标)
  • UILabel (for the title) UILabel(用于标题)
  • UILabel (for the content) UILabel(用于内容)

I want it such that the content label's height grows and shrinks to wrap the text it contains (like Android's wrap_content ).我希望内容标签的高度增长和收缩以包裹它包含的文本(如 Android 的wrap_content )。 And then, I want the custom view to also grow and shrink to wrap all three sub views.然后,我希望自定义视图也可以增长和收缩以包裹所有三个子视图。

However, I cannot, for the life of me, figure out how these auto layouts/constraints work.但是,对于我的生活,我无法弄清楚这些自动布局/约束是如何工作的。

01) How would I make my UILabel's height grow/shrink to match its contained text? 01) 我如何使我的 UILabel 的高度增长/缩小以匹配其包含的文本?

02) How would I make my custom view's height grow/shrink to match its contained sub views? 02) 我如何使自定义视图的高度增大/缩小以匹配其包含的子视图?

override func layoutSubviews() {
    super.layoutSubviews()
    img_icon = UIImageView()
    txt_title = UILabel()
    txt_content = UILabel()

    img_icon.backgroundColor = Palette.white
    img_icon.image = icon
    txt_title.text = title
    txt_title.textAlignment = .Center
    txt_title.font = UIFont(name: "Roboto-Bold", size:14)
    txt_title.textColor = Palette.txt_heading1
    txt_content.text = content
    txt_content.textAlignment = .Center
    txt_content.font = UIFont(name: "Roboto-Regular", size:12)
    txt_content.textColor = Palette.txt_dark
    txt_content.numberOfLines = 0
    txt_content.preferredMaxLayoutWidth = self.frame.width
    txt_content.lineBreakMode = NSLineBreakMode.ByWordWrapping
    self.backgroundColor = Palette.white
    addSubview(img_icon)
    addSubview(txt_title)
    addSubview(txt_content)

    /*snip img_icon and txt_title constraints*/

    let txt_content_x = NSLayoutConstraint(item: txt_content, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 0)
    let txt_content_y = NSLayoutConstraint(item: txt_content, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 80)
    let txt_content_w = NSLayoutConstraint(item: txt_content, attribute: .Width, relatedBy: .Equal, toItem: self, attribute: .Width, multiplier: 1, constant: 0)
    let txt_content_h = NSLayoutConstraint(item: txt_content, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 40)
    txt_content.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activateConstraints([
        txt_content_x,
        txt_content_y,
        txt_content_w,
        txt_content_h
    ])
}

I understand that, in the above code I've tried, I have the height set to a constant 40 .我知道,在我试过的上面的代码中,我将高度设置为常量40 This is only because I don't know how to achieve what I want.这只是因为我不知道如何实现我想要的。

[EDIT] [编辑]

I've tried setting the height constraint to greater than or equal to but it just crashes Xcode.我试过将高度限制设置为大于或等于但它只是崩溃 Xcode。

[EDIT] [编辑]

It crashes Xcode if I try to view it but works perfectly fine in the simulator.如果我尝试查看它但在模拟器中运行良好,它会崩溃 Xcode。 Question now is, why ?现在的问题是,为什么

My height constraint is now:我的身高限制现在是:

let txt_content_h = NSLayoutConstraint(item: txt_content, attribute: .Height, relatedBy: .GreaterThanOrEqual, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 40)

It works in the simulator and has the desired behaviour.它在模拟器中工作并具有所需的行为。 However, if I open the storyboard that contains the view, it crashes.但是,如果我打开包含该视图的 storyboard,它就会崩溃。 It's definitely that line of code because changing it back to .Equal resolves the crash.这绝对是那行代码,因为将它改回.Equal可以解决崩溃问题。

[EDIT] [编辑]

My temporary fix is:我的临时修复是:

#if TARGET_INTERFACE_BUILDER
    //use .Equal for height constraint
#else
    //use .GreaterThanOrEqual for height constraint
#endif

This way, it doesn't crash Xcode and still renders the way I want it on the simulator.这样,它不会崩溃 Xcode 并且仍然在模拟器上呈现我想要的方式。

[EDIT] [编辑]

I removed the pre-processor check because I realized there's no actual thing like that defined and it still works now.我删除了预处理器检查,因为我意识到没有像定义的那样实际的东西,它现在仍然有效。 I swear I've changed nothing else .我发誓我没有改变其他任何东西

I am this close to giving up on iOS development because the interface builder keeps crashing Xcode without a reason when everything works in the simulator.几乎要放弃 iOS 开发,因为当模拟器中一切正常时,界面构建器会无缘无故地崩溃 Xcode。 Then, I do some nonsense edits and it works fine again.然后,我做了一些无意义的编辑,它再次正常工作。

01) How would I make my UILabel's height grow/shrink to match its contained text? 01) 如何让我的 UILabel 的高度增长/缩小以匹配其包含的文本?

Just set top, left and right-constraint to the labels superview.只需为标签超级视图设置顶部、左侧和右侧约束即可。 Set the property number of lines to 0 .将属性number of lines设置为0 Then it will start wrapping text.然后它将开始换行文本。

02) How would I make my custom view's height grow/shrink to match its contained sub views? 02) 如何让我的自定义视图的高度增长/缩小以匹配其包含的子视图?

By using interface builder this is much easier to achieve.通过使用界面构建器,这更容易实现。

My suggestion to you is to start with your constraints in storyboard.我对您的建议是从故事板中的约束开始。 You will not need to compile your code to see what the constraints will result in. Also you will get warnings and errors directly in the interface builder.您无需编译代码即可查看约束将导致什么结果。您还将直接在界面构建器中收到警告和错误。

If you WANT to use programmatic constraints, my suggestion is to start using a framework for it.如果您想使用编程约束,我的建议是开始使用它的框架。 For example: https://github.com/SnapKit/SnapKit例如: https : //github.com/SnapKit/SnapKit

当代码无缘无故卡住时,如果我没记错的话,通常 clean 会有很多好处,cmd-shift-k

You can use a trick with constraints to achieve wrap-content.您可以使用带有约束的技巧来实现 wrap-content。 For example :例如 :

let maximumWidth = frame / 4  //For example
yourView.widthAnchor.constraint(lessThanOrEqualToConstant: maximumWidth).isActive = true

The "maximumWidth" depends on your UI and your design and you can change it. “maximumWidth”取决于您的 UI 和您的设计,您可以更改它。

Also, you should set "lineBreakMode" in StoryBoard or in code like :此外,您应该在 StoryBoard 或以下代码中设置“lineBreakMode”:

yourBtn.titleLabel?.lineBreakMode = .byCharWrapping //For UIButton or
yourTxt.textContainer.lineBreakMode = .byCharWrapping //For UITextView

I understand there is no direct application of wrap content in iOS just like we have in Android and thats a big problem, I resolved it through manual anchors like this.我知道 iOS 中没有直接应用包装内容,就像我们在 Android 中一样,这是一个大问题,我通过这样的手动锚点解决了它。

create a function with where in you calculate the height of the view using创建一个 function 并在其中计算视图的高度

mainView.contentSize.height mainView.contentSize.height

and then set anchors based on the total height to the enclosing view, call this function inside然后根据总高度设置锚点到封闭视图,在里面调用这个 function

 override func viewWillLayoutSubviews()

And this would work, the viewWillLayoutSubviews() is a lifecycle method and whenever you override you have to do这会起作用, viewWillLayoutSubviews() 是一个生命周期方法,无论何时你覆盖你都必须做

super.viewWillLayoutSubviews() super.viewWillLayoutSubviews()

This worked in my case, might work with yours too, if there is a better approach please do comment.这适用于我的情况,也可能适用于您的情况,如果有更好的方法请发表评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM