Add fourteen skills from Dimillian/Skills, integrate the merged Snowflake and WordPress updates into the maintainer sync, and refresh registry metadata, attributions, walkthrough notes, and the 8.9.0 release notes while keeping validation warnings within budget.
2.3 KiB
2.3 KiB
ScrollView and Lazy stacks
Intent
Use ScrollView with LazyVStack, LazyHStack, or LazyVGrid when you need custom layout, mixed content, or horizontal/ grid-based scrolling.
Core patterns
- Prefer
ScrollView+LazyVStackfor chat-like or custom feed layouts. - Use
ScrollView(.horizontal)+LazyHStackfor chips, tags, avatars, and media strips. - Use
LazyVGridfor icon/media grids; prefer adaptive columns when possible. - Use
ScrollViewReaderfor scroll-to-top/bottom and anchor-based jumps. - Use
safeAreaInset(edge:)for input bars that should stick above the keyboard.
Example: vertical custom feed
@MainActor
struct ConversationView: View {
private enum Constants { static let bottomAnchor = "bottom" }
@State private var scrollProxy: ScrollViewProxy?
var body: some View {
ScrollViewReader { proxy in
ScrollView {
LazyVStack {
ForEach(messages) { message in
MessageRow(message: message)
.id(message.id)
}
Color.clear.frame(height: 1).id(Constants.bottomAnchor)
}
.padding(.horizontal, .layoutPadding)
}
.safeAreaInset(edge: .bottom) {
MessageInputBar()
}
.onAppear {
scrollProxy = proxy
withAnimation {
proxy.scrollTo(Constants.bottomAnchor, anchor: .bottom)
}
}
}
}
}
Example: horizontal chips
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 8) {
ForEach(chips) { chip in
ChipView(chip: chip)
}
}
}
Example: adaptive grid
let columns = [GridItem(.adaptive(minimum: 120))]
ScrollView {
LazyVGrid(columns: columns, spacing: 8) {
ForEach(items) { item in
GridItemView(item: item)
}
}
.padding(8)
}
Design choices to keep
- Use
Lazy*stacks when item counts are large or unknown. - Use non-lazy stacks for small, fixed-size content to avoid lazy overhead.
- Keep IDs stable when using
ScrollViewReader. - Prefer explicit animations (
withAnimation) when scrolling to an ID.
Pitfalls
- Avoid nesting scroll views of the same axis; it causes gesture conflicts.
- Don’t combine
ListandScrollViewin the same hierarchy without a clear reason. - Overuse of
LazyVStackfor tiny content can add unnecessary complexity.