Home > Software engineering >  How to automatically grow SwiftUI MacOS TableColumn to fix the text
How to automatically grow SwiftUI MacOS TableColumn to fix the text

Time:07-18

I have a table as follows:

var body: some View {
    Table(logs, selection: $selectedLine, sortOrder: $sortOrder) {
        TableColumn("timestamp", value: \.timestamp) {
            Text("\($0.timestamp.formatted(date: .abbreviated, time: .standard))")
        }
        TableColumn("device", value: \.level)
        TableColumn("message", value: \.message)
    }
    .onChange(of: sortOrder) {
        logs.sort(using: $0)
    }
}

Right now the table defaults to splitting each of the columns equally, but I would like it to set the column to fix the size of the data within.

timestamp and device are tiny compared to message, which often needs to scroll scroll to view it all.

How can I make it so that timestamp and device will shrink, and message will grow even if it means scroll would be required? Is it even possible?

CodePudding user response:

Use .width() on the Table columns:

        Table(logs) {
            TableColumn("timestamp") { log in
                Text(log.timestamp.formatted(date: .omitted , time: .standard))
            }
            .width(100)
            TableColumn("device", value: \.level)
                .width(50)
            TableColumn("message", value: \.message)
        }

and if you want to size according to content you can use GeometryReader like this:

    @State private var colWidth: CGFloat = 100
    
    var body: some View {
        Table(logs) {
            TableColumn("timestamp") { log in
                Text(log.timestamp.formatted(date: .omitted , time: .standard))
                    .overlay( GeometryReader { geo in Color.clear.onAppear { colWidth = geo.size.width }})
            }
            .width(min: colWidth, max: colWidth)

Edit: set max, but still be able to shrink

    @State private var colWidth1: CGFloat?
    @State private var colWidth2: CGFloat?

    var body: some View {
        Table(logs) {
            TableColumn("timestamp") { log in
                Text(log.timestamp.formatted(date: .omitted , time: .standard))
                    .overlay( GeometryReader { geo in Color.clear.onAppear { colWidth1 = max(colWidth1 ?? 0, geo.size.width) }})
            }
            .width(ideal: colWidth1, max: colWidth1)
            
            TableColumn("device") { log in
                Text(log.level)
                    .overlay( GeometryReader { geo in Color.clear.onAppear { colWidth2 = max(colWidth2 ?? 0, geo.size.width) }})
            }
            .width(ideal: colWidth2, max: colWidth2)

            TableColumn("message", value: \.message)
                .width(ideal: 200, max: .infinity)
        }
    }
  • Related