FocusState Textfield not working within toolbar ToolbarItem
Asked Answered
B

1

8

Let me explain, I have a parent view with a SearchBarView, im passing down a focus state binding like this .

   SearchBarView(searchText:$object.searchQuery, searching: $object.searching, focused: _searchIsFocused 

That works perfectly as @FocusState var searchIsFocused: Bool is defined in parent view passing it down to the SearchBarView (child view ). In parent I can check the change in value and everything ok.

The problem relies when in parent I have the SearchBarView inside .toolbar {} and ToolBarItem(). nothing happens, not change in value of focus, etc. I have my SearchBarView in the top navigation bar and still want to use it there.. but I need to be able to know when it is in focus. if I use inside any VStack or whatever, everything perfectly..

-- EDIT -- providing more code to test

SearchBarView

struct SearchBarView: View {
@Environment(\.colorScheme) var colorScheme
@Binding var searchText: String
@Binding var searching: Bool
@FocusState var focused: Bool


 var body: some View {
     ZStack {
         
         Rectangle()
             .foregroundColor(colorScheme == .dark ? Color("darkSearchColor") : Color.white)
             .overlay(
                     RoundedRectangle(cornerRadius: 13)
                        .stroke(.black.opacity(0.25), lineWidth: 1)
             )


         HStack {
             Image(systemName: "magnifyingglass").foregroundColor( colorScheme == .dark ? .gray : .gray )
          
             
             TextField("Search..", text: $searchText )
                 .focused($focused, equals: true)
                 .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20))
                 .disableAutocorrection(true).onSubmit {
                     let _ = print("Search textfield Submited by return button")
                 }
                 
         }
         .foregroundColor(colorScheme == .dark ? Color("defaultGray") :.gray)
         .padding(.leading, 13)
         .padding(.trailing, 20).overlay(
            HStack {
                Spacer()
                if searching {
                    ActivityIndicator().frame(width:15,height:15).aspectRatio(contentMode: .fit).padding(.trailing,15)
                }
            }
         )
         
         .onChange(of: focused) { searchIsFocused in
             let _ = print("SEARCH IS FOCUSED VALUE: \(searchIsFocused) ")

         }
         
     }
             .frame(height: 36)
             .cornerRadius(13)
             
     }
 }

-- home View Code --

struct HomeView: View {

@Environment(\.colorScheme) var colorScheme

@FocusState var searchIsFocused: Bool


 @State var searching:Bool = false
    @State var searchQuery: String = ""





var body: some View {
        NavigationStack {
            GeometryReader { geofull in
                ZStack(alignment: .bottom)  {
                    Color("background")//.edgesIgnoringSafeArea([.all])
                    ScrollView(showsIndicators: false)  {
                    
                    
                    VStack {

                        // Testing Bar inside VStack.. Here It Works. comment the bar the leave
                        // the one inside the .toolbar ToolbarItem to test
                        SearchBarView(searchText:$searchQuery, searching: $searching, focused: _searchIsFocused).padding(0)

                    }.toolbar {
                    
                    //MARK: Navbar search field
                            ToolbarItem(placement:.principal) {
                               
                                SearchBarView(searchText:$searchQuery, searching: $searching, focused: _searchIsFocused).padding(0)
                                     
                                
                            }
                    
                    }
                    .onChange(of: searchIsFocused) { searchIsFocused in
                            let _ = print("HOME VIEW searchIsFocused VALUE: \(searchIsFocused) ")
         
                        }


                }
            }
        }
    }
}
}
Baillieu answered 29/10, 2022 at 12:10 Comment(11)
frustrating, lol. I have two SearchBarViews testing now, one inside toolbar and toolbaritem(.principal) , and another one inside a Vstack , one changes the focus state ok and the one in the navbar doesn't...Baillieu
Could you provide a bit more code to reproduce this?Epsilon
@Epsilon okk i will in an hour or twoBaillieu
@Epsilon Just added the code for the SearchBarView and the HomeView, You will see the focus changing from the searchbarview inside the VStack working as should. but there will be no change from the one inside the navbar...Baillieu
@lorenzogonzalez Did you end up finding a solution for this?Sugary
@ZaheerMoola Hey Zaheer, sadly nop! just about today I did remove the focus state and im not using it.. the problem still happens that I know of. if I place the searcher outside of Toolbar item the focus works... it fires...Baillieu
Thanks for the reply @lorenzogonzalez. From my side, I did discover that if I declare the focus state variable in the same place where my NavigationView is declared and pass that as a binding to my child view it works as expected. Sadly this isn't a great/clean solution so I ended up wrapping a UIKit text field.Sugary
Hey @ZaheerMoola ! ohh I see.. thanks so much for giving a solution on this. I guess im going to try once more on this with that method to check again... :) thanks a lot ... if later you find anything else.. please let us know.. :DBaillieu
@ZaheerMoola How do you pass it as binding? the focused modifier only accepts FocusState<Bool>.BindingMerriott
When I refer to passing the binding, I'm referring to passing the FocusState itself as a binding. For example, if you have two views: View A, which contains the NavigationView, and View B which is navigated to from View A. Currently, the focustate would not work on View B in this context if you declare it there. Instead, you need to declare it in View A, and then pass it as a Binding to View B when you create it. I hope that explains it.Sugary
Hey zaheer please check my code as i guess thats what im doing im passing _focused to focused: in the searchView plese check the code in the homeview where i call the searchview .. im passing the focused arg with _focused which comes from the @focusstate at the homeview… but it still didnt work when having the search inside .toolbar at the homeview, it works anywhere else in the code.. inside any vstack etcBaillieu
F
0

Update

This only works on macOS

Original answer

Add the View Modifier focusSection() to your SearchBarView

Documentation: focusSection()

Example:

SearchBarView(searchText:$searchQuery, searching: $searching, focused: _searchIsFocused)
    .focusSection()
    .padding(0)

Available since macOS 13

Freeze answered 8/3 at 12:0 Comment(4)
Def im checking this ;) thnxBaillieu
thats a case in tvos and macos, but i dont think this modifier is available in iOS.. i will still check when i get homeBaillieu
@lorenzogonzalez That's correct, it is not available on iOS, sorry, I missed that detail.Freeze
I havent checked this issue in a while … i kind of gave up on it lol, i will try checking this again and see if i can come up with an answerBaillieu

© 2022 - 2024 — McMap. All rights reserved.