SwiftUI cum pentru a anima fiecare personaj în textfield?

0

Problema

Ca un utilizator tipuri de caractere într-un textfield, aș dori pentru a afișa unele animație pe fiecare nou caracter tastat (cam așa cum Numerar App animă numere, dar aș vrea să-l pună în aplicare pentru caractere alfabetice, precum și).

enter image description here

Este posibil să facă acest lucru în SwiftUI? Intuiția mea este că am putea avea la podul de la UIKit pentru mai nuanțată acces la o textfieldmodelului element, dar nu sunt sigur cum să pună în aplicare efectiv asta.

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

Cel mai bun răspuns

1

Puteți crea doar un "Fals" TextField care apare peste cel real. Apoi arată personajele într-un ForEach.

Aceasta se face cu FocusState în 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()
}

Aici este o versiune de probă care. nevoie doar de numere, cum ar fi calculator de proba

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

Multumesc. Crezi că pentru a permite editarea, putem cumva programatic schimba Z-index de text și textul de acoperire? Poate folosi un ZStack mai degrabă decât de suprapunere. Și atunci când utilizatorul face clic pe text, putem aduce Textfield în față pentru editarea și actualizarea char-matrice pe editare... e complex, dar vă mulțumesc pentru soluție!
PipEvangelist

Posibil, dar foarte complex, probabil predispus la mai multe bug-uri.
lorem ipsum

@PipEvangelist de Fapt, mi-am dat seama de un alt mod de a face asta. se pare un pic off, dar o versiune mai bună. Acesta permite editarea. Cursorul este doar un pic off
lorem ipsum

Vă mulțumesc! Acest lucru este genial
PipEvangelist

În alte limbi

Această pagină este în alte limbi

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