web-dev-qa-db-ja.com

SwiftuiのNavigationViewにセグメント化されたスタイルピッカーを追加する

質問はタイトルと同じくらい簡単です。 PickerSegmentedPickerStyleNavigationBarのスタイルを持つSwiftUIを入れようとしています。ネイティブPhoneアプリケーションの履歴ページのようなものです。画像は下にあります

enter image description here

私はGoogleとGithubなどのプロジェクト、ライブラリ、またはチュートリアル、そして運を探しました。たとえばNativa AppsとWhatsAppがそれを持っているかどうかは、可能になるはずです。どんな助けにも感謝されるでしょう。

7
Faruk

単純な答えセグメントコントローラを中心とし、ボタンの1つを隠す方法。

@State var showLeadingButton = true
    var body: some View {
        HStack {
            Button(action: {}, label: {"leading"})
                          .opacity(showLeadingButton ? true : false)


            Spacer()

            Picker(selection: $selectedStatus,
                   label: Text("SEGMENT") {
                segmentValues
                }
             .id(UUID())
             .pickerStyle(SegmentedPickerStyle())
             .fixedSize()

             Spacer()
             Button(action: {}, label: {"trailing"})
        }
        .frame(width: UIScreen.main.bounds.width)
    }
 _
1

Centerにセグメント管理が必要な場合は、GeometryReaderを使用する必要があります。以下のコードはピッカーをタイトルとして提供し、末尾(右)ボタンを提供します。

同じ幅で左右の側面に2つのビューを設定し、ミドルビューは残りを取ります。 5マジックナンバーは、セグメントを必要とする幅に依存します。あなたはあなたにとって最善のフィット感を試して見てもらえます。

   GeometryReader {
    
    Text("TEST")
     .navigationBarItems(leading:
                                    HStack {
                                        Spacer().frame(width: geometry.size.width / 5)
                                        Spacer()
                                        picker
                                        Spacer()
                                        Button().frame(width: geometry.size.width / 5)
                                           }.frame(width: geometry.size.width)
    
    }
 _

しかし、より良い解決策は、ピッカーサイズを保存してその他のフレームサイズを計算する場合、PickerはiPadとiPhoneで同じになります。

 @State var segmentControllerWidth: CGFloat = 0

    var body: some View {
            HStack {
                Spacer()
                    .frame(width: (geometry.size.width / 2) - (segmentControllerWidth / 2))
                    .background(Color.red)
                segmentController
                    .fixedSize()
                    .background(PreferenceViewSetter())
                profileButton
                    .frame(width: (geometry.size.width / 2) - (segmentControllerWidth / 2))
            }
            .onPreferenceChange(PreferenceViewKey.self) { preferences in
                segmentControllerWidth = preferences.width
            }
        }
    
    
    struct PreferenceViewSetter: View {
        var body: some View {
            GeometryReader { geometry in
                Rectangle()
                    .fill(Color.clear)
                    .preference(key: PreferenceViewKey.self,
                                value: PreferenceViewData(width: geometry.size.width))
            }
        }
    }
    
    struct PreferenceViewData: Equatable {
        let width: CGFloat
    }
    
    struct PreferenceViewKey: PreferenceKey {
        typealias Value = PreferenceViewData
    
        static var defaultValue = PreferenceViewData(width: 0)
    
        static func reduce(value: inout PreferenceViewData, nextValue: () -> PreferenceViewData) {
            value = nextValue()
        }
    }
 _
1