ios - SwiftUI's navigationBarItems leading and trailing buttons not showing in FamilyActivityPicker - Stack Overflow

admin2025-04-17  0

I have the following View in SwiftUI to display FamilyActivityPicker:

import SwiftUI
import FamilyControls

struct FamilyActivityPickerView: View {
    @State private var selectionToDiscourage = FamilyActivitySelection()
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        FamilyActivityPicker(headerText: "Select Apps to Restrict", selection: $selectionToDiscourage).navigationBarItems(leading: Button("Cancel") {
            print("Cancel!")
            dismiss()
        }, trailing: Button("Done") {
            print("Done!")
            dismiss()
        }).ignoresSafeArea().onChange(of: selectionToDiscourage) { newSelection in
            let applications = selectionToDiscourage.applications
            let categories = selectionToDiscourage.categories
            let webDomains = selectionToDiscourage.webDomains
            print("applications: \(applications), categories: \(categories), webDomains: \(webDomains)")
        }
    }
}

However, neither of the navigationBarItems leading and trailing buttons are showing:

What am I doing wrong? How are we supposed to Cancel or Done the FamilyActivityPicker view?

EDIT:

When I use NavigationStack with .toolbar, I end up with 2 navigation bars as shown below screenshot which looks very ugly and wastes space:

import SwiftUI
import FamilyControls

struct FamilyActivityPickerView: View {
    @State private var selectionToDiscourage = FamilyActivitySelection()
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        NavigationStack {
            FamilyActivityPicker(selection: $selectionToDiscourage).ignoresSafeArea().onChange(of: selectionToDiscourage) { newSelection in
                let applications = selectionToDiscourage.applications
                let categories = selectionToDiscourage.categories
                let webDomains = selectionToDiscourage.webDomains
                print("applications: \(applications), categories: \(categories), webDomains: \(webDomains)")
            }.toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") {
                        print("Cancel!")
                        dismiss()
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Done") {
                        print("Done!")
                        dismiss()
                    }
                }
            }
        }
    }
}

Result:

I have the following View in SwiftUI to display FamilyActivityPicker:

import SwiftUI
import FamilyControls

struct FamilyActivityPickerView: View {
    @State private var selectionToDiscourage = FamilyActivitySelection()
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        FamilyActivityPicker(headerText: "Select Apps to Restrict", selection: $selectionToDiscourage).navigationBarItems(leading: Button("Cancel") {
            print("Cancel!")
            dismiss()
        }, trailing: Button("Done") {
            print("Done!")
            dismiss()
        }).ignoresSafeArea().onChange(of: selectionToDiscourage) { newSelection in
            let applications = selectionToDiscourage.applications
            let categories = selectionToDiscourage.categories
            let webDomains = selectionToDiscourage.webDomains
            print("applications: \(applications), categories: \(categories), webDomains: \(webDomains)")
        }
    }
}

However, neither of the navigationBarItems leading and trailing buttons are showing:

What am I doing wrong? How are we supposed to Cancel or Done the FamilyActivityPicker view?

EDIT:

When I use NavigationStack with .toolbar, I end up with 2 navigation bars as shown below screenshot which looks very ugly and wastes space:

import SwiftUI
import FamilyControls

struct FamilyActivityPickerView: View {
    @State private var selectionToDiscourage = FamilyActivitySelection()
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        NavigationStack {
            FamilyActivityPicker(selection: $selectionToDiscourage).ignoresSafeArea().onChange(of: selectionToDiscourage) { newSelection in
                let applications = selectionToDiscourage.applications
                let categories = selectionToDiscourage.categories
                let webDomains = selectionToDiscourage.webDomains
                print("applications: \(applications), categories: \(categories), webDomains: \(webDomains)")
            }.toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") {
                        print("Cancel!")
                        dismiss()
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Done") {
                        print("Done!")
                        dismiss()
                    }
                }
            }
        }
    }
}

Result:

Share edited Mar 8 at 22:44 sudoExclamationExclamation asked Mar 8 at 21:30 sudoExclamationExclamationsudoExclamationExclamation 8,81810 gold badges51 silver badges120 bronze badges 4
  • I don't have a NavigationStack as parent container because the FamilyActivityPicker has its own navigation bar, so I thought I didn't need one. When I add a NavigationStack as parent container, I end up having 2 navigation bars, one mine and one provided by the FamilyActivityPicker. Is there a way to avoid that? – sudoExclamationExclamation Commented Mar 8 at 22:14
  • I don't think I can "drop the NavigationStack that is inside FamilyActivityPicker" because the FamilyActivityPicker is provided by Apple. I can't make changes to it as it's closed source. – sudoExclamationExclamation Commented Mar 8 at 22:31
  • @BenzyNeez I edited by question with result of using NavigationStack with .toolbar, I end up with 2 navigation bars as shown below screenshot which looks very ugly and wastes space. Any way to fix it? – sudoExclamationExclamation Commented Mar 8 at 22:44
  • I actually tried using overlays with ZStack containing the buttons. But it becomes an issue as soon as the user clicks the searchbar as iOS animates the searchbar to the top and it ends up behind my buttons. Can you explain what do you mean by showing the picker as a sheet? – sudoExclamationExclamation Commented Mar 8 at 23:15
Add a comment  | 

2 Answers 2

Reset to default 1

What you are looking for is `familyActivityPicker` not `FamilyActivityPicker`

    import SwiftUI
    import FamilyControls

    struct FamilyParentView: View {
        @State var selection = FamilyActivitySelection()
        @State var isPresented = false


       var body: some View {
           Button("Present FamilyActivityPicker") { isPresented = true }
           .familyActivityPicker(isPresented: $isPresented,
                                 selection: $selection)
           .onChange(of: selection) { _, newSelection in
               let applications = selection.applications
               let categories = selection.categories
               let webDomains = selection.webDomains
           }
       }
    }

You cannot modify the navigation buttons of the FamilyActivityPicker.

It looks like you are presenting your FamilyActivityPickerView in a sheet. if that is the case, you should use the .familyActivityPicker modifier, instead of the view FamilyActivityPicker. Replace the .sheet modifier with this modifier.

Change

.sheet(isPresented: $isPresened) {
    FamilyActivityPickerView()
}

to

.familyActivityPicker(isPresented: $isPresented, selection: $selection)

SwiftUI will present a FamilyActivityPicker in a sheet, and it will automatically add "Done" and "Cancel" buttons.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1744884410a272451.html

最新回复(0)