I experimenting with the SwiftUI TextField and want to get rid of the predictive suggestion bar above the keyboard:
struct ContentView: View {
#State private var text: String = ""
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
TextField("Hello", text: $text)
.autocorrectionDisabled()
.textContentType(.init(rawValue: ""))
}
.padding()
}
}
When typing, the predictive suggestions are still shown above the keyboard. Is there a way to get rid of these as well?
You need to use autocorrectionDisabled instead of disableAutocorrection, add .textContentType(.init(rawValue: "")) and don't forget to set the keyboard to .keyboardType(.asciiCapable). Default keyboard doesn't work. I don't know why.
struct ContentView: View {
#State private var text: String = ""
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
TextField("Hello", text: $text)
.keyboardType(.asciiCapable)
.autocorrectionDisabled(true)
.textContentType(.init(rawValue: ""))
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Related
I have a requirement where we need to keep close active unless bottom sheet is not closed. I have seen similar implementations in iOS maps where search keyboard is opened until the view is fully dismissed.
What I have currently :-
What I want :- https://drive.google.com/file/d/1SmXniFp0ZTF5igMzk6gk3eflCeP1xjn6/view?usp=share_link
This is code which i use to to present iOS native sheet :-
struct ContentView: View {
#State var isPresented = false
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.onTapGesture {
isPresented.toggle()
}
.sheet(isPresented: $isPresented) {
BottomSheetViewRepresentable(content: {
NavigationView {
DemoView()
}
.navigationTitle("Hey")
}, detents: [.large()])
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct DemoView: View {
var body: some View{
if #available(iOS 16.0, *) {
ZStack {
TextField("", text: .constant("Hey"))
}
.scrollDismissesKeyboard(.never)
} else {
// Fallback on earlier versions
Color.yellow
}
}
}
I see you have added .scrollDismissesKeyboard(.never) on the ZStack which seems not working.
Try wrapping content in a List or ScrollView, then set scrollDismissesKeyboard to never.
Examples -
var body: some View {
ScrollView {
VStack {
TextField("Name", text: $username)
.textFieldStyle(.roundedBorder)
TextEditor(text: $bio)
.frame(height: 400)
.border(.quaternary, width: 1)
}
.padding(.horizontal)
}
.scrollDismissesKeyboard(.never)
}
List example -
struct KeyboardDismissExample: View {
#State private var text = ""
var body: some View {
List {
ForEach(0..<100) { i in
TextField(("Item \(i)"), text: .constant(""))
}
}
.scrollDismissesKeyboard(.never)
}
}
I have a basic window with an input field (page 1), on top of it appears a popup window (page 2), inside of which there is also an input fields and buttons, which, when clicked, will bring up a small window with an input field (page 3). If there is no "Done" on the keyboard, the interface functions normally. If you add a "Done" button, it turns out that its color changes from system color blue to gray when moving from page 2 to page 3. Experimenting and wondering why this is so, I found that the toolbar on page 1 is responsible for the color of the button on page 3... If you change the color of the button on the toolbar on page 1 - it will change on the toolbar on page 3, and page 2 will not be affected. Also, adding buttons causes error: "[LayoutConstraints] Unable to simultaneously satisfy constraints." I want to understand why setting the button on the keyboard for Page 1, I also get a button when I type on Page 3? And why is it grayed out and not working? Why if I change the color for the button on Page 1, does it also change for that gray button on Page 3?
A small representative sample:
ContentView
import SwiftUI
struct ContentView: View {
#State private var bloodClucoseLvl: String = ""
#State private var isSheetShown: Bool = false
#FocusState private var focusField: Bool
var body: some View {
NavigationView {
List {
Section("Add your current blood glucose lvl") {
TextField("5,0 mmol/l", text: $bloodClucoseLvl)
.focused($focusField)
}
Section("Add food or drink") {
Button(action:{
isSheetShown.toggle()
}, label:{
HStack{
Text("Add")
Image(systemName: "folder.badge.plus")
}
})
.sheet(isPresented: $isSheetShown) {
addFoodButton()
}
}
}
.navigationTitle("Page 1 - General")
.toolbar{
ToolbarItem(placement: .keyboard) {
HStack {
Spacer()
Button(action: {
focusField = false
}) {
Text("Done")
}
}
}
}
.ignoresSafeArea(.keyboard)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
addFoodButton
import SwiftUI
struct addFoodButton: View {
#State private var selectedFood: String = ""
#State public var addScreen: Bool = false
var body: some View {
ZStack {
NavigationView {
List {
Section("or choose from category"){
NavigationLink(destination: Alcohol(addScreen: $addScreen)){
Text("Alcohol")
}
}
}
.listStyle(.insetGrouped)
.searchable(text: $selectedFood, prompt: "Search by word")
.navigationTitle("Page 2 - Search in DB")
}
if addScreen{
addScreenView(addScreen: $addScreen)
}
}
}
}
struct Alcohol: View {
#State private var searchInsideCategory: String = ""
#Binding var addScreen: Bool
var body: some View {
List {
Button(action: {addScreen.toggle()}){
Text("Light beer")
}
}
.navigationTitle("Page 2 - Choose beer")
.searchable(text: $searchInsideCategory, prompt: "Search inside a category")
}
}
struct addFoodButton_Previews: PreviewProvider {
static var previews: some View {
addFoodButton()
}
}
addScreenView
import SwiftUI
struct addScreenView: View {
#Binding var addScreen: Bool
#State private var gram: String = ""
var body: some View {
ZStack{
Color.black.opacity(0.2).ignoresSafeArea()
VStack(spacing:0){
Text("Page 3 - Add an item")
.bold()
.padding()
Divider()
VStack(){
TextField("gram", text: $gram)
.padding(.leading, 16)
.padding(.trailing, 16)
.keyboardType(.numberPad)
Rectangle()
.frame(height: 1)
.padding(.leading, 16)
.padding(.trailing, 16)
}.padding()
Divider()
HStack(){
Button(action: {
addScreen.toggle()
}){
Text("Cancel").frame(minWidth:0 , maxWidth: .infinity)
}
Divider()
Button(action: {
addScreen.toggle()
}){
Text("Save").frame(minWidth:0 , maxWidth: .infinity)
}
}.frame(height: 50)
}
.background(Color.white.cornerRadius(10))
.padding([.leading, .trailing], 15)
}
}
}
struct addScreenView_Previews: PreviewProvider {
static var previews: some View {
addScreenView(addScreen: .constant(true))
}
}
The navigationTitle is not working.
I use Swift5.5.2
In the preview there is no sign of the navigation title just an empty space.
struct ContentView: View {
#State private var firstname = ""
#State private var lastname = ""
#State private var birthdate = Date()
#State private var shouldSendNewsletter = false
var body: some View {
NavigationView {
Form {
Section(header: Text("Personal Information")) {
TextField("First Name", text: $firstname)
TextField("Last Name", text: $lastname)
DatePicker("Birth Date", selection: $birthdate, displayedComponents: .date)
Section(header: Text("Actions")) {
Toggle("Send Newsletter", isOn: $shouldSendNewsletter)
}//:Actions
}
}//:Form
}//: NAVIGATION VIEW
.navigationTitle("ABC")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Preview of navigation title
NavigationView is a container that hold ChildViews inside it. So .navigationTitle resides inside NavigationView, so in order to change navigationTitle we must call it from inside of NavigationView like this
NavigationView{
VStack{
}
.navigationTitle("ABC")
}
.navigationTitle("ABC") should be attached to the topmost view inside your NavigationView:
NavigationView {
Form {
Section(header: Text("Personal Information")) {
TextField("First Name", text: $firstname)
TextField("Last Name", text: $lastname)
DatePicker("Birth Date", selection: $birthdate, displayedComponents: .date)
Section(header: Text("Actions")) {
Toggle("Send Newsletter", isOn: $shouldSendNewsletter)
} //: Actions
}
} //: Form
.navigationTitle("ABC") /// <- here!
} //: NAVIGATION VIEW
i have made an app in SwiftUI where you can create different classes. The app saves this in an array. I have a textfield and a button in the same view as the scrollview that displays the array. This works perfectly fine and I can easily add new classes. Now I made a new view with a text field and a button. This view can be viewed by pressing a button in the nav bar. It uses the exact same function as the other view, but in the other view adding a item to the array works, in this view it doesn't work. I hope you understand my problem and can help me.
Thank You.
This is the file where I store the array:
import Foundation
import SwiftUI
import Combine
struct Class: Identifiable {
var name: String
var id = UUID()
}
class ClassStore: ObservableObject {
#Published var classes = [Class]()
}
This is the view with the button + textfield that works and the scrollview that displays the array:
import SwiftUI
struct ContentView: View {
#State var showNewClass = false
#ObservedObject var classStore = ClassStore()
#State var newClass: String = ""
#State var toDoColor: Color = Color.pink
func addNewClass() {
classStore.classes.append(
Class(name: newClass)
)
newClass = ""
}
var body: some View {
NavigationView {
VStack {
HStack {
TextField("New Todo", text: $newClass)
Image(systemName: "app.fill")
.foregroundColor(Color.pink)
.padding(.horizontal, 3)
Image(systemName: "books.vertical")
.padding(.horizontal, 3)
if newClass == "" {
Text("Add!")
.foregroundColor(Color.gray)
} else {
Button(action: {
addNewClass()
}) {
Text("Add!")
}
}
}.padding()
ScrollView {
ForEach(self.classStore.classes) { name in
Text(name.name)
}
}
.navigationBarTitle(Text("Schulnoten"))
.navigationBarItems(trailing:
Button(action: {
self.showNewClass.toggle()
}) {
Text("New Class")
}
.sheet(isPresented: $showNewClass) {
NewClass(isPresented: $showNewClass)
})
}
}
}
}
And this is the new view I created, the button and the textfield have the exact same code, but somehow this doesn't work:
import SwiftUI
struct NewClass: View {
#Binding var isPresented: Bool
#State var className: String = ""
#ObservedObject var classStore = ClassStore()
func addNewClass() {
classStore.classes.append(
Class(name: className)
)
}
var body: some View {
VStack {
HStack {
Text("New Class")
.font(.title)
.fontWeight(.semibold)
Spacer()
}
TextField("Name of the class", text: $className)
.padding()
.background(Color.gray)
.cornerRadius(5)
.padding(.vertical)
Button(action: {
addNewClass()
self.isPresented.toggle()
}) {
HStack {
Text("Safe")
.foregroundColor(Color.white)
.fontWeight(.bold)
.font(.system(size: 20))
}
.padding()
.frame(width: 380, height: 60)
.background(Color.blue)
.cornerRadius(5)
}
Spacer()
}.padding()
}
}
Sorry if my English is not that good. I'm not a native speaker.
I assume you should pass same class store from parent view into sheet, ie
struct NewClass: View {
#Binding var isPresented: Bool
#State var className: String = ""
#ObservedObject var classStore: ClassStore // << expect external
and in ContentView
.sheet(isPresented: $showNewClass) {
NewClass(isPresented: $showNewClass, classStore: self.classStore) // << here !!
})
I'm trying to create a TextField with a line below it, for that I used a Divide as suggested in this answer and I added a .onTapGesture() to it to change the Divider color, however that's a component that's embedded in another view.
In my ContentView I have a Button and my UnderscoredTextField and they are contained inside a HStack and it's contained inside a Background component (taken from this answer) to be able to dismiss the keyboard programmatically, but I'd like to be able to change the #State var isActive variable inside the UnderscoredTextField when that happens, but as I'm new to SwiftUI I'm not quite sure how to achieve this.
import SwiftUI
struct ContentView: View {
var body: some View {
Background {
UnderscoredTextField(phoneNumber: "")
}.onTapGesture {
self.hideKeyboard()
//How to tell my UnderscoreTextField's isActive variable to change
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import SwiftUI
struct UnderscoredTextField: View {
#State var phoneNumber: String
#State var isActive: Bool = false
var body: some View {
VStack {
TextField("12345678", text: $phoneNumber)
.keyboardType(.phonePad)
.onTapGesture {
self.isActive = true
}
Divider()
.padding(.horizontal)
.frame(height: 1)
.background(isActive ? Color.red : Color.gray)
}
}
}
struct UnderscoredTextField_Previews: PreviewProvider {
static var previews: some View {
UnderscoredTextField(phoneNumber: "12345678")
}
}
This is what it looks like when I hide the keyboard, but I'd like to switch it back to gray
If I understood correctly it is enough to use onEditingChanged, like below
var body: some View {
VStack {
TextField("12345678", text: $phoneNumber, onEditingChanged: {
self.isActive = $0 // << here !!
}).keyboardType(.phonePad)
Divider()
.padding(.horizontal)
.frame(height: 1)
.background(isActive ? Color.red : Color.gray)
}
}