SwiftUI, ako oživiť každý znak v textfield?

0

Otázka

Ako používateľ typy znakov v textfield, by som chcel zobraziť niektoré animácie na každom novo zadané znak (trochu ako Peňažné App oživuje čísla, ale chcel by som, aby ho pre abecedné znaky ako dobre).

enter image description here

Je to možné urobiť v SwiftUI? Moja intuícia je, že by som mohol most UIKit pre viac nuáns prístup k textfield"s prvkom, ale nie ste istí, ako to vlastne implementovať, že.

swift swiftui
2021-11-23 14:54:17
1

Najlepšiu odpoveď

1

Stačí vytvoriť "Falošné" TextField že sa objaví viac ako ten skutočný. Potom zobraziť znaky v ForEach.

To je robené s FocusState v iOS 15

@available(iOS 15.0, *)
struct AnimatedInputView: View {
    @FocusState private var isFocused: Int?
    @State var text: String = ""
    //If all the fonts match the cursor is better aligned 
    @State var font: Font = .system(size: 48, weight: .bold, design: .default)
    @State var color: Color = .gray
    var body: some View {
        HStack(alignment: .center, spacing: 0){
            //To maintain size in between the 2 views
            Text(text)
                .font(font)
                .opacity(0)
                .overlay(
                    //This textField will be invisible
                    TextField("", text: $text)
                        .font(font)
                        .foregroundColor(.clear)
                        .focused($isFocused, equals: 1)
                )
                .background(
                    ZStack{
                        HStack(alignment: .center, spacing: 0, content: {
                            //You need an array of unique/identifiable characters
                            let uniqueArray = text.uniqueCharacters()
                            ForEach(uniqueArray, id: \.id, content: { char in
                                CharView(char: char.char, isLast: char == uniqueArray.last, font: font)
                                
                            })
                        })
                    }.opacity(1)
                        .minimumScaleFactor(0.1)
                    
                )
            
                .onAppear(perform: {
                    //Bring focus to the hidden TextField
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
                        isFocused = 1
                    })
                })
        }
        .padding()
        .border(color)
        .font(.title)
        //Bring focus to the hidden textfield
        .onTapGesture {
            isFocused = 1
        }
    }
}
struct CharView: View{
    var char: Character
    var isLast: Bool
    var font: Font
    @State var scale: CGFloat = 0.75
    var body: some View{
        Text(char.description)
            .font(font)
            .minimumScaleFactor(0.1)
            .scaleEffect(scale)
            .onAppear(perform: {
                //Animate only if last character
                if isLast{
                    withAnimation(.linear(duration: 0.5)){
                        scale = 1
                    }
                }else{
                    scale = 1
                }
            })
    }
}
@available(iOS 15.0, *)
struct AnimatedInputView_Previews: PreviewProvider {
    static var previews: some View {
        AnimatedInputView()
    }
}
//Convert String to Unique characers
extension String{
    func uniqueCharacters() -> [UniqueCharacter]{
        let array: [Character] = Array(self)
        return array.uniqueCharacters()
    }
    func numberOnly() -> String {
        self.trimmingCharacters(in: CharacterSet(charactersIn: "-0123456789.").inverted)
    }
    
}
extension Array where Element == Character {
    
    func uniqueCharacters() -> [UniqueCharacter]{
        var array: [UniqueCharacter] = []
        
        for char in self{
            array.append(UniqueCharacter(char: char))
        }
        return array
    }
    
}

//String/Characters can be repeating so yu have to make them a unique value
struct UniqueCharacter: Identifiable, Equatable{
    var char: Character
    var id: UUID = UUID()
}

Tu je ukážka verzii. trvá len čísla ako kalkulačka vzorky

import SwiftUI

@available(iOS 15.0, *)
struct AnimatedInputView: View {
    @FocusState private var isFocused: Int?
    @State var text: String = ""
    //If all the fonts match the cursor is better aligned 
    @State var font: Font = .system(size: 48, weight: .bold, design: .default)
    @State var color: Color = .gray
    var body: some View {
        HStack(alignment: .center, spacing: 0){
            Text("$").font(font)
            //To maintain size in between the 2 views
            Text(text)
                .font(font)
                .opacity(0)
                .overlay(
                    //This textField will be invisible
                    TextField("", text: $text)
                        .font(font)
                        .foregroundColor(.clear)
                        .focused($isFocused, equals: 1)
                        .onChange(of: text, perform: { value in
                               if Double(text) == nil{
                                   //Leaves the negative and decimal period
                                   text = text.numberOnly()
                               }
                               //This condition can be improved.
                               //Checks for 2 occurences of the decimal period
                               //Possible solution
                               while text.components(separatedBy: ".").count > 2{
                                   color = .red
                                   text.removeLast()
                               }

                               //This condition can be improved.
                               //Checks for 2 occurences of the negative
                               //Possible solution
                               while text.components(separatedBy: "-").count > 2{
                                   color = .red
                                   text.removeLast()
                               }
                               color = .gray

                           })
                )
                .background(
                    ZStack{
                        HStack(alignment: .center, spacing: 0, content: {
                            //You need an array of unique/identifiable characters
                            let uniqueArray = text.uniqueCharacters()
                            ForEach(uniqueArray, id: \.id, content: { char in
                                CharView(char: char.char, isLast: char == uniqueArray.last, font: font)
                                
                            })
                        })
                    }.opacity(1)
                        .minimumScaleFactor(0.1)
                    
                )
            
                .onAppear(perform: {
                    //Bring focus to the hidden TextField
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
                        isFocused = 1
                    })
                })
        }
        .padding()
        .border(color)
        .font(.title)
        //Bring focus to the hidden textfield
        .onTapGesture {
            isFocused = 1
        }
    }
}
2021-11-24 02:45:46

Ďakujem. Myslíte si, že ak chcete zapnúť upravovanie, môžeme nejako programovo meniť z-index textfield a prekrytie textu? Možno použiť ZStack skôr ako prekrytie. A keď používateľ klikne na texte, sme si len priniesť Textfield na prednej strane pre úpravu a aktualizáciu char-pole na upraviť... je To zložité, ale ďakujem za riešenie!
PipEvangelist

Je to možné, ale veľmi zložité pravdepodobne náchylné na viac chýb.
lorem ipsum

@PipEvangelist Vlastne som zistil, iný spôsob, ako to urobiť. vyzerá to trošičku mimo, ale lepšia verzia. To umožňuje editáciu. Kurzor je len trochu mimo
lorem ipsum

Ďakujeme! Je to brilantná
PipEvangelist

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................