เมื่อวางฉลากหลายบรรทัด (โดยมีการกำหนด linebreak เป็น Word Wrap) ในมุมมองแบบสแต็กเลเบลจะสูญเสียการจัดเรียงทันทีและแสดงข้อความฉลากในหนึ่งบรรทัดแทน
ทำไมถึงเกิดเหตุการณ์นี้ขึ้นและใครจะรักษาป้ายกำกับหลายบรรทัดในมุมมองแบบสแต็กได้อย่างไร
เมื่อวางฉลากหลายบรรทัด (โดยมีการกำหนด linebreak เป็น Word Wrap) ในมุมมองแบบสแต็กเลเบลจะสูญเสียการจัดเรียงทันทีและแสดงข้อความฉลากในหนึ่งบรรทัดแทน
ทำไมถึงเกิดเหตุการณ์นี้ขึ้นและใครจะรักษาป้ายกำกับหลายบรรทัดในมุมมองแบบสแต็กได้อย่างไร
คำตอบ:
คำตอบที่ถูกต้องอยู่ที่นี่:
https://stackoverflow.com/a/43110590/566360
UILabelข้างในUIView(ตัวแก้ไข -> ฝังใน -> มุมมอง)UILabelกับUIView(ตัวอย่างเช่นพื้นที่ต่อท้ายพื้นที่ด้านบนและพื้นที่ชั้นนำเพื่อ จำกัด การดู)UIStackViewจะยืดออกUIViewไปพอดีและUIViewจะเป็นการบังคับUILabelไปหลายบรรทัด
UIViewจำเป็นต้องใช้คนเสฉวน
สำหรับมุมมองสแต็กแนวนอนที่มีมุมมองUILabelเป็นหนึ่งในอินเทอร์เฟซตัวสร้างตั้งค่าไว้label.numberOfLines = 0ก่อน สิ่งนี้ควรอนุญาตให้ฉลากมีมากกว่า 1 บรรทัด ในขั้นต้นนี้ไม่สามารถทำงานให้ฉันได้เมื่อมุมมองสแต็stackView.alignment = .fillก stackView.alignment = .centerเพื่อให้การทำงานเพียงแค่ตั้งค่า UIStackViewฉลากในขณะนี้สามารถขยายไปยังหลายบรรทัดภายใน
เอกสารแอปเปิ้ลกล่าวว่า
สำหรับการจัดตำแหน่งทั้งหมดยกเว้นการจัดตำแหน่งการเติมมุมมองสแต็กจะใช้คุณสมบัติขนาดเนื้อหาภายในของมุมมองที่จัดเรียงแล้วเมื่อคำนวณขนาดของมันในแนวตั้งฉากกับแกนของสแต็ก
บันทึกคำยกเว้นที่นี่ เมื่อ.fillมีการใช้แนวนอนUIStackViewจะไม่ปรับขนาดตัวเองในแนวตั้งโดยใช้ขนาดการสัมภาษณ์ย่อยที่จัดเรียงไว้
.alignmentUIStackView ที่คุณต้องตั้งค่าเป็นอะไรก็ได้ แต่.fill ไม่ใช่ UILabel ซึ่งสร้างความสับสนเล็กน้อยในตัวอย่างที่ให้label.alignment = .centerมา ฉันคิดว่านี่น่าจะเป็นstackView.alignment = .center
multiLineจนกว่าคุณจะให้ความกว้างคงที่ เมื่อเรากำหนดความกว้างแล้วมันจะแบ่งเป็นหลาย ๆ เส้นเมื่อถึงความกว้างดังที่แสดง:หากเราไม่ให้ความกว้างคงที่แก่มุมมองสแต็กสิ่งต่าง ๆ ก็จะคลุมเครือ มุมมองสแต็กจะเติบโตขึ้นพร้อมกับเลเบล (ถ้าค่าเลเบลเป็นแบบไดนามิก) นานเท่าใด
หวังว่านี่จะสามารถแก้ไขปัญหาของคุณได้
preferredMaxLayoutWidthในviewDidLayoutSubviewsฉลากของคุณUIViewControllerหรือถ้าคุณซับคลาสlayoutSubviews UIView
การตั้งค่าที่ต้องการ MaxLayoutWidth เป็น UILabel ได้ผล
self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
.centerและฉันไม่ต้องการป้ายกำกับของฉันภายใน UIView
หลังจากลองข้อเสนอแนะด้านบนทั้งหมดแล้วฉันไม่พบการเปลี่ยนแปลงคุณสมบัติใด ๆ สำหรับ UIStackView ฉันเพิ่งเปลี่ยนคุณสมบัติของ UILabels ดังต่อไปนี้ (ฉลากจะถูกเพิ่มไปยังมุมมองกองซ้อนในแนวตั้งแล้ว):
ตัวอย่างของ Swift 4:
[titleLabel, subtitleLabel].forEach(){
$0.numberOfLines = 0
$0.lineBreakMode = .byWordWrapping
$0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}
เคล็ดลับที่วิเศษสำหรับผมก็คือการตั้งค่าไปwidthAnchorUIStackView
การตั้งค่าleadingAnchorและtrailingAnchorจะไม่ทำงาน แต่การตั้งค่าcenterXAnchorและwidthAnchorทำให้การแสดง UILabel ถูกต้อง
iOS 9+
โทร[textLabel sizeToFit]หลังจากตั้งค่าข้อความของ UILabel
sizeToFit จะจัดรูปแบบฉลากหลายบรรทัดใหม่โดยใช้ PreferredMaxWidth ฉลากจะปรับขนาด stackView ซึ่งจะปรับขนาดเซลล์ ไม่มีข้อ จำกัด เพิ่มเติมนอกเหนือจากการตรึงมุมมองสแต็กเข้ากับมุมมองเนื้อหา
UIStackViewสร้างจาก multiline UILabelที่มีความสูงอัตโนมัติเลเบลล้อมรอบตามความกว้างของสแต็กวิวและความสูงของสแต็กวิวขึ้นอยู่กับความสูงที่ห่อของฉลาก (ด้วยวิธีนี้คุณไม่จำเป็นต้องฝังป้ายกำกับในUIView) (Swift 5, iOS 12.2)
// A vertical stackview with multiline labels and automatic height.
class ThreeLabelStackView: UIStackView {
let label1 = UILabel()
let label2 = UILabel()
let label3 = UILabel()
init() {
super.init(frame: .zero)
self.translatesAutoresizingMaskIntoConstraints = false
self.axis = .vertical
self.distribution = .fill
self.alignment = .fill
label1.numberOfLines = 0
label2.numberOfLines = 0
label3.numberOfLines = 0
label1.lineBreakMode = .byWordWrapping
label2.lineBreakMode = .byWordWrapping
label3.lineBreakMode = .byWordWrapping
self.addArrangedSubview(label1)
self.addArrangedSubview(label2)
self.addArrangedSubview(label3)
// (Add some test data, a little spacing, and the background color
// make the labels easier to see visually.)
self.spacing = 1
label1.backgroundColor = .orange
label2.backgroundColor = .orange
label3.backgroundColor = .orange
label1.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi."
label2.text = "Hello darkness my old friend..."
label3.text = "When I wrote the following pages, or rather the bulk of them, I lived alone, in the woods, a mile from any neighbor, in a house which I had built myself, on the shore of Walden Pond, in Concord, Massachusetts, and earned my living by the labor of my hands only."
}
required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
นี่คือตัวอย่างViewControllerที่ใช้
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myLabelStackView = ThreeLabelStackView()
self.view.addSubview(myLabelStackView)
// Set stackview width to its superview.
let widthConstraint = NSLayoutConstraint(item: myLabelStackView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1, constant: 0)
self.view.addConstraints([widthConstraint])
}
}
เพิ่มUIStackViewคุณสมบัติ
stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal
แทนที่จะเพิ่มฉลากไว้ข้างในUIViewซึ่งไม่จำเป็นถ้าคุณใช้ข้างในUITableViewCellกรุณาโหลดข้อมูลซ้ำอีกครั้ง
UIStackViewต่อไปนี้จะเป็นการนำสนามเด็กเล่นของฉลากหลายคู่สายที่มีเส้นแบ่งที่อยู่ภายใน มันไม่จำเป็นต้องฝังUILabelอะไรภายในและได้รับการทดสอบด้วย Xcode 9.2 และ Swift 4 หวังว่ามันจะเป็นประโยชน์
import UIKit
import PlaygroundSupport
let containerView = UIView()
containerView.frame = CGRect.init(x: 0, y: 0, width: 400, height: 500)
containerView.backgroundColor = UIColor.white
var label = UILabel.init()
label.textColor = .black
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "This is an example of sample text that goes on for a long time. This is an example of sample text that goes on for a long time."
let stackView = UIStackView.init(arrangedSubviews: [label])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
containerView.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: containerView.widthAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: containerView.heightAnchor).isActive = true
PlaygroundPage.current.liveView = containerView
เค้าโครงระบบควรจะหาจุดเริ่มต้นความกว้างและความสูงเพื่อวาดมุมมองย่อยในกรณีนี้มุมมองย่อยทั้งหมดของคุณมีลำดับความสำคัญเท่ากันจุดนั้นทำให้เกิดความขัดแย้งระบบโครงร่างไม่รู้จักการขึ้นต่อกันระหว่างมุมมอง
ตั้งค่าการบีบอัดการสัมภาษณ์ย่อยสแต็คจะแก้ปัญหาด้วยหลายบรรทัดขึ้นอยู่กับมุมมองสแต็กของคุณเป็นแนวนอนหรือแนวตั้งและอันไหนที่คุณต้องการกลายเป็นหลายบรรทัด stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal)
lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
ในกรณีของฉันฉันทำตามคำแนะนำก่อนหน้า แต่ข้อความของฉันยังคงถูกตัดเป็นบรรทัดเดียวแม้ว่าจะอยู่ในแนวนอนเท่านั้น กลับกลายเป็นว่าฉันพบ\0ตัวละครโมฆะที่มองไม่เห็นในข้อความของป้ายกำกับซึ่งเป็นผู้ร้าย มันจะต้องมีการแนะนำข้างสัญลักษณ์ประ em ฉันได้แทรก เมื่อต้องการดูว่าสิ่งนี้เกิดขึ้นในกรณีของคุณหรือไม่ให้ใช้ดีบักเกอร์ดูเพื่อเลือกป้ายกำกับของคุณและตรวจสอบข้อความ
Xcode 9.2:
เพียงกำหนดจำนวนบรรทัดเป็น 0 สตอรีบอร์ดจะดูแปลกหลังจากตั้งค่านี้ ไม่ต้องกังวลกับการดำเนินโครงการ ในขณะที่รันทุกอย่างจะปรับขนาดตามการตั้งค่าสตอรีบอร์ดของคุณ ฉันคิดว่ามันเป็นบั๊กในกระดานเรื่องราว

เคล็ดลับ: ตั้งค่า "จำนวนซับเป็น 0" ในครั้งสุดท้าย รีเซ็ตเมื่อคุณต้องการแก้ไขมุมมองอื่นและตั้งค่าเป็น 0 หลังจากแก้ไข
อะไรที่เหมาะกับฉัน!
stackview: การจัดตำแหน่ง: เติมการกระจาย: เติมความกว้างของสัดส่วนที่ จำกัด ให้กับ superview ex 0.8
ป้ายกำกับ: กึ่งกลางและบรรทัด = 0
สำหรับผู้ที่ยังใช้งานไม่ได้ ลองตั้งค่า Autoshrink ด้วยขนาดแบบอักษรขั้นต่ำบน UILabel
มันเกือบจะเหมือน @ Andy's Answer แต่คุณสามารถเพิ่มUILabelพิเศษของคุณในUIStackviewแนวตั้งได้สำหรับฉัน
สำหรับฉันปัญหาคือความสูงของมุมมองสแต็กสั้นเกินไป มุมมองเลเบลและสแต็กถูกตั้งค่าอย่างเหมาะสมเพื่อให้เลเบลมีหลายบรรทัด แต่เลเบลเป็นเหยื่อรายแรกของการบีบอัดเนื้อหาที่สแต็กวิวใช้เพื่อทำให้ความสูงของมันเล็กพอ