This question already has answers here:
How do I create a multiline TextField in SwiftUI?
(17 answers)
Closed 9 months ago.
I start learning SwiftUI and I'm trying to make the TextField multiline but it didn't work, also when I click on the return button it dismisses the keyboard.
TextField("Description", text: $categoryTitle)
.lineLimit(nil)
so how I can fix it?
Since iOS 16
The lineLimit modifier works as expected if you choose .vertical value for the axis parameter. And it also supports range now:
TextField("Title", text: $text, axis: .vertical)
.lineLimit(5...10)
Since iOS 14
Form iOS 14 and with Xcode 12, it's available as TextEditor
struct ContentView: View {
#State var text: String = "Multiline \ntext \nis called \nTextEditor"
var body: some View {
TextEditor(text: $text)
}
}
iOS 13
Also, if you want to support iOS 13, you can take at look this answer to port UITextField inside SwiftUI with full access to all of its properties.
iOS 16.0+ supprts multiline TextField.
struct ContentView: View {
#State private var description: String = """
Join us, and let's force unwrap SwiftUl's
birthday presents. Note that although
this activity is optional, we may have
guards at the entry.
"""
var body: some View {
Form {
TextField("Description", text: $description, axis: .vertical)
.lineLimit(5) // You can restrict min & max visible lines
}
}
}
Related
I'm trying to have a vertically growing TextField in `SwiftUI but also have the software keyboard have a custom submission method.
This uses the new functionality of iOS 16's TextFields being able to take an axis as an argument for which way it should grow. See the docs here: https://developer.apple.com/documentation/swiftui/textfield/init(_:text:axis:)-8rujz.
Here's a sample ContentView showing the setup.
struct ContentView: View {
#State var message: String = ""
var body: some View {
VStack {
Text("Try to submit this using the blue send button on the software keyboard")
TextField("Placeholder", text: $message, axis: .vertical)
.onSubmit {
print("submission!")
}
.submitLabel(.send)
}
}
}
When you run this, you can see the TextField properly grows vertically, but even when you have a custom submission label, pressing the blue "send" button in the software keyboard on iOS just inserts a newline, rather than firing the .onSubmit
When using a hardware keyboard, pressing the return does run the code in .onSubmit, so this seemingly just a limitation of the software keyboard.
I am using the following code (example) to render a SwiftUI Picker on iOS:
let strings: [String] = ["short", "very, ver long string"]
#State var selectedString: String = ""
Form {
Picker("Method", selection: $selectedString) {
ForEach(strings, id: \.self) { string in
Text(string)
}
}
}
In iOS 16 the design of the menu style picker has changed (it now includes 2 small chevrons), which is all good, except it no longer fills the available width (as it did on iOS 15). This results in longer strings flowing onto multiple lines even when this isn't neccessary.
Short String (all fine):
Long String (not so good):
I have tried .fixedSize(), which works to some extend but if the string does in fact need to be on two lines this forces the label to be squished. If I add a background to the Picker, it is clear that it only fills around 1/3 of the available space.
Does anyone have any suggestions?
Separate the label from the Picker and wrap it in a HStack.
Form {
HStack {
// the new label text
Text("Method")
.fixedSize() // give other views in HStack space to grow
// push the external label and Picker to the leading and trailing view edges
Spacer()
Picker("Method", selection: $selectedString) {
ForEach(strings, id: \.self) { string in
Text(string)
}
}
.labelsHidden() // the label is in the Text view
}
}
Hide the Picker label by using the .labelsHidden() modifier.
Use the .fixedSize() modifier on the new Text. This will allow the Picker to expand to fit all its contents.
Use Spacer between Text label and Picker to push both items to the edge.
I'm making a sign-in interface for iOS in SwiftUI. The user should be able to easily switch from the username text field to the password text field by tapping the "next" button on the software keyboard. It's working well but the keyboard always bounces a little when switching between the two text fields for some reason. Edit: As suggested in this answer I've added a Spacer into the VStack to make it fill the available space. The text fields aren't bouncing anymore but the keyboard unfortunately still is. I've updated the code and the GIF to reflect my changes.
After googling a little it seemed like this wasn't a very common issue. This question seemed to be similar to what happens to me but following the answer and wrapping the text fields in a ScrollView or a GeometryReader did not change anything at all. This is my code:
struct AuthenticationView: View {
#State var userName: String = ""
#State var userAuth: String = ""
#FocusState var currentFocus: FocusObject?
enum FocusObject: Hashable { case name, auth }
var body: some View {
VStack(spacing: 8) {
TextField("Username", text: $userName)
.focused($currentFocus, equals: .name)
.padding(8).background(Color.lightGray)
.cornerRadius(8).padding(.bottom, 8)
.textInputAutocapitalization(.never)
.onSubmit { currentFocus = .auth }
.autocorrectionDisabled(true)
.keyboardType(.asciiCapable)
.textContentType(.username)
.submitLabel(.next)
SecureField("Password", text: $userAuth)
.focused($currentFocus, equals: .auth)
.padding(8).background(Color.lightGray)
.cornerRadius(8).padding(.bottom, 16)
.textInputAutocapitalization(.never)
.onSubmit { currentFocus = nil }
.autocorrectionDisabled(true)
.keyboardType(.asciiCapable)
.textContentType(.password)
.submitLabel(.done)
Spacer() // This fixes the text fields
// But it does not fix the keyboard
}.padding(32)
}
}
Your current layout says:
Put the edit fields into a VStack.
Layout the VStack in the parent view by centering it in the available space. Note, that the VStack only uses a minimum size.
Now, when the keyboard appears, the available space of the parent view, i.e. its height, will be reduced accordingly.
Because the VStack is layout in the center, the text fields bounce up and down.
There are a couple of options:
Ensure the VStack extends its height and the text fields are aligned at the top. For example using a Spacer:
VStack(spacing: 8) {
TextField("Username", text: $userName)
...
SecureField("Password", text: $userAuth)
...
Spacer()
}.padding(32)
Using a ScrollView:
ScrollView {
Spacer(minLength: 80) // give some space at the top
VStack(spacing: 8) {
TextField("Username", text: $userName)
...
SecureField("Password", text: $userAuth)
...
}.padding(32)
}
It may not look pretty, but it should give you an idea, where to work on this issue (you may want to use a GeometryReader and a possibly a ScrollView to perfect your layout).
Another option is to use a Form. Put your fields into there, and with a Form you get also a head start which looks pretty nice. The reason why a Form works is because the same reasons why it works with a Spacer (aligns fields on top) and because of a ScrollView.
The fact that the keyboard disappears temporarily when you tap "Next" is unfortunate. I have no solution for this, so far.
I run into an issue I have no idea how to solve. I plan to have a shared code base for macOS and iOS with SwiftUI (as much as possible).
But already with something simple like setting background color for a text field there is a difference
Following code snippet:
struct NewTextField : View
{
#State var d:String = ""
var body: some View
{
HStack(content:
{
TextField("Date: ", text:$d)
.foregroundColor(.black)
.background(Color.green)
/// ... more views
}
}
}
This is simplified; I have multiple textfields on the real application with background colors depending on the content.
on iOS it looks ok; the full textfield background is set to the desired color; on macOS the TextField appear with white background and colored border.
What I'm doing wrong ?
just to leave it not unanswered:
added
.textFieldStyle(PlainTextFieldStyle())
and it create the desired effect
TextField("Date: ", text:$d)
.textFieldStyle(PlainTextFieldStyle())
.foregroundColor(.black)
.background(Color.green)
based on this post: SwiftUI customized text field in OSX
I have some trouble aligning TextFiled and Text in HStack.
The problem is with .lastTextBaseline alignment.
struct TextFieldCurrency: View {
#State var value = "32"
var body: some View {
HStack(alignment: .lastTextBaseline) {
TextField("price", text: $value)
.background(Color.yellow)
.modifier(TextFieldValueAppearance()) //font: 32
Text("PLN")
.background(Color.red)
.modifier(TextFiledUnitAppearance()) //font: 16
}.background(Color.green)
}
}
Code above produces this which is totally wrong.
But the same code with Text instead TextField.
So, my questions are:
Why this happen? How is TextField different from Text?
What is solution to baseline alignment?
I have Xcode 11.2 and Mac OS Catalina 10.15.0