9

I have a navigation list with each list item being in this format:

HStack {
        TextField("Insert something here.",text: self.$userData.pages[i].title)
            .border(Color.blue)
        Spacer()
    }

This results in the following view:

The touchable area is highlighted by the blue border and it takes the whole width of the row

The problem with this is that despite the list item being a navigation link, the user clicking anywhere along the item will result in them editing the text content. What I would prefer is a TextField that has the same width as a Text:

The blue border wraps the text instead of taking the max width

So if the user clicks outside the TextField, the navigation works, but if they click on the text, it will let them edit the text. (The above view is with Text field).

Apologies if I've asked an unclear or bad question. I'm new to Stack Overflow and SwiftUI.

Edit:

I've tried using the fixedSize modifier, and the TextField correctly wraps my Text, but now the Navigation Link doesn't work (i.e. clicking on it just doesn't navigate). This is my full code:

NavigationLink(destination: PageView(page: self.userData.pages[i])) {
                        HStack {
                            Button(action: {}){
                                TextField(" ", text: self.$userData.pages[i].title)
                                .fixedSize()

                            }
                            .buttonStyle(MyButtonStyle())
                            .border(Color.blue)
                            Spacer()
                        }
                    }
user4500882
  • 303
  • 3
  • 8
  • This should be helpful [Make TextField wrap it content in SwiftUI](https://stackoverflow.com/a/61821548/12299030) – Asperi Jun 10 '20 at 17:41
  • @Asperi I've tried this, and I believe it runs into the same issue I described in my edit. – user4500882 Jun 11 '20 at 00:20

1 Answers1

18

No need to apologize, your question is clear. You can do this by using fixedSize()

so your code should be like this

HStack {
        TextField("Insert something here.",text: self.$userData.pages[i].title)
            .border(Color.blue)
            .fixedSize()
        Spacer()
    }

You can further specify how would you like the stretch to be, either vertical or horizontal or even both by passing parameters like so .fixedSize(horizontal: true, vertical: false)

UPDATED ANSWER TO MATCH YOUR NEW REQUIREMENTS

import SwiftUI

struct StackOverflow5: View {
    @State var text: String = ""
    @State var selection: Int? = nil

    var body: some View {
        NavigationView {
            ZStack {
                NavigationLink(destination: Page2(), tag: 1, selection:self.$selection) {
                    Color.clear
                        .onTapGesture {
                            self.selection = 1
                        }
                }


                TextField("Text", text: self.$text)
                    .fixedSize()
            }
        }
    }
}

struct StackOverflow5_Previews: PreviewProvider {
    static var previews: some View {
        StackOverflow5()
    }
}

struct Page2: View {
    var body: some View {
        Text("Page2")
    }
}

We used a ZStack here to separate between our TextField and our NavigationLink so they can be interacted with separately.

Note the use of Color.clear before our TextField and this is on purpose so that our TextField has interaction priority. Also we used Color.clear because it will stretch as a background and it's clear so it's not visible.

Obviously I hard coded 1 here but this can be from List or a ForEach

Additionally, if you don't want to use selection and tag you can do something like this

...
@State var isActive: Bool = false
...
NavigationLink(destination: Page2(), isActive: self.$isActive) {
     Color.clear
          .onTapGesture {
               self.isActive.toggle()
          }
}
....
Muhand Jumah
  • 1,726
  • 1
  • 11
  • 26
  • Perfect thanks! I guess I ignored `fixedSize` when going through the documentation bc it said it fixed the view at its ideal size, and I thought that meant the same thing as its default size. – user4500882 Jun 10 '20 at 18:33
  • No worries, glad I was able to help. Keep in mind though `fixedSize` is a function of any view not necessarily `TextField`. Good luck! – Muhand Jumah Jun 10 '20 at 18:34
  • So I've just tried this, and I've run into a problem, although I'm not sure if this is this solution's fault, but now the NavigationLink just doesn't seem to work. I know the TextField is being properly wrapped, but clicking on the row does not navigate me. I tried the simulator and the real device, but it still doesn't seem to work. Do you have any thoughts? – user4500882 Jun 10 '20 at 22:27
  • Got it, I am working on updating my answer to reflect. Are you okay with fixed width and height? because one solution is to wrap everything in a `zStack` so that NavigationLink sits under textfield and it takes 100% width and 100% height, this way if you tap on NavigationLink you are good and if you tap on textfield, well you oonly update textfield. – Muhand Jumah Jun 10 '20 at 22:59
  • Are you referring to fixed width/height of the NavigationLink or the TextField? I need the TextField to take the width of the text inside it but the navigationLink's width/height can be fixed. – user4500882 Jun 11 '20 at 00:08
  • So it turns out something else in my code was actually the culprit for breaking the navigation link...I apologize for the inconvenience I caused! I tried your updated code and the original code after fixing it and both work. Sorry about that again (still new to Swift...). Thanks so much! – user4500882 Jun 12 '20 at 01:25
  • Not a problem at all! don't hesitate to ask if you need more help! – Muhand Jumah Jun 12 '20 at 01:27