簡體   English   中英

如何在 SwiftUI 上制作平滑的自定義選擇器?

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

我想在 swiftUI 中復制這個選擇器。特別是,我在屏幕的左下角有一個按鈕,當我單擊它時,我想顯示不同的圖標(類似於下圖,但垂直)。 只要我點擊其中一個選項,按鈕就會收縮回帶有所選圖標的初始形式(圓圈)。

關閉時:

關閉按鈕

打開時:

打開按鈕

我對這種語言和一般的應用程序都不熟悉,我嘗試使用彈出菜單,但這不是預期的結果,因為現在我有一個水平分段的選擇器。

您不能使用內置的Picker執行此操作,因為它不提供這樣的樣式,並且PickerStyle不允許您創建自定義 styles(從 2022 版開始)。

您可以使用其他 SwiftUI 視圖創建自己的實現。 這是我的簡短嘗試:

一個擴展的選擇器。最初它顯示為一個黑色圓圈,其中包含一個帶有斜線的紅色揚聲器圖標。當我點擊它時,它會水平擴展,同時顯示一個旁邊帶有感嘆號的白色揚聲器,以及一個帶有兩條聲線的白色揚聲器。當我點擊帶感嘆號的揚聲器的中間圖標時,其他兩個圖標消失,選擇器折疊成一個黑色圓圈,只顯示帶感嘆號的揚聲器圖標。我再次點擊它,它重新展開以顯示所有三個圖標。我點擊最右邊的揚聲器圖標,選擇器折疊成黑色圓圈,現在只顯示揚聲器圖標。我點擊以展開選擇器並選擇紅色的帶斜杠的揚聲器圖標。選擇器折疊成一個黑色圓圈,僅顯示紅色圖標。然后整個動畫無限重復。

這是代碼:

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