before updating to iOS 26 my list was looking fine but now it has abnormal paddings and because I am using fixed height, I had to increase the height from 40 to 60 to fit the text. There are currently two issues I am facing.
- The list is now not being clipped at the bottom edges when I increase the height to 60
- When the text is more than one line, unlike before it does not decrease padding to fit it in the specified height but instead cuts it off.
Following are my modifiers for my view, I have also treid with minHeight and mxHeight but both issues persist
struct SwiftUIView: View {
var body: some View {
let names = [Name(name: "Name 1"), Name(name: "Name 2 Name Double line list row text which should fit in it too")]
ZStack {
Color(.pink)
List {
Section {
ForEach(names) { name in
Button {
// do action
} label: {
Text(name.name)
}
}
}
}
.clipShape(.rect(cornerRadius: 15))
.frame(height: 2 * 52)
}
}
}
Desired behaviour is that like before iOS 26 the padding would decrease for a row when the text is multiline.
1 Answer 1
As discussed in the comments, the modifier .onScrollGeometryChange can be used to measure the height of the list precisely (requires iOS 18). You can then set this height on the list, before applying the clip shape. This approach also adapts to changes in the text size.
Here is the fully updated example to show it working:
struct SwiftUIView: View {
let names = [
Name(name: "Name 1"),
Name(name: "Name 2 Name Double line list row text which should fit in it too")
]
@State private var listHeight: CGFloat?
var body: some View {
ZStack {
Color.pink
.ignoresSafeArea()
List {
Section {
ForEach(names) { name in
Button {
// do action
} label: {
Text(name.name)
}
}
}
}
.listStyle(.plain)
.onScrollGeometryChange(for: CGFloat.self, of: \.contentSize.height) { _, height in
if height > 0 {
listHeight = height
}
}
.frame(height: listHeight)
.clipShape(.rect(cornerRadius: 15))
.scrollContentBackground(.hidden)
.padding(10)
}
}
}
struct Name: Identifiable {
let id = UUID()
let name: String
}
Screenshot
Re. your point 2:
When the text is more than one line, unlike before it does not decrease padding to fit it in the specified height but instead cuts it off.
If you want the text to have less vertical padding when it wraps to 2 or more lines then try setting the top and bottom row insets to 0 using .listRowInsets:
ForEach(names) { name in
Button {
// do action
} label: {
Text(name.name)
}
.listRowInsets(.init(top: 0, leading: 16, bottom: 0, trailing: 16)) // 👈 here
}
Rows that fit on 1 line will still have some vertical padding by virtue of the environment value defaultMinListRowHeight. This is the case for the first line in your example:
Screenshot
5 Comments
if height > 0 as shown in the code above? And is the type of the state variable an optional, also as shown?GeometryReader in the background will be the full (greedy) height of the list, not the height of its contents, so probably not useful. The issue with initial size may be because other content on the same page is competing for the same screen space. This gets back to my original request for an MRE that showed the context of how the list was being shown. If the circumstances are more complex, I would suggest raising a new question. This should include a complete MRE that incorporates the solution you have from here.if check to a larger value, for example, 10. Or try an additional frame modifier: .frame(minHeight: 10). Then if 10 doesn't help, try the approximate height of one row (40?).Explore related questions
See similar questions with these tags.
.clipShapeafter the.frame. Otherwise, please provide enough code to allow the problem to reproduced (in other words, more than a few modifiers). A screenshot would also be helpful to illustrate the issue.