Home > Blockchain >  How to add a limit to the lines of text in a customized text field?
How to add a limit to the lines of text in a customized text field?

Time:01-26

I have a customized text field that allows me to write multiple lines of text. However, I am wondering if there is a way to limit how many lines this text field will allow you to write. Setting a frame doesn't seem to work, as once you pass the frame's limit, you just continue to scroll down new lines. Something like TikTok or Instagram's edit bio forms, which after a certain amount of returns, you can't go any further.

Here is what I have so far:

struct NewSnippetTextEditor : UIViewRepresentable {
    
    @Binding var txt : String
    
    var doppleGray = Color(hue: 1.0, saturation: 0.058, brightness: 0.396)
    
    @StateObject var profileData = ProfileViewModel()
    
    func makeCoordinator() -> NewSnippetTextEditor.NewSnippetCoordinator {
        
        return NewSnippetTextEditor.NewSnippetCoordinator(parent1: self)
    }
     
    func makeUIView(context: UIViewRepresentableContext<NewSnippetTextEditor>) -> UITextView {
        let tview = UITextView()
        tview.isEditable = true
        tview.isUserInteractionEnabled = true
        tview.isScrollEnabled = true
        tview.text = "What's up..."
        tview.textColor = .gray
        tview.font = .systemFont(ofSize: 18)
        tview.keyboardType = .twitter
        
        tview.delegate = context.coordinator
        return tview
    }
    
    func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<NewSnippetTextEditor>) {
        
    }
    
    class NewSnippetCoordinator : NSObject, UITextViewDelegate{
        
        var parent : NewSnippetTextEditor
        
        init(parent1 : NewSnippetTextEditor) {
            parent = parent1
        }
        
        func textViewDidChange(_ textView: UITextView) {
            self.parent.txt = textView.text
        }
        
        func textViewDidBeginEditing(_ textView: UITextView) {
            textView.text = ""
            textView.textColor = .label
            
        }
    }
    
}

And then to display this in a view I use:

NewSnippetTextEditor(txt: $newSnippetData.snippetTxt)
                .cornerRadius(20)
                .padding(EdgeInsets.init(top: 0, leading: 20, bottom: 0, trailing: 40))
                .opacity(newSnippetData.isPosting ? 0.5 : 1)
                .disabled(newSnippetData.isPosting ? true : false)

If this doesn't work for you, I also have another version that you might be able to better tweak.

struct NewSnippetTextView: UIViewRepresentable{
    @Binding var text:String
    @Binding var height:CGFloat
    var placeholderText: String
    @State var editing:Bool = false
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.isEditable = true
        textView.isScrollEnabled = true
        textView.text = placeholderText
        textView.delegate = context.coordinator
        textView.textColor = UIColor.white
        textView.backgroundColor = UIColor.black
        textView.font = UIFont.systemFont(ofSize: 18)
        textView.keyboardType = .twitter
        return textView
    }
    
    func updateUIView(_ textView: UITextView, context: Context) {
        if self.text.isEmpty == true{
            textView.text = self.editing ? "" : self.placeholderText
            textView.textColor = self.editing ? .white : .lightGray
        }
        
        DispatchQueue.main.async {
            self.height = textView.contentSize.height
            textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        }
    }
    
    func makeCoordinator() -> Coordinator {
        NewSnippetTextView.Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextViewDelegate{
        var parent: NewSnippetTextView
        
        init(_ params: NewSnippetTextView) {
            self.parent = params
        }
        
        func textViewDidBeginEditing(_ textView: UITextView) {
            DispatchQueue.main.async {
               self.parent.editing = true
            }
        }
        
        func textViewDidEndEditing(_ textView: UITextView) {
            DispatchQueue.main.async {
               self.parent.editing = false
            }
        }
        
        func textViewDidChange(_ textView: UITextView) {
            DispatchQueue.main.async {
                self.parent.height = textView.contentSize.height
                self.parent.text = textView.text
            }
        }
        
        
    }
    
}

To display this second version I used:

NewSnippetTextView(text: $newSnippetData.snippetTxt, height: $textViewHeight, placeholderText: "What's up")
                .frame(height: textViewHeight < 160 ? self.textViewHeight : 160)
                .cornerRadius(20)
                .padding(EdgeInsets.init(top: 0, leading: 20, bottom: 0, trailing: 40))
                .opacity(newSnippetData.isPosting ? 0.5 : 1)
                .disabled(newSnippetData.isPosting ? true : false)

CodePudding user response:

How about using a standard TextEditor and checking its length at change: (I admit it only counts characters, not lines, but you could implement that too by counting line breaks)

    TextEditor(text: $textInput)
        .onChange(of: textInput) { newValue in
            if newValue.count > 30 {
                textInput = String(newValue.dropLast(1))
            }
        }
  •  Tags:  
  • Related