最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - How do you set SwiftUI's Table column resizing behavior so that other columns are not affected on resize? - Stac

programmeradmin5浏览0评论

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
  • @sweeper - the behavior does not manifest with small tables; you need many columns such that their combined widths exceed the width of the view containing the Table. – Bryan Commented Mar 19 at 19:21
  • @Sweeper - Done. You're using the .bordered TableStyle and groups to allow more than 10 columns, yes? Just tried again over here and the SwiftUI Table shrinks columns while an AppKit NSTableView maintains all other column widths when one is expanded. – Bryan Commented Mar 19 at 21:11
  • Ah, I was not using the .bordered style. You basically want to set NSTableView.columnAutoresizingStyle. SwiftUI sets it to .uniformColumnAutoresizingStyle by default, whereas NSTableView 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 use Groups. – Sweeper Commented Mar 19 at 21:41
  • @Sweeper Precisely. So how do I do that in SwiftUI? – Bryan Commented Mar 19 at 22:07
  • 1 There is no SwiftUI API for this. You either use SwiftUI-Introspect or wrap your own NSViewRepresentable. – Sweeper Commented Mar 19 at 22:09
Add a comment  | 

1 Answer 1

Reset to default 0

A Workaround

I've discovered a hacky workaround that sort-of solves this problem:

  1. Suppose your Table starts at 800 points wide. (The view that contains the Table has a width of 800.)

  2. As long as you set the .width(min:ideal:max:) modifiers on your TableColumns such that it's NOT POSSIBLE for SwiftUI to squeeze them all into that 800 width, the Framework seems to automatically switch to AppKit's lastColumnOnlyAutoresizingStyle.

  3. 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 TableColumns' 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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论