SwiftUI自定义下拉菜单添加滚动失效问题求助
解决SwiftUI自定义Dropdown添加滚动容器后显示为空的问题
问题核心是外层固定高度限制了展开后的下拉列表空间:原代码中.frame(width: maxWidth, height: 50)给整个Dropdown设置了固定高度50,当展开下拉选项时,ScrollView被压缩在这个高度内,没有足够空间渲染内容,所以显示为空。
以下是修复后的完整代码,关键修改点已标注:
struct DropDown: View { /// Customization Properties var hint: String var options: [String] var anchor: Anchor = .bottom var maxWidth: CGFloat = 300 var cornerRadius: CGFloat = 15 @Binding var selection: String? /// View Properties @State private var showOptions: Bool = false /// Environment Scheme @Environment(\.colorScheme) private var scheme @SceneStorage("drop_down_zindex") private var index = 1000.0 @State private var zIndex: Double = 1000.0 var listOptions = [ "YouTube", "Instagram", "X (Twitter)", "Snapchat", "TikTok", "Facebook", "Weibo", "Wechat", "Discord" ] var body: some View { GeometryReader { let size = $0.size VStack(spacing: 0) { HStack(spacing: 0) { Text(selection ?? hint) .foregroundStyle(selection == nil ? .gray : .primary) .lineLimit(1) Spacer(minLength: 0) Image(systemName: "chevron.down") .foregroundStyle(.gray) .rotationEffect(.init(degrees: showOptions ? -180 : 0)) } .padding(.horizontal, 15) .frame(width: size.width, height: 50) // 固定触发栏高度为50 .background(scheme == .dark ? .black : .white) .contentShape(.rect) .onTapGesture { index += 1 zIndex = index withAnimation(.snappy) { showOptions.toggle() } } .zIndex(10) if showOptions { DropDownView() } } .clipped() .contentShape(.rect) .background((scheme == .dark ? Color.black : Color.white).shadow(.drop(color: .primary.opacity(0.15), radius: 4)), in: .rect(cornerRadius: cornerRadius)) } .frame(width: maxWidth) // 移除固定高度,让视图自适应展开后的高度 .zIndex(zIndex) } @ViewBuilder func DropDownView() -> some View { ScrollView(.vertical) { VStack(spacing: 10) { ForEach(listOptions, id: \.self) { option in HStack(spacing: 0) { Text(option) .lineLimit(1) Spacer(minLength: 0) Image(systemName: "checkmark") .font(.caption) .opacity(selection == option ? 1 : 0) } .foregroundStyle(selection == option ? Color.primary : Color.gray) .animation(.none, value: selection) .frame(height: 40) .contentShape(.rect) .onTapGesture { withAnimation(.snappy) { selection = option showOptions = false } } } .padding(.horizontal, 15) .padding(.vertical, 5) .transition(.move(edge: anchor == .top ? .bottom : .top)) } } .frame(maxHeight: 250) // 给滚动列表设置最大高度,避免展开后占满屏幕 .background(scheme == .dark ? .black : .white) // 保持背景一致 } } // 补充Anchor枚举定义(原代码可能遗漏) enum Anchor { case top, bottom }
关键修改说明:
- 移除外层固定高度:将
.frame(width: maxWidth, height: 50)改为.frame(width: maxWidth),让Dropdown能根据展开状态自动调整整体高度。 - 固定触发栏高度:把触发栏的高度从
size.height改为固定的50,确保收起时高度一致。 - 给滚动列表设置最大高度:给
ScrollView添加.frame(maxHeight: 250),限制下拉列表的最大高度,避免展开后占满屏幕,同时保证内容超出时可以滚动。 - 补充滚动列表背景:给
ScrollView添加背景色,保持和触发栏的视觉一致性。
这样修改后,既保留了原有Dropdown的交互功能,又能让选项列表正常滚动,不会出现显示为空的问题。
内容的提问来源于stack exchange,提问作者Edward Tattsyrup
相关产品推荐
相关产品推荐

