Disable return key in swiftui textfield - swiftui

I want to enable pressing on the keyboard return key only when a condition occurs.
For example:
SecureField("", text:$password)
.focused($passwordFocused)
.onSubmit {
if password.count >= 8 {
joinNetwork()
}
}
.submitLabel(.join)
I want to make the return key disabled if the password does not hit the condition. Or at least change the color of the return button to gray.

use .onChange to update state variables as user types. here is a small example that changes the password bullet color from pink to black based on password length. alter this for your purposes
SecureField("", text:$password)
.onChange(of: password, perform: { _ in
isPasswordViable = (password.count >= 8)
})
.onSubmit {
guard isPasswordViable else { return }
print("submitted \(password)")
}
.foregroundColor(isPasswordViable ? .black : .pink)

Related

SwiftUI - Change List row background colour programatically

I'm trying to change the background colour of a row in a list based on a value
I have an Int16 value stored in card.owned and I want to change the background if this value is above 0, otherwise use the normal background.
Previously with a table view I could change it with the cellForRowAtIndexPath method, but not sure how to do it with SwiftUI without changing every row
Currently I have
List {
ForEach(cards) { section in
let header: String = nameForSectionHeader(sectionID: section.id)
Section(header: Text(header)) {
ForEach(section) { card in
NavigationLink(destination: CardView(card: card)) {
VStack(alignment: .leading) {
if let name = card.name, let id = card.cardID {
Text("\(id) - \(name)")
}
if let set = card.set, let setName = set.name {
Text("Set: \(setName)")
}
if card.owned > 0 {
Text("Owned: \(card.owned)")
}
}
}
}
}
}
.listRowBackground(lightGreen)
}

SwiftUI: How to know when view is moved inside scroll view?

I need some direction to resolve a problem. I have multiple videos inside a scroll view and I want only one of them to play at a time. I know about geo.frame to know the position of the view in screen but how can I constantly check if the screen moved to a point? I want to use this code in the video player view but I can only put this to .onAppear and it won't work because it is only called once. Is there a method that I can check when the screen is moved (scroll view is dragged) so that I can play the video in the middle and stop the other ones?
if (geo.frame(in: .global).midY > 200 && geo.frame(in: .global).midY < 800) {
avPlayer.play()
print("Global center: \(geo.frame(in: .global).midX) x \(geo.frame(in: .global).midY)")
print("Video to play: \(postID)")
}
You can put this code inside your view body using the Geometry reader. The value of geo is updated as the items are being scrolled and moved around.
Put this in a view of a row in your table of videos:
struct Example: View {
private func checkLocation(geo: GeometryProxy) -> Bool {
let loc = geo.frame(in: .global).midY
print ("Loc is: \(loc)")
if loc > 200 {
return true
}
return false
}
var body: some View {
GeometryReader { geo in
if checkLocation(geo: geo) {
Text ("This is working")
}
}
}
}

SwiftUI - Wrong index with removeAll(where: )

I want to let the user remove an image in an array. When the image is pressed, an action sheet is presented so the user can confirm the removal of the image. The problem is that it removes the wrong image. It always removes the first image of the array.
#State var pickerResult: [SImage] = []
...
ScrollView(.horizontal, showsIndicators: true){
HStack{
ForEach(pickerResult) { simage in
Image(uiImage: simage.image)
.onTapGesture() {
imageActionSheetIsPresented = true
// This will work: self.pickerResult.removeAll(where: {$0.image == simage.image})
}
.actionSheet(isPresented: $imageActionSheetIsPresented) {
ActionSheet(title: Text("Do you want to remove the image?"), buttons: [
.default(Text("Remove image")){
self.pickerResult.removeAll(where: {$0.image == simage.image})
print(simage.id)
// Returns id of the first image in the array
},
.cancel()
])
}
}
}
}
As you see in the code, skipping the confirmation and letting the user remove the image with onTap will work just fine.
Some how 'simage' is always the first item in the array when using ActionSheet.
Here is the SImage:
struct SImage: Identifiable{
var id = UUID()
var image: UIImage
}

Assign a string value to a toggle switch in swiftui

i have a form that works correctly but would like to add a toggle to indicated if a garment is used or new. if it is new toggle on, if its used a condtion box will show where the user can input the garments condition.
when then toggle is on, i would like to set the value to static string value of "New"
code i have tried:
Form{
VStack {
Toggle(isOn: self.$itemNew) {
Text("is the item new?")
self.$Cond == "New"
}
if !itemNew {
TextField("Item Condition:", text: self.$Cond) {}
}
}
}
that code didnt seem to work, any pointers on where i should be looking to solve this one?
Thanks
You don't have to use a $, you can create a Binding manually like this:
Toggle(isOn: Binding(get: {self.cond == "New" ? true : false},
set: {
if newValue == true{
self.cond == "New"
}else{
self.cond == "Not really new"
}
})) {
Text("is the item new?")
}
And the self.cond is still must be a #State variable to trigger View update its visual presentation.
But your case isn't look very ordinary for that instrument. Is there other possible values of the string?

Check state of Option-Key in SwiftUI (macOS)

I'm looking for a way to check the state of the option-key in SwiftUI on macOS.
I.e. depending on whether the option key is pressed or not I want to perform different actions in the .onTapGesture closure.
macOS-only SwiftUI has .modifiers modifier to specify EventModifiers, so your case is covered like in below example:
Rectangle()
.fill(Color.yellow)
.frame(width: 100, height: 40)
.gesture(TapGesture().modifiers(.option).onEnded {
print("Do anyting on OPTION+CLICK")
})
.onTapGesture {
print("Do anyting on CLICK")
}
While using the modifiers method on the gesture should probably be preferred, one can also actually test for the option key itself using CGEventSource in CoreGraphics:
import CoreGraphics
extension CGKeyCode
{
static let kVK_Option : CGKeyCode = 0x3A
static let kVK_RightOption: CGKeyCode = 0x3D
var isPressed: Bool {
CGEventSource.keyState(.combinedSessionState, key: self)
}
static var optionKeyPressed: Bool {
return Self.kVK_Option.isPressed || Self.kVK_RightOption.isPressed
}
}
This lets you detect the option key (or any other keys for that matter) in contexts where there isn't a modifier property or method.
The key codes in the extension can be renamed to be more Swifty, but those are the names that go way back to Classic MacOS's Toolbox and were defined in Inside Macintosh. I have a gist containing all the old key codes.
2022
.onTapGesture {
if NSEvent.modifierFlags.contains(.option) {
print("Option key Tap")
} else {
print("Tap")
}
}
.onDrag {
if NSEvent.modifierFlags.contains(.option) {
return NSItemProvider(object: "\(item.id)" as NSString)
}
return NSItemProvider()
}