简体   繁体   English

如何在 SwiftUI 上制作平滑的自定义选择器?

[英]How can I make a smoothed custom Picker on SwiftUI?

I would like to replicate this picker in swiftUI. In particular, I have a button on the bottom left of the screen and when I click it I would like to show different icons (similar to the image below, but vertically).我想在 swiftUI 中复制这个选择器。特别是,我在屏幕的左下角有一个按钮,当我单击它时,我想显示不同的图标(类似于下图,但垂直)。 As soon as I click on one of the choices the button should shrink back to the initial form (circle) with the chosen icon.只要我点击其中一个选项,按钮就会收缩回带有所选图标的初始形式(圆圈)。

When closed:关闭时:

关闭按钮

When open:打开时:

打开按钮

I am new to this language and to app in general, I tried with a Pop Up menu, but it is not the desired result, for now I have an horizontal segmented Picker.我对这种语言和一般的应用程序都不熟悉,我尝试使用弹出菜单,但这不是预期的结果,因为现在我有一个水平分段的选择器。

You can't do this with the built-inPicker , because it doesn't offer a style like that and PickerStyle doesn't let you create custom styles (as of the 2022 releases).您不能使用内置的Picker执行此操作,因为它不提供这样的样式,并且PickerStyle不允许您创建自定义 styles(从 2022 版开始)。

You can create your own implementation out of other SwiftUI views instead.您可以使用其他 SwiftUI 视图创建自己的实现。 Here's what my brief attempt looks like:这是我的简短尝试:

一个扩展的选择器。最初它显示为一个黑色圆圈,其中包含一个带有斜线的红色扬声器图标。当我点击它时,它会水平扩展,同时显示一个旁边带有感叹号的白色扬声器,以及一个带有两条声线的白色扬声器。当我点击带感叹号的扬声器的中间图标时,其他两个图标消失,选择器折叠成一个黑色圆圈,只显示带感叹号的扬声器图标。我再次点击它,它重新展开以显示所有三个图标。我点击最右边的扬声器图标,选择器折叠成黑色圆圈,现在只显示扬声器图标。我点击以展开选择器并选择红色的带斜杠的扬声器图标。选择器折叠成一个黑色圆圈,仅显示红色图标。然后整个动画无限重复。

Here's the code:这是代码:

enum SoundOption {
    case none
    case alertsOnly
    case all
}

struct SoundOptionPicker: View {
    @Binding var option: SoundOption
    @State private var isExpanded = false

    var body: some View {
        HStack(spacing: 0) {
            button(for: .none, label: "volume.slash")
                .foregroundColor(.red)
            button(for: .alertsOnly, label: "speaker.badge.exclamationmark")
                .foregroundColor(.white)
            button(for: .all, label: "volume.2")
                .foregroundColor(.white)
        }
        .buttonStyle(.plain)
        .background {
            Capsule(style: .continuous).foregroundColor(.black)
        }
    }

    @ViewBuilder
    private func button(for option: SoundOption, label: String) -> some View {
        Button {
            withAnimation(.easeOut) {
                if isExpanded {
                    self.option = option
                    isExpanded = false
                } else {
                    isExpanded = true
                }
            }
        } label: {
            Image(systemName: label)
                .fontWeight(.bold)
                .padding(10)
        }
        .frame(width: shouldShow(option) ? buttonSize : 0, height: buttonSize)
        .opacity(shouldShow(option) ? 1 : 0)
        .clipped()
    }

    private var buttonSize: CGFloat { 44 }

    private func shouldShow(_ option: SoundOption) -> Bool {
        return isExpanded || option == self.option
    }
}

struct ContentView: View {
    @State var option = SoundOption.none

    var body: some View {
        ZStack {
            Color(hue: 0.6, saturation: 1, brightness: 0.2)
            SoundOptionPicker(option: $option)
                .shadow(color: .gray, radius: 3)
                .frame(width: 200, alignment: .trailing)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM