String Interpolation with Text View and Textfield in Swiftui - swiftui

Hi I'm wondering if there's any way to have string interpolation with a textfield and Text in Swiftui. Like
Text("hi \(TextField("Enter your name", $name)")

You can try below code
struct ContentView: View {
#State private var name = ""
var body: some View {
VStack{
TextField("Enter your name", text: $name)
Text("Hi \(name)")
}
}
}
Hope this is what you want

If you really want to do that you can put your statements in an Hstack like so:
import SwiftUI
struct SwiftUIView: View {
#State var name = ""
var body: some View {
HStack {
Text("Hi")
TextField("Name", text: $name)
.frame(width: (name.isEmpty ? 45 : 0) + CGFloat(name.count) * 9)
Text("blabla")
}
}
}
Note: This gives you a dynamic change, but not a perfect one Because the size of each character is different you will get a bigger whitespace at the end. I just choose 9 here, for char width. I still think having a extra Textfield and using the variable then later, is the better option.

Related

Best way to present a long Segmented Picker in Swift UI

I need some suggestions on presenting a segmented picker in Swift UI.
It is to display distinct time ranges (<15min, <30min, <45min) all the way to 120min.
It ends up being 8 segments. I am really not a fan of the scrolling picker as it not in theme what what I am looking for in presentation.
The problem with how it stands now is that the time unit is cut off with each segment showing "15.." and doesn't look clean.
I have put the segmented picker in a horizontal scroll view which looks okay but the user may not know to scroll.
One option I used but can't get to work out is splitting the one long segment into 2 separate views.
The problem is the user can select a segment from either pickers which is not what I want.
What I want is if the user selects one picker, the other one is not selectable or vice versa.
I have been messing with some formatting options, so please ignore that.
Is this possible?
Thanks is advance!
struct ContentView: View {
var body: some View {
VStack{
To60min()
To120min()
.foregroundColor(Color.red)
}
}}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}}
struct To60min: View {
#State private var selectedTimeRangeto60 = ""
#State private var timeRangesTo60 = ["15min", "30min", "45min", "60min"]
var body: some View {
Picker("", selection: $selectedTimeRangeto60) {
ForEach(timeRangesTo60, id: \.self) {
Text($0)
}
}
.frame(width: .infinity, height: 75)
.background(.gray)
.padding()
.pickerStyle(.segmented)
.contrast(22.0)
}
}
struct To120min: View {
#State private var selectedTimeRangeto120 = ""
#State private var timeRangesTo120 = ["75min", "90min", "105min", "120min"]
var body: some View {
Picker("", selection: $selectedTimeRangeto120) {
ForEach(timeRangesTo120, id: \.self) {
Text($0)
}
}
.padding()
.pickerStyle(.segmented)
.contrast(22)
}
}
For anything more than 3-4 items (depending on label length), I would switch from a .segmented to .menu picker style. https://developer.apple.com/documentation/swiftui/pickerstyle

Storing restoring text upon rebuild of `TextEditor` in `LazyVStack`

I'm using LazyVStack to list TextEditor objects. But it rebuilds while scrolling (as expected in Lazystacks) but I want to restore the text I was typing in each Text Editor. I'm thinking of using objectIndex and saving it to String array to save and retrieve the text. I don't wanna use Non-Lazy stacks. Any other better ideas to store and restore the text?
import SwiftUI
struct ContentView: View {
#State private var text: String = ""
var body: some View {
VStack {
ScrollView {
LazyVStack {
ForEach(0..<20, id: \.self) { objectIndex in
VStack {
TextEditorObject (text: text)
}
}
}
}
}
}
}
struct TextEditorObject: View {
#State var text: String
var body: some View {
VStack {
VStack {
TextEditor (text: $text)
.frame(width: 200, height: 200, alignment: .leading)
}
}
}
}
In TextEditorObject change #State var text: String to #Binding var text: String

TextField swiftui xcode 13

I have been working with xcode 12 and swiftui. In my app I have textFiel with a localizable placeholder in Spanish and English, I switch to xcode 13 and it doesn't show me my localizable placeholder
this only happens in TextField, with SecureField it does not happen even with Text
this is my code
struct ContentView: View {
#State var email:String = ""
var body: some View {
VStack () {
TextField("login5", text: self.$email)
.autocapitalization(.none)
.padding()
.background(RoundedRectangle(cornerRadius: 50).stroke(Color("grayColor")))
}.padding(.horizontal, 20)
}
}
Localizable.strings
"login5" = "Correo eléctronico";
with SecureField in ios15, you can use the prompt parameter to get your localized string:
SecureField("purpose", text: $password, prompt: Text("login6"))
or using the label:
SecureField(text: $password) {
Text("login6")
}
EDIT1:
This is the test code I'm using to show a working localized TextField and SecureField.
import SwiftUI
#main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
#State var email = ""
#State var password = ""
#State var isVisible = false
var body: some View {
VStack (spacing: 55) {
Button(action: { isVisible.toggle() }) {
Text("Toggle isVisible")
}
TextField("login5", text: $email).border(.black)
if isVisible {
TextField("login6", text: $password).border(.green)
} else {
SecureField("password", text: $password, prompt: Text("login6")).border(.red)
}
}.padding(.horizontal, 20)
}
}
Test Localizable.strings file.
"login5" = "hola login5";
"login6" = "contraseña";
EDIT2: alternative approach of manually using LocalizedStringKey,
TextField(LocalizedStringKey("login5"), text: $email)
Your main Problem is, like workingdog already said, you need to use text: $variable.
That means for you declare your variable as #State var password = "" and use it like this..
struct ContentView: View {
#State var password = ""
...
if self.visible{
TextField("login6", text: $password)
....
} else {
SecureField("login6", text: $password)
....
}
}
Btw. next time post your code as code not as picture. Its easier to help you :)
Hope I understand your problem correctly and this will be your solution.
I've had the exact same problem, going from Xcode 12 to 13. All of a sudden some (not all) of my text fields no longer show localized string. I was able to fix the problem by forcing:
TextField(LocalizedString("usernameLabel"), text: $username)
Instead of
Textfield("usernameLabel", text: $username)

How to select an item by a button or tapGesture in my SwiftUI List and transfer it to another view

In my app I´m needing two players (only 2 names/strings), selected from an array built in a List/ForEach SwiftUI-code, which are used in another view.
What is the way to bring the name into a string for my Text(item)?
Can I select two items out of the list?
Thx for any help.
Franz
My code (modified, found by Ale Patron,Tutorial using UserDefaults with encoding and decoding the array/list ):
#State private var allTeams: [PlayerItem] = []
#State private var newPlayer = ""
#State private var selectedPlayer = ""
#State private var selection: String?
struct PlayerItem: Identifiable {
var id = UUID()
let player: String
}
var body: some View {
VStack{
HStack {
TextField("Add Players/Teams...", text: $newPlayer)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
self.allTeams.append(PlayerItem(player: self.newPlayer))
self.newPlayer = ""
}) {
Image(systemName: "plus")
}
.padding(.leading, 5)
}.padding()
List{
ForEach(allTeams) { playerItem in
Text(playerItem.player)
}
.onTapGesture {
print("How can I select my first und my second player")
}
}
Text("Selected Player: \(selectedPlayer)")
}
}
}
You should use indices for what you are trying to do.
Try this:
ForEach(allTeams.indices) { i in
Text(allTeams[i].player)
.onTapGesture {
print("How can I select my first und my second player")
print("The selected player is \(allTeams[i].player). The second player is \(allTeams[i + 1].player)"
}
}
Make sure to also check if the selected player is the last one in the array and to catch this. Otherwise, you may encounter an out-of-bounds error.

How to make a reusable TextPopUp in SwiftUI?

I am having trouble building a reusable SwiftUI text pop up view. I think the problem is the binding but I not sure. It is supposed to be a ContextMenu, but the reason I am not using ContextMenu is it does not show enough lines of text.
So far I have this...
struct TextPopUpView: View {
#EnvironmentObject var oracleViewModel: OracleViewModel
#Binding var showPopover: Bool
var displayedText: String
var popUpText: String
var body: some View {
Text("\(displayedText)")
.font(.title)
.fontWeight(.bold)
.onLongPressGesture {
self.showPopover = true
}
.popover(isPresented: $showPopover) {
Text("\(self.popUpText)")
.frame(width: 250.0)
.onTapGesture {
self.showPopover = false
}
}
}
}
And than I implement it for a particular view like so...
TextPopUpView(showPopover: $showPopover, displayedText: oracleViewModel.***someElement***, popUpText: oracleViewModel.getDescriptionFor***SomeElement***()).environmentObject(oracleViewModel)
where 'someElement' is the particular element text and popup text I want to show.
The problem is when I use TextPopUpView more than once in a view, the Popup view only displays the text for the last implementation on the said page.
I am guessing I am doing something wrong in the implementations of a reusable view, but I am not sure what. Any suggestions?
EDIT: (Example Used in code)
struct TopView: View {
#EnvironmentObject var oracleViewModel: OracleViewModel
#State private var showPopover: Bool = false
***Blarg Blarg Blarg***
VStack{
VStack {
Text("RUNE")
.font(.system(size:10))
.padding(.bottom, 5.0)
TextPopUpView(showPopover: $showPopover,
displayedText: oracleViewModel.rune,
popUpText: oracleViewModel.getDescriptionForRune()).environmentObject(oracleViewModel)
}
.padding(.bottom)
VStack {
Text("ELEMENT")
.font(.system(size:10))
.padding(.bottom, 5.0)
TextPopUpView(showPopover: $showPopover,
displayedText: oracleViewModel.element,
popUpText: oracleViewModel.getDescriptionForElement())
.environmentObject(oracleViewModel)
}
}
***Blarg Blarg Blarg***
}
(For some reason I only get the description for the Element, when I long press either view the TextPopUp is attached to)