ios – SwiftUI – Getting Text views to not wrap or truncate in a LazyVGrid with adaptive GridItems


I started looking at Paul Hudson’s Hacking with Swift tutorial on positioning views in a grid. If I run the code given in the first listing, I get exactly what’s shown in the corresponding screenshot. In other words, this code …

import SwiftUI

struct ContentView: View {
    let data = (1...100).map { "Item \($0)" }

    let columns = [
        GridItem(.adaptive(minimum: 80))

    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 20) {
                ForEach(data, id: \.self) { item in
        .frame(maxHeight: 300)

… ran on an iPad 11 Pro Max simulator gets me the following:
enter image description here

So far so good.

But I want to show a grid of Text views with a bit more content, so I change the first line of my view to …

    let data = (1...100).map { "Item \($0) - more content" }

… but this gets me …
enter image description here

This is where my understanding falls apart. I would like to see a grid where each Text view is given the amount of horizontal space needed to accommodate the longest content, without line breaks or truncation. Something like this:

Item 1 - more content     Item 2 - more content
Item 3 - more content     Item 4 - more content
Item 42 - more content    Item 43 - more content
Item 44 - more content    Item 45 - more content
Item 142 - more content   Item 143 - more content
Item 144 - more content   Item 145 - more content
Item 7142 - more content  Item 7143 - more content
Item 7144 - more content  Item 7145 - more content

And if my data was long enough that strings were longer than half the width of the screen, I’d expect the grid to utilize just a single column.

Why don’t the Text views take up more horizontal space? We’ve only specified a minimum for our adaptive GridItems, so why would they not expand horizontally as needed to accommodate the longest string? The documentation for GridItem.Size.adaptive says (emphasis mine):

This approach prefers to insert as many items of the minimum size as possible but lets them increase to the maximum size.

So how would I get the grid to let these views increase to their maximum size (which is .infinity by default)?

I’ve tried adding .fixedSize() to each Text, hoping it would force them to retain their ideal size. But this does not work:
enter image description here

Similarly, I’ve tried .lineLimit(1) as well, but this results in truncation:
enter image description here

I’m aware of three similar questions (here, here, here) but they are trying to achieve a variable line length with the given data. In my case I really do want a grid. I just want each grid item to take up as much horizontal space as the largest one. How could I achieve this?

I feel like I’m missing something simple about the way SwiftUI layout (or that of a grid) works. I know that during layout the parent view proposes a size to its children, and each child responds with its desired size. In this case it looks like the grid has already decided it will fit four columns on the screen, so it only offers roughly a quarter of its width to each Text. I don’t follow why that would be the case when we’ve asked the grid items to be adaptive and only provided a minimum width.

In a “teach a man to fish …” fashion, I’d greatly appreciate any advice or tooling that would help me understand how you arrive at your specific answer. For instance, is there a way for a developer to follow (debug print perhaps?) the proposals and counterproposals between parent and child views? Is there any documentation, explanation, etc. to learn more about what exactly goes on during the layout pass? Any detailed explanation of how exactly a grid decides on the sizes of adaptive GridItems?


Source link

Leave a Reply

Your email address will not be published.