You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 22:06:01