NB: This question concerns only macOS, not iOS
I have a large, 30-column Table
that scrolls both vertically and horizontally on macOS.
When a user changes the width of a column in SwiftUI's Table
by dragging, other columns shrink as much as possible before the framework adjusts the width of the entire table. (In the image above, expanding the "Label" column has squished the other columns.)
How do I tell Table
that it should preserve all column widths and, when one column is resized, it should simply make the entire table wider or narrower as necessary?
For Sweeper
Here's a Table
that produces the behavior. You'll obviously have to provide your own KeyPaths
. Note the presence of Group
(to allow more than 10 columns, even though only 9 columns are present here) and the TableStyle
modifier.
var body: some View
{
Table(cues, sortOrder: $sortOrder)
{
Group
{
TableColumn("", value: \SheetCue.associatedMasterCue!.notesCount) { cue in
Text("Blah")
}
.width(min: 18, max: 18)
TableColumn("Title", value: \SheetCue.associatedMasterCue!.title) { cue in
Text("Blah")
}
.width(min: 80, ideal: 250, max: 2000)
TableColumn("Artist", value: \SheetCue.associatedMasterCue!.artist) { cue in
Text("Blah")
}
.width(min: 40, ideal: 200, max: 2000)
TableColumn("Album", value: \SheetCue.associatedMasterCue!.album) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Composer/Writer", value: \SheetCue.associatedMasterCue!poser) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
}
Group
{
TableColumn("Label", value: \SheetCue.associatedMasterCue!.label) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Publisher", value: \SheetCue.associatedMasterCue!.publisher) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Contact", value: \SheetCue.associatedMasterCue!.contactInfo) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Uses", value: \SheetCue.numberOfUses) { cue in
Text(String(cue.numberOfUses.formatted()))
}
.width(min: 30, ideal: 40, max: 80)
}
}
.onChange(of: sortOrder) { _, sortOrder in
cues.sort(using: sortOrder)
}
.tableStyle(.bordered)
}
NB: This question concerns only macOS, not iOS
I have a large, 30-column Table
that scrolls both vertically and horizontally on macOS.
When a user changes the width of a column in SwiftUI's Table
by dragging, other columns shrink as much as possible before the framework adjusts the width of the entire table. (In the image above, expanding the "Label" column has squished the other columns.)
How do I tell Table
that it should preserve all column widths and, when one column is resized, it should simply make the entire table wider or narrower as necessary?
For Sweeper
Here's a Table
that produces the behavior. You'll obviously have to provide your own KeyPaths
. Note the presence of Group
(to allow more than 10 columns, even though only 9 columns are present here) and the TableStyle
modifier.
var body: some View
{
Table(cues, sortOrder: $sortOrder)
{
Group
{
TableColumn("", value: \SheetCue.associatedMasterCue!.notesCount) { cue in
Text("Blah")
}
.width(min: 18, max: 18)
TableColumn("Title", value: \SheetCue.associatedMasterCue!.title) { cue in
Text("Blah")
}
.width(min: 80, ideal: 250, max: 2000)
TableColumn("Artist", value: \SheetCue.associatedMasterCue!.artist) { cue in
Text("Blah")
}
.width(min: 40, ideal: 200, max: 2000)
TableColumn("Album", value: \SheetCue.associatedMasterCue!.album) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Composer/Writer", value: \SheetCue.associatedMasterCue!poser) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
}
Group
{
TableColumn("Label", value: \SheetCue.associatedMasterCue!.label) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Publisher", value: \SheetCue.associatedMasterCue!.publisher) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Contact", value: \SheetCue.associatedMasterCue!.contactInfo) { cue in
Text("Blah")
}
.width(min: 40, ideal: 160, max: 2000)
TableColumn("Uses", value: \SheetCue.numberOfUses) { cue in
Text(String(cue.numberOfUses.formatted()))
}
.width(min: 30, ideal: 40, max: 80)
}
}
.onChange(of: sortOrder) { _, sortOrder in
cues.sort(using: sortOrder)
}
.tableStyle(.bordered)
}
Share
Improve this question
edited Mar 19 at 21:09
Bryan
asked Mar 19 at 18:53
BryanBryan
5,8374 gold badges46 silver badges81 bronze badges
5
|
1 Answer
Reset to default 0A Workaround
I've discovered a hacky workaround that sort-of solves this problem:
Suppose your
Table
starts at 800 points wide. (The view that contains theTable
has a width of 800.)As long as you set the
.width(min:ideal:max:)
modifiers on yourTableColumns
such that it's NOT POSSIBLE for SwiftUI to squeeze them all into that 800 width, the Framework seems to automatically switch to AppKit'slastColumnOnlyAutoresizingStyle
.But, if it CAN force all of your columns into that 800 width (while still respecting each column's
min
width value), then the original issue in the question manifests.
So if you carefully manage your TableColumn
s' min
width properties, you can kinda force SwiftUI to stop being dumb. Until a dedicated modifier arrives to control column resizing, this will have to do.
.bordered
TableStyle and groups to allow more than 10 columns, yes? Just tried again over here and the SwiftUI Table shrinks columns while an AppKitNSTableView
maintains all other column widths when one is expanded. – Bryan Commented Mar 19 at 21:11.bordered
style. You basically want to setNSTableView.columnAutoresizingStyle
. SwiftUI sets it to.uniformColumnAutoresizingStyle
by default, whereasNSTableView
uses.lastColumnOnlyAutoresizingStyle
, which still allows the last column to be auto-resized. I believe you want to set it to.noColumnAutoresizing
. Btw you don't need to useGroup
s. – Sweeper Commented Mar 19 at 21:41NSViewRepresentable
. – Sweeper Commented Mar 19 at 22:09