Nhãn đa dòng trong UIStackView


154

Khi đặt nhãn multiline (với ngắt dòng được đặt thành Word Wrap) vào chế độ xem ngăn xếp, nhãn ngay lập tức mất ngắt dòng và hiển thị văn bản nhãn trong một dòng thay thế.

Tại sao điều này xảy ra và làm thế nào để bảo quản nhãn đa dòng trong chế độ xem ngăn xếp?


1
Bạn đã đặt số lượng dòng thành 0?
dasdom

Bạn đã tìm thấy một câu trả lời?
Brenden

Câu trả lời:


204

Câu trả lời đúng là đây:
https://stackoverflow.com/a/43110590/566360


  1. Nhúng UILabelbên trong một UIView(Trình chỉnh sửa -> Nhúng vào -> Xem)
  2. Sử dụng hạn chế để phù hợp với UILabelđến UIView(ví dụ, dấu không gian, không gian hàng đầu, và không gian dẫn đến những hạn chế SuperView)

Các UIStackViewsẽ căng ra UIViewđể phù hợp đúng cách, và UIViewsẽ hạn chế UILabelđến nhiều dòng.


36
Thật là ngu ngốc nhưng nó hoạt động! Cảm ơn người đàn ông! Có thể một ngày nào đó Apple sẽ phát hành thứ gì đó không bị hỏng một nửa trong SDK của họ ...
Guillaume L.

1
Trời ơi! Bạn là một vị cứu tinh! Tôi đã ở đó hàng giờ rồi :) Hãy nhớ đặt các dòng thành 0 trong Thanh tra thuộc tính, đã bị thiếu.
absin

8
đây là cách giải quyết, giải pháp chính xác là ở đây stackoverflow.com/a/43110590/566360
vietstone

2
Đã đủ cho tôi chỉ để thay đổi hướng ngang thành trung tâm. Không UIViewcần shenanigans.
shim

1
@Lucien đây chính xác là những gì đã được nói trong câu trả lời này. nhưng câu trả lời đúng là ở đây: stackoverflow.com/a/43110590/566360
Andy

144

Đối với chế độ xem ngăn xếp ngang có một UILabeltrong các chế độ xem của nó, trước tiên, trong Trình tạo giao diện được đặt label.numberOfLines = 0. Điều này sẽ cho phép nhãn có nhiều hơn 1 dòng. Điều này ban đầu không hoạt động đối với tôi khi chế độ xem ngăn xếp có stackView.alignment = .fill. Để làm cho nó hoạt động chỉ đơn giản là thiết lập stackView.alignment = .center. Bây giờ nhãn có thể mở rộng thành nhiều dòng trong UIStackView.

Các tài liệu hướng dẫn của Apple nói

Đối với tất cả các sắp xếp ngoại trừ căn chỉnh điền, chế độ xem ngăn xếp sử dụng thuộc tính Kích thước nội dung của từng chế độ xem được sắp xếp khi tính toán kích thước của nó vuông góc với trục của ngăn xếp

Lưu ý từ trừ ở đây. Khi .fillđược sử dụng, chiều ngang UIStackViewKHÔNG thay đổi kích thước theo chiều dọc bằng cách sử dụng các kích thước xem trước được sắp xếp.


3
Đây là giải pháp thích hợp mà không cần hack. Đọc tài liệu luôn luôn được đền đáp!
Hồi giáo Q.

3
Đây phải là giải pháp được chấp nhận. Với cách giải quyết của UIView, văn bản của UILabel trôi nổi trên một khung nhìn khác trong trường hợp của tôi.

14
Nó thực sự không hoạt động ... Tôi có 3 nhãn trong stackview của mình. Tôi đã đặt các dòng thành 0 và căn chỉnh về giữa ... Tôi vẫn thấy các nhãn bị cắt ra.
MatterGoal

11
Đó là .alignmentUIStackView mà bạn phải đặt thành bất cứ thứ gì nhưng .fill không phải là UILabel, điều này hơi khó hiểu trong ví dụ đưa ra label.alignment = .center. Tôi nghĩ rằng điều này nên làstackView.alignment = .center
ae14

2
Nhưng làm thế nào tôi có thể làm cho nhiều dòng UILableView hoạt động trong StackView dọc?
DàChún

42
  • Đầu tiên đặt số nhãn của dòng thành 0
  • Chế độ xem ngăn xếp vẫn không tăng lên multiLinetrừ khi bạn cho nó một chiều rộng cố định. Khi chúng ta sửa chiều rộng của nó thì nó sẽ bị phá vỡ thành multiline khi chiều rộng đó đạt được như được hiển thị:

ghi lại màn hình

Nếu chúng ta không cung cấp chiều rộng cố định cho chế độ xem ngăn xếp thì mọi thứ sẽ trở nên mơ hồ. Chế độ xem ngăn xếp sẽ phát triển trong bao lâu với nhãn (nếu giá trị nhãn là động)?

Hy vọng điều này có thể khắc phục vấn đề của bạn.


3
Điều gì xảy ra nếu chiều rộng của chế độ xem ngăn xếp không cố định mà thay vào đó tỷ lệ thuận với chiều rộng của thiết bị (tức là giám sát).
OutOnAWeekend

Vâng, chúng ta có thể có một chiều rộng tỷ lệ quá. Vấn đề là nếu nhãn phải phá vỡ sau một số chiều rộng bất kể nó là gì nhưng cần phải được xác định.
Irfan

@AnandKumar bạn có thể chỉ định preferredMaxLayoutWidthtrong viewDidLayoutSubviewscho nhãn của bạn trong UIViewControllerhoặc layoutSubviewsnếu bạn phân lớp UIView.
Shyngys Kassymov

4
Đây phải là câu trả lời được chấp nhận, toàn bộ quan điểm của stackview là không phải thêm các ràng buộc giữa stackview và các yếu tố của nó ...
Honey

4
Đưa ra một giá trị cố định đánh bại mục đích tự động thanh toán
Hồi giáo Q.

17

Đặt ưa thíchMaxLayoutWidth cho UILabel làm việc cho tôi

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

3
Đây là câu trả lời đúng trong cuốn sách của tôi. Khi bạn gặp rắc rối với UILabel và cần xử lý nhiều dòng bạn thực sự cần cung cấp cho nó một ưu tiênMaxLayoutWidth. Nó có thể hoạt động mà không có nó, nhưng mọi thứ có thể trở nên khá sôi nổi rất nhanh nếu không có nó.
Mof

2
Tất cả đã thử tất cả các câu trả lời và tất cả chúng đều sai ngoại trừ của bạn. Cảm ơn!
Levan

Điều này đã giải quyết hoàn hảo vấn đề của tôi và cảm thấy ít hack hơn, cảm ơn bạn.
Ethan Zhao

Cảm ơn câu trả lời của bạn! Trong trường hợp của tôi, căn chỉnh của stackView đã được đặt thành .centervà tôi thực sự không cần nhãn của mình trong UIView.
Fariza Zhumat

12

Chỉ cần đặt số dòng thành 0 trong Trình kiểm tra thuộc tính cho nhãn. Nó sẽ làm việc cho bạn.

nhập mô tả hình ảnh ở đây


12
Đối với stackView dọc, bạn cần đặt Bộ phân phối thành "Điền" để làm việc này.
SnoopyProtocol

2
Đặt Phân phối thành "Điền" là chìa khóa để khắc phục.
Dylan Moore

Tôi thấy rằng đối với một UIStackView dọc, tôi phải đặt các ràng buộc trên và dưới cho một UILabel con để mở rộng và hiển thị tất cả văn bản.
bruce1337

8

Sau khi thử tất cả các gợi ý trên, tôi thấy không cần thay đổi thuộc tính nào cho UIStackView. Tôi chỉ thay đổi các thuộc tính của UILabels như sau (Các nhãn đã được thêm vào chế độ xem ngăn xếp dọc):

Ví dụ Swift 4:

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

5

Trò ảo thuật cho tôi là đặt một widthAnchorcái UIStackView.

Cài đặt leadingAnchortrailingAnchorsẽ không hoạt động, nhưng cài đặt centerXAnchorwidthAnchorlàm cho màn hình UILabel chính xác.


4

iOS 9+

Gọi [textLabel sizeToFit]sau khi cài đặt văn bản của UILabel.

sizeToFit sẽ bố trí lại nhãn multiline bằng cách sử dụng preferMaxWidth. Nhãn sẽ thay đổi kích thước stackView, sẽ thay đổi kích thước ô. Không có ràng buộc bổ sung nào ngoài việc ghim chế độ xem ngăn xếp vào chế độ xem nội dung được yêu cầu.


4

Đây là một ví dụ đầy đủ về một chiều dọc UIStackViewđược tạo thành từ các multiline UILabelvới chiều cao tự động.

Các nhãn được bọc dựa trên chiều rộng của stackview và chiều cao của stackview dựa trên chiều cao được bọc của nhãn. (Với phương pháp này, bạn không cần phải nhúng nhãn vào UIView.) (Swift 5, iOS 12.2)

nhập mô tả hình ảnh ở đây

// 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") }
}

Đây là một mẫu ViewControllersử dụng nó.

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

Thêm UIStackViewthuộc tính,

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

Thay vì thêm nhãn bên trong UIViewkhông bắt buộc. Nếu bạn đang sử dụng bên trong UITableViewCell, vui lòng tải lại dữ liệu khi xoay.


3

Sau đây là triển khai Playground của nhãn nhiều dòng với dấu ngắt dòng bên trong a UIStackView. Nó không yêu cầu nhúng UILabelbất cứ thứ gì vào bên trong và đã được thử nghiệm với Xcode 9.2 và Swift 4. Hy vọng nó hữu ích.

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

Bố cục hệ thống nên tìm ra nguồn gốc, chiều rộng và chiều cao để vẽ nó cho các cuộc phỏng vấn, trong trường hợp này, tất cả các cuộc phỏng vấn của bạn đều có cùng mức độ ưu tiên, điểm đó tạo ra xung đột, hệ thống bố cục không biết phụ thuộc giữa các chế độ xem, lần đầu tiên, thứ hai, v.v.

Đặt nén xem trước ngăn xếp sẽ giải quyết vấn đề với nhiều dòng, tùy thuộc vào chế độ xem ngăn xếp của bạn là ngang hay dọc và cái nào bạn muốn trở thành nhiều dòng. stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal) lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)


0

Trong trường hợp của tôi, tôi đã làm theo các đề xuất trước đó, nhưng văn bản của tôi vẫn bị cắt ngắn thành một dòng duy nhất mặc dù chỉ trong phong cảnh. Hóa ra, tôi tìm thấy một \0ký tự null vô hình trong văn bản của nhãn là thủ phạm. Nó phải được giới thiệu cùng với biểu tượng em dash mà tôi đã chèn. Để xem điều này cũng xảy ra trong trường hợp của bạn, hãy sử dụng Trình gỡ lỗi Xem để chọn nhãn của bạn và kiểm tra văn bản của nó.


0

Mã 9,2:

Chỉ cần đặt số dòng thành 0. Bảng phân cảnh sẽ trông lạ sau khi cài đặt này. Đừng lo lắng chạy dự án. Trong khi chạy, mọi thứ sẽ thay đổi kích thước theo thiết lập bảng phân cảnh của bạn. Tôi nghĩ rằng đó là loại lỗi trong bảng phân cảnh. nhập mô tả hình ảnh ở đây

Mẹo: Đặt "số lượng lót thành 0" cuối cùng. đặt lại nó khi bạn muốn chỉnh sửa một số chế độ xem khác và đặt thành 0 sau khi chỉnh sửa.

nhập mô tả hình ảnh ở đây


0

Những gì làm việc cho tôi!

stackview: căn chỉnh: điền, phân phối: điền, ràng buộc tỷ lệ chiều rộng để giám sát ex. 0,8

nhãn: tâm và đường = 0



0

Nó gần giống như Câu trả lời của @ Andy, nhưng bạn có thể thêm UILabelphần bổ sung UIStackview, theo chiều dọc cho tôi.


0

Đối với tôi, vấn đề là chiều cao của chế độ xem ngăn xếp đơn giản là quá ngắn. Chế độ xem nhãn và ngăn xếp được thiết lập đúng để cho phép nhãn có nhiều dòng, nhưng nhãn là nạn nhân đầu tiên của nén nội dung mà chế độ xem ngăn xếp được sử dụng để có chiều cao đủ nhỏ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.