เมื่อวางฉลากหลายบรรทัด (โดยมีการกำหนด 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
จะไม่ปรับขนาดตัวเองในแนวตั้งโดยใช้ขนาดการสัมภาษณ์ย่อยที่จัดเรียงไว้
.alignment
UIStackView ที่คุณต้องตั้งค่าเป็นอะไรก็ได้ แต่.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)
}
เคล็ดลับที่วิเศษสำหรับผมก็คือการตั้งค่าไปwidthAnchor
UIStackView
การตั้งค่า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
แนวตั้งได้สำหรับฉัน
สำหรับฉันปัญหาคือความสูงของมุมมองสแต็กสั้นเกินไป มุมมองเลเบลและสแต็กถูกตั้งค่าอย่างเหมาะสมเพื่อให้เลเบลมีหลายบรรทัด แต่เลเบลเป็นเหยื่อรายแรกของการบีบอัดเนื้อหาที่สแต็กวิวใช้เพื่อทำให้ความสูงของมันเล็กพอ