ฉลากหลายบรรทัดใน UIStackView


154

เมื่อวางฉลากหลายบรรทัด (โดยมีการกำหนด linebreak เป็น Word Wrap) ในมุมมองแบบสแต็กเลเบลจะสูญเสียการจัดเรียงทันทีและแสดงข้อความฉลากในหนึ่งบรรทัดแทน

ทำไมถึงเกิดเหตุการณ์นี้ขึ้นและใครจะรักษาป้ายกำกับหลายบรรทัดในมุมมองแบบสแต็กได้อย่างไร


1
คุณตั้งค่าจำนวนบรรทัดเป็น 0 หรือไม่
dasdom

คุณพบคำตอบหรือไม่?
Brenden

คำตอบ:


204

คำตอบที่ถูกต้องอยู่ที่นี่:
https://stackoverflow.com/a/43110590/566360


  1. ฝังUILabelข้างในUIView(ตัวแก้ไข -> ฝังใน -> มุมมอง)
  2. ใช้ข้อ จำกัด เพื่อให้พอดีUILabelกับUIView(ตัวอย่างเช่นพื้นที่ต่อท้ายพื้นที่ด้านบนและพื้นที่ชั้นนำเพื่อ จำกัด การดู)

UIStackViewจะยืดออกUIViewไปพอดีและUIViewจะเป็นการบังคับUILabelไปหลายบรรทัด


36
มันช่างโง่เหลือเกิน แต่ใช้งานได้! ขอบคุณคน! บางทีวันหนึ่ง Apple จะปล่อยบางอย่างที่ไม่แตกครึ่งใน SDK ...
Guillaume L.

1
โอ้! คุณเป็นผู้กอบกู้! ฉันอยู่ที่นี่หลายชั่วโมง :) อย่าลืมตั้งค่าบรรทัดเป็น 0 ในตัวตรวจสอบคุณลักษณะ
absin

8
นี่เป็นวิธีแก้ปัญหาวิธีแก้ปัญหาที่ถูกต้องอยู่ที่นี่stackoverflow.com/a/43110590/566360
vietstone

2
ก็เพียงพอแล้วสำหรับฉันเพียงแค่เปลี่ยนการจัดตำแหน่งแนวนอนเป็นศูนย์กลาง ไม่UIViewจำเป็นต้องใช้คนเสฉวน
ชิม

1
@Lucien ตรงนี้เป็นสิ่งที่พูดในคำตอบนี้ แต่คำตอบที่ถูกต้องอยู่ที่นี่: stackoverflow.com/a/43110590/566360
Andy

144

สำหรับมุมมองสแต็กแนวนอนที่มีมุมมองUILabelเป็นหนึ่งในอินเทอร์เฟซตัวสร้างตั้งค่าไว้label.numberOfLines = 0ก่อน สิ่งนี้ควรอนุญาตให้ฉลากมีมากกว่า 1 บรรทัด ในขั้นต้นนี้ไม่สามารถทำงานให้ฉันได้เมื่อมุมมองสแต็stackView.alignment = .fillstackView.alignment = .centerเพื่อให้การทำงานเพียงแค่ตั้งค่า UIStackViewฉลากในขณะนี้สามารถขยายไปยังหลายบรรทัดภายใน

เอกสารแอปเปิ้ลกล่าวว่า

สำหรับการจัดตำแหน่งทั้งหมดยกเว้นการจัดตำแหน่งการเติมมุมมองสแต็กจะใช้คุณสมบัติขนาดเนื้อหาภายในของมุมมองที่จัดเรียงแล้วเมื่อคำนวณขนาดของมันในแนวตั้งฉากกับแกนของสแต็ก

บันทึกคำยกเว้นที่นี่ เมื่อ.fillมีการใช้แนวนอนUIStackViewจะไม่ปรับขนาดตัวเองในแนวตั้งโดยใช้ขนาดการสัมภาษณ์ย่อยที่จัดเรียงไว้


3
นี่คือทางออกที่เหมาะสมโดยไม่มีแฮ็ค การอ่านเอกสารจะจ่ายเสมอ!
ศาสนาอิสลาม Q.

3
นี่ควรเป็นทางออกที่ยอมรับได้ ด้วยการแก้ไขข้อความของ UIView UILabel ลอยข้ามมุมมองย่อยอื่นในกรณีของฉัน

14
มันใช้งานไม่ได้จริง ๆ ... ฉันมี 3 ป้ายกำกับใน stackview ของฉัน ฉันตั้งค่าบรรทัดเป็นศูนย์และจัดแนวกึ่งกลาง ... ฉันยังเห็นป้ายถูกตัดออก
MatterGoal

11
เป็น.alignmentUIStackView ที่คุณต้องตั้งค่าเป็นอะไรก็ได้ แต่.fill ไม่ใช่ UILabel ซึ่งสร้างความสับสนเล็กน้อยในตัวอย่างที่ให้label.alignment = .centerมา ฉันคิดว่านี่น่าจะเป็นstackView.alignment = .center
ae14

2
แต่ฉันจะทำให้หลายบรรทัด UILableView ทำงานในแนวตั้ง StackView ได้อย่างไร
DàChún

42
  • ก่อนอื่นให้ตั้งค่าหมายเลขป้ายกำกับของบรรทัดเป็น 0
  • มุมมองแบบสแต็กจะไม่ขยายmultiLineจนกว่าคุณจะให้ความกว้างคงที่ เมื่อเรากำหนดความกว้างแล้วมันจะแบ่งเป็นหลาย ๆ เส้นเมื่อถึงความกว้างดังที่แสดง:

บันทึกหน้าจอ

หากเราไม่ให้ความกว้างคงที่แก่มุมมองสแต็กสิ่งต่าง ๆ ก็จะคลุมเครือ มุมมองสแต็กจะเติบโตขึ้นพร้อมกับเลเบล (ถ้าค่าเลเบลเป็นแบบไดนามิก) นานเท่าใด

หวังว่านี่จะสามารถแก้ไขปัญหาของคุณได้


3
จะเกิดอะไรขึ้นถ้าความกว้างของมุมมองสแต็กไม่ได้รับการแก้ไข แต่จะเป็นสัดส่วนกับความกว้างของอุปกรณ์ (เช่นของผู้ดูแล)
OutOnAWeekend

ใช่เราสามารถมีความกว้างได้ตามสัดส่วนเช่นกัน ประเด็นคือถ้าฉลากต้องทำลายหลังจากความกว้างบางอย่างไม่ว่าจะเป็นอะไรก็ตาม แต่จำเป็นต้องกำหนด
Irfan

@AnandKumar คุณสามารถระบุpreferredMaxLayoutWidthในviewDidLayoutSubviewsฉลากของคุณUIViewControllerหรือถ้าคุณซับคลาสlayoutSubviews UIView
Shyngys Kassymov

4
นี่ควรจะเป็นคำตอบที่ได้รับการยอมรับจุดทั้งหมดของ stackview คือไม่ต้องเพิ่มข้อ จำกัด ระหว่าง stackview กับองค์ประกอบ ...
Honey

4
การให้ค่าคงที่เอาชนะวัตถุประสงค์ของการชำระอัตโนมัติ
อิสลาม Q.

17

การตั้งค่าที่ต้องการ MaxLayoutWidth เป็น UILabel ได้ผล

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;

3
นี่คือคำตอบที่ถูกต้องในหนังสือของฉัน เมื่อใดก็ตามที่คุณยุ่งกับ UILabel และต้องการจัดการกับหลายบรรทัดคุณต้องให้ MaxLayoutWidth ที่ต้องการจริงๆ มันอาจทำงานได้โดยที่ไม่มีมัน แต่สิ่งต่าง ๆ จะค่อนข้างขี้ขลาดอย่างรวดเร็วหากไม่มีมัน
กระทรวงการคลัง

2
ทุกคนลองตอบคำถามทั้งหมดและพวกเขาทั้งหมดนั้นผิดยกเว้นคุณ ขอบคุณ!
Levan

สิ่งนี้แก้ไขปัญหาของฉันได้อย่างสมบูรณ์แบบและรู้สึกแฮ็คน้อยลงขอบคุณมาก
Ethan Zhao

ขอบคุณสำหรับคำตอบ! ในกรณีของฉันการจัดตำแหน่ง stackView ของฉันถูกตั้งค่าไว้แล้ว.centerและฉันไม่ต้องการป้ายกำกับของฉันภายใน UIView
Fariza Zhumat

12

เพียงตั้งค่าจำนวนบรรทัดเป็น 0 ในตัวตรวจสอบคุณสมบัติของฉลาก มันจะทำงานสำหรับคุณ.

ป้อนคำอธิบายรูปภาพที่นี่


12
สำหรับ stackView ในแนวตั้งคุณต้องมีชุดการแจกจ่ายเป็น "เติม" เพื่อให้การทำงานนี้
SnoopyProtocol

2
การตั้งค่าการแจกจ่ายเป็น "เติม" เป็นกุญแจสำหรับการแก้ไข
Dylan Moore

ฉันพบว่าสำหรับ UIStackView แนวตั้งฉันต้องตั้งค่าข้อ จำกัด ด้านบนและด้านล่างสำหรับ UILabel เด็กเพื่อขยายและแสดงข้อความทั้งหมด
bruce1337

8

หลังจากลองข้อเสนอแนะด้านบนทั้งหมดแล้วฉันไม่พบการเปลี่ยนแปลงคุณสมบัติใด ๆ สำหรับ UIStackView ฉันเพิ่งเปลี่ยนคุณสมบัติของ UILabels ดังต่อไปนี้ (ฉลากจะถูกเพิ่มไปยังมุมมองกองซ้อนในแนวตั้งแล้ว):

ตัวอย่างของ Swift 4:

    [titleLabel, subtitleLabel].forEach(){
        $0.numberOfLines = 0
        $0.lineBreakMode = .byWordWrapping
        $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
    }

5

เคล็ดลับที่วิเศษสำหรับผมก็คือการตั้งค่าไปwidthAnchorUIStackView

การตั้งค่าleadingAnchorและtrailingAnchorจะไม่ทำงาน แต่การตั้งค่าcenterXAnchorและwidthAnchorทำให้การแสดง UILabel ถูกต้อง


4

iOS 9+

โทร[textLabel sizeToFit]หลังจากตั้งค่าข้อความของ UILabel

sizeToFit จะจัดรูปแบบฉลากหลายบรรทัดใหม่โดยใช้ PreferredMaxWidth ฉลากจะปรับขนาด stackView ซึ่งจะปรับขนาดเซลล์ ไม่มีข้อ จำกัด เพิ่มเติมนอกเหนือจากการตรึงมุมมองสแต็กเข้ากับมุมมองเนื้อหา


4

นี่คือตัวอย่างเต็มรูปแบบของแนวตั้งที่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])
    }
}

3

เพิ่มUIStackViewคุณสมบัติ

stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal

แทนที่จะเพิ่มฉลากไว้ข้างในUIViewซึ่งไม่จำเป็นถ้าคุณใช้ข้างในUITableViewCellกรุณาโหลดข้อมูลซ้ำอีกครั้ง


3

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

1

เค้าโครงระบบควรจะหาจุดเริ่มต้นความกว้างและความสูงเพื่อวาดมุมมองย่อยในกรณีนี้มุมมองย่อยทั้งหมดของคุณมีลำดับความสำคัญเท่ากันจุดนั้นทำให้เกิดความขัดแย้งระบบโครงร่างไม่รู้จักการขึ้นต่อกันระหว่างมุมมอง

ตั้งค่าการบีบอัดการสัมภาษณ์ย่อยสแต็คจะแก้ปัญหาด้วยหลายบรรทัดขึ้นอยู่กับมุมมองสแต็กของคุณเป็นแนวนอนหรือแนวตั้งและอันไหนที่คุณต้องการกลายเป็นหลายบรรทัด stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal) lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)


0

ในกรณีของฉันฉันทำตามคำแนะนำก่อนหน้า แต่ข้อความของฉันยังคงถูกตัดเป็นบรรทัดเดียวแม้ว่าจะอยู่ในแนวนอนเท่านั้น กลับกลายเป็นว่าฉันพบ\0ตัวละครโมฆะที่มองไม่เห็นในข้อความของป้ายกำกับซึ่งเป็นผู้ร้าย มันจะต้องมีการแนะนำข้างสัญลักษณ์ประ em ฉันได้แทรก เมื่อต้องการดูว่าสิ่งนี้เกิดขึ้นในกรณีของคุณหรือไม่ให้ใช้ดีบักเกอร์ดูเพื่อเลือกป้ายกำกับของคุณและตรวจสอบข้อความ


0

Xcode 9.2:

เพียงกำหนดจำนวนบรรทัดเป็น 0 สตอรีบอร์ดจะดูแปลกหลังจากตั้งค่านี้ ไม่ต้องกังวลกับการดำเนินโครงการ ในขณะที่รันทุกอย่างจะปรับขนาดตามการตั้งค่าสตอรีบอร์ดของคุณ ฉันคิดว่ามันเป็นบั๊กในกระดานเรื่องราว ป้อนคำอธิบายรูปภาพที่นี่

เคล็ดลับ: ตั้งค่า "จำนวนซับเป็น 0" ในครั้งสุดท้าย รีเซ็ตเมื่อคุณต้องการแก้ไขมุมมองอื่นและตั้งค่าเป็น 0 หลังจากแก้ไข

ป้อนคำอธิบายรูปภาพที่นี่


0

อะไรที่เหมาะกับฉัน!

stackview: การจัดตำแหน่ง: เติมการกระจาย: เติมความกว้างของสัดส่วนที่ จำกัด ให้กับ superview ex 0.8

ป้ายกำกับ: กึ่งกลางและบรรทัด = 0


0

สำหรับผู้ที่ยังใช้งานไม่ได้ ลองตั้งค่า Autoshrink ด้วยขนาดแบบอักษรขั้นต่ำบน UILabel

ภาพหน้าจอการตั้งค่า UILabel Autoshrink


ลองปรับปรุงคำตอบด้วยตัวอย่างรหัส
fridoo

1
@fridoo เพิ่มภาพหน้าจอของการตั้งค่า
Michal Mondík

0

มันเกือบจะเหมือน @ Andy's Answer แต่คุณสามารถเพิ่มUILabelพิเศษของคุณในUIStackviewแนวตั้งได้สำหรับฉัน


0

สำหรับฉันปัญหาคือความสูงของมุมมองสแต็กสั้นเกินไป มุมมองเลเบลและสแต็กถูกตั้งค่าอย่างเหมาะสมเพื่อให้เลเบลมีหลายบรรทัด แต่เลเบลเป็นเหยื่อรายแรกของการบีบอัดเนื้อหาที่สแต็กวิวใช้เพื่อทำให้ความสูงของมันเล็กพอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.