1

The LineLimit does not work:

TextField("Text", text: $model.commitDescr)
     .multilineTextAlignment(.leading)
     .lineLimit(5)

LineLimit change nothing - I'm able to display 10-20-30 lines.

Similar way with scrollView allways have maxHeight(400) insteaad of dymamic height:

ScrollView() {
     TextField("Text", text: $model.commitDescr)
         .multilineTextAlignment(.leading)
         .lineLimit(5)
}
.frame(minHeight: 20, maxHeight: 400)

The following also does not work properly:

TextField("Text", text: $model.commitDescr)
     .multilineTextAlignment(.leading)
     .lineLimit(5)
     .frame(minHeight: 20, maxHeight: 400)
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101

5 Answers5

3

Here is a way for this issue:

struct ContentView: View {
    
    @State private var commitDescr: String = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

    var body: some View {

        TextEditorView(string: $commitDescr)
  
    }
    
}


struct TextEditorView: View {
    
    @Binding var string: String
    @State private var textEditorHeight : CGFloat = CGFloat()

    var body: some View {
        
        ZStack(alignment: .leading) {

            Text(string)
                .lineLimit(5)
                .foregroundColor(.clear)
                .padding(.top, 5.0)
                .padding(.bottom, 7.0)
                .background(GeometryReader {
                    Color.clear.preference(key: ViewHeightKey.self,
                                           value: $0.frame(in: .local).size.height)
                })
            
            TextEditor(text: $string)
                .frame(height: textEditorHeight)
               
        }
        .onPreferenceChange(ViewHeightKey.self) { textEditorHeight = $0 }
        
    }
    
}


struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}
ios coder
  • 1
  • 4
  • 31
  • 91
2

@available(iOS 14.0, macOS 11.0, *)

use TextEditor instead of TextField

TextEditor(text: $text)
      .fixedSize(horizontal: false, vertical: true)
      .multilineTextAlignment(.leading)
 

in use example :

 ScrollView {
    VStack{
        TextEditor(text: $text)
            .frame(minHeight: 40, alignment: .leading)
            .frame(maxHeight: MAX_HEIGHT)
            .cornerRadius(10, antialiased: true)
            .foregroundColor(.black)
            .font(.body)
            .padding()
            .fixedSize(horizontal: false, vertical: true)
            .multilineTextAlignment(.leading)
     }
     .background(Color.red)

 }
2

Starting from iOS 16, there is an axis parameter for TextField.

Example:

TextField("Message", text: $messageText, axis: .vertical)

Docs

1

Fixed height, allows scrolling

Use TextEditor, rather than TextField. You then set the maxHeight to whatever you would like.

struct ContentView: View {
    @State private var text = ""

    var body: some View {
        TextEditor(text: $text)
            .frame(maxHeight: 300)
    }
}

Result:

Result

Fixed number of lines, no scrolling

If you want to limit the number of lines you can display with TextEditor, you can use SwiftUI-Introspect to do that.

Example:

struct ContentView: View {
    @State private var text = ""

    var body: some View {
        TextEditor(text: $text)
            .introspectTextView { textView in
                textView.textContainer.maximumNumberOfLines = 5
                textView.textContainer.lineBreakMode = .byTruncatingTail
            }
    }
}

Result:

Result

George
  • 25,988
  • 10
  • 79
  • 133
  • I want to have some MaxHeight limit. And in case of limit is reached, need to display scroll to scroll the text. – Andrew_STOP_RU_WAR_IN_UA Sep 04 '21 at 18:37
  • @Andrew This first example does do that. With only a few lines, it doesn't scroll. When you reach the max height, you can see scrolling then enabled. Do you mean that you want the `TextEditor` height to start small and centered, then expand to the max height? – George Sep 04 '21 at 18:38
  • Start height of `TextEditor` must be 1 line. If `$text` have 5 lines - must be 5 lines height. If `$text` have 6 lines or more - `TextEditor` must have height of 5 lines + scroll displayed. – Andrew_STOP_RU_WAR_IN_UA Sep 04 '21 at 18:42
0

Usually, a TextField is only for one line of text.

For multiple lines of input, a TextEditor may be a better solution in native SwiftUI. You could also set a .frame(maxHeight: XX, alignment: .leading) for this.

To be clear, the example beneath will make sure the editor is always 200 points high, even when no text is entered:

TextEditor(text: $variable)
     .frame(maxHeight: 200, alignment: .center)

On request of the asker, an extra example where the editor is small (50 points high) and only expands to the maxHeight when text is entered:

TextEditor(text: $variable)
     .frame(minHeight: 50, maxHeight: 200, alignment: .center)

Proof of concept: https://i.stack.imgur.com/CimV7.jpg

Björn
  • 338
  • 1
  • 13
  • frame does not work. I has wrote this in my question. Frame does not work not in case of TextField wrapped not in case of ScrollView wrapped. Please, try it on your side. – Andrew_STOP_RU_WAR_IN_UA Sep 04 '21 at 18:18
  • You used a TextField as you wrote in your question. I wrote about the TextEditor for which the .frame property is working just fine on my side. Please, try it on your side. Next time, please read the answers carefully before commenting on them. – Björn Sep 05 '21 at 17:54
  • Your code does not have correct behavior. Proof: https://imgur.com/a/6oJVdUd Code of SwiftPunk do what expected. Proof: https://i.imgur.com/ES0IsgI.png – Andrew_STOP_RU_WAR_IN_UA Sep 05 '21 at 18:16
  • Ah, you want your editor as small as possible when no text is entered? Maybe you should have added that to your question. As now read your question, it states that you want to give it a maxHeight and for the field not to grow infinitely. Just add a minHeight to your frame like this: .frame(minHeight: 50, maxHeight: 200, alignment: .center). Don't tell me it does not work, since it does. Good luck! – Björn Sep 05 '21 at 18:28
  • @Björn: "a `TextEditor` may be a better solution in native SwiftUI", Are u sure TextEditor is native for SwiftUI or maybe it is coming from UIKit? – ios coder Sep 05 '21 at 18:36
  • Björn, did you looked screenshot I have send? https://i.imgur.com/QEbouI8.png Looks like you didn't. Because of it does not work and I have already send the proof. This is the same screenshot, you can check. – Andrew_STOP_RU_WAR_IN_UA Sep 05 '21 at 18:38
  • `Maybe you should have added that to your question. ` -- and by the way, it was in the question. Please check the title of the question. – Andrew_STOP_RU_WAR_IN_UA Sep 05 '21 at 18:39
  • @swiftPunk https://developer.apple.com/documentation/swiftui/texteditor TextEditor actually is part of the native SwiftUI framework :) – Björn Sep 05 '21 at 18:45
  • @Björn: If we can access it in SwiftUI it does not mean it is native! it is coming from UIKit, not the only TextEditor also ScrollView, NavigationView, List, Picker,... . They are all UIViewRepresentable! Read this article for more info: https://wwdcbysundell.com/2020/uikit-views-that-now-have-swiftui-counterparts-in-ios14/ :) – ios coder Sep 05 '21 at 18:52
  • @swiftPunk I kind of do not see what your point is? It is part of the SwiftUI package, works well and is supported by Apple for multiple iOS runs for good sake? I do not sleep any worse at night if I may not call it fully 'native'? I have other more important matters to worry about, other than nitpicking on the naming of Swift packages :) – Björn Sep 05 '21 at 18:55
  • @Björn: I think you just reading Apple document about TextEditor that they say it is native and you just repeat it without seeing it what it is! I am not fighting with words with you! you can access UIColor in SwiftUI without importing UIKit, is it make it native to SwiftUI? Most of the things we are using in SwiftUI are not native, they are coming from UIKit, I would say Color, View protocol, GeometryReader, main, Environment these are native for SwiftUI, – ios coder Sep 05 '21 at 19:30
  • if even Apple says that TextEditor is native to SwiftUI it is not true! It is not native and it will not be! unless apple change the under hood cods for pure SwiftUI. ps: I am not interested arguing with you. **Last comment!** – ios coder Sep 05 '21 at 19:30
  • Haha, I like the idea that you are so keen on the word 'native', protecting it at all costs! Conclusion: it is provided by Apple, it is a perfectly working framework, birthed by UIKit or SwiftUI, no one has ever cared any less :) – Björn Sep 05 '21 at 19:45
  • He is right -- it is not native. That's why SwiftUI is so slow. It will be native in future, when SwiftUI will be rewritten and all "backround" of UIKit will be removed from it. But just now there is no way to rewrite swiftUI from scratch -- too much of work. That's why "TextEditor" is not native in swiftUI and no matter that it is provided by Apple. – Andrew_STOP_RU_WAR_IN_UA Sep 05 '21 at 20:25
  • `Actually show some respect for the people answering your question man, come on` - I didnt tried to be unrespectfull, sorry if you think in another way. English language is not native for me so I have a little bit troubles with it :) – Andrew_STOP_RU_WAR_IN_UA Sep 05 '21 at 20:28