আমি কীভাবে সুইফটআইআই-তে একটি মাল্টলাইন পাঠ্যফিল্ড তৈরি করব?


93

আমি সুইফটুইতে একটি বহুমাত্রিক টেক্সটফিল্ড তৈরি করার চেষ্টা করছি, তবে কীভাবে তা বুঝতে পারি না।

আমার কাছে বর্তমানে এই কোডটি রয়েছে:

struct EditorTextView : View {
    @Binding var text: String

    var body: some View {
        TextField($text)
            .lineLimit(4)
            .multilineTextAlignment(.leading)
            .frame(minWidth: 100, maxWidth: 200, minHeight: 100, maxHeight: .infinity, alignment: .topLeading)
    }
}

#if DEBUG
let sampleText = """
Very long line 1
Very long line 2
Very long line 3
Very long line 4
"""

struct EditorTextView_Previews : PreviewProvider {
    static var previews: some View {
        EditorTextView(text: .constant(sampleText))
            .previewLayout(.fixed(width: 200, height: 200))
    }
}
#endif

তবে এটি আউটপুট:

এখানে চিত্র বর্ণনা লিখুন


4
আমি কেবল লাইনলিমিট () ব্যবহার করে জিএম, এক্সকোড সংস্করণ 11.0 (11 এ 419 সি), জিএম-এ সুইফটুইয়ের সাথে একাধিক পাঠ্যক্ষেত্র তৈরি করার চেষ্টা করেছি। এটি এখনও কাজ করে না। আমি বিশ্বাস করতে পারি না অ্যাপল এটি এখনও ঠিক করে নি। একাধিক পাঠ্যক্ষেত্র মোবাইল অ্যাপ্লিকেশনগুলিতে মোটামুটি সাধারণ।
e987

উত্তর:


49

আপডেট: এক্সকোড 11 বিটা 4 এখন সমর্থন করে TextView, আমি খুঁজে পেয়েছি যে একটি মোড়ানো UITextViewএখনও কাজ করার জন্য সম্পাদনাযোগ্য মাল্টলাইন পাঠ্য পাওয়ার সেরা উপায়। উদাহরণস্বরূপ, TextViewডিসপ্লে গ্লিটস রয়েছে যেখানে পাঠ্যটি ভিউয়ের ভিতরে সঠিকভাবে উপস্থিত হয় না।

আসল (বিটা 1) উত্তর:

আপাতত, আপনি UITextViewএকটি কম্পোজেবল তৈরি করতে একটি মোড়ানো করতে পারেন View:

import SwiftUI
import Combine

final class UserData: BindableObject  {
    let didChange = PassthroughSubject<UserData, Never>()

    var text = "" {
        didSet {
            didChange.send(self)
        }
    }

    init(text: String) {
        self.text = text
    }
}

struct MultilineTextView: UIViewRepresentable {
    @Binding var text: String

    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.isScrollEnabled = true
        view.isEditable = true
        view.isUserInteractionEnabled = true
        return view
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = text
    }
}

struct ContentView : View {
    @State private var selection = 0
    @EnvironmentObject var userData: UserData

    var body: some View {
        TabbedView(selection: $selection){
            MultilineTextView(text: $userData.text)
                .tabItemLabel(Image("first"))
                .tag(0)
            Text("Second View")
                .font(.title)
                .tabItemLabel(Image("second"))
                .tag(1)
        }
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(UserData(
                text: """
                        Some longer text here
                        that spans a few lines
                        and runs on.
                        """
            ))

    }
}
#endif

এখানে চিত্র বর্ণনা লিখুন


দুর্দান্ত অস্থায়ী সমাধান! খাঁটি SwiftUI ব্যবহার করে এটি সমাধান না হওয়া অবধি আপাতত গ্রহণ।
গ্যাব্রিয়েলানটা

7
এই সমাধানটি আপনাকে এমন পাঠ্য প্রদর্শন করতে দেয় যা ইতিমধ্যে এতে নতুন লাইন রয়েছে, তবে এটি স্বাভাবিকভাবে দীর্ঘ লাইনগুলি ভাঙ্গা / মোড়ানো বলে মনে হয় না। (পাঠ্যটি কেবল ফ্রেমের বাইরে এক লাইনে অনুভূমিকভাবে বর্ধমান রাখে long
মাইকেল

6
যদি আমি স্থিতি (একটি প্রকাশকের সাথে পরিবেশগত বিষয়টির পরিবর্তে) ব্যবহার করি এবং এটি মাল্টলাইনটেক্সটভিউয়ের জন্য বাধ্যবাধকতা হিসাবে পাস করি তবে এটি কাজ করবে বলে মনে হয় না। আমি কীভাবে পরিবর্তনগুলিকে রাজ্যে প্রতিবিম্বিত করতে পারি?
ধূসর

এনভায়রনমেন্ট অবজেক্ট ব্যবহার না করে টেক্সটভিউতে কোনও ডিফল্ট পাঠ্য সেট করার কোনও উপায় আছে কি?
শিখুন 2

83

ঠিক আছে, আমি @ সাস অ্যাপ্রোচ দিয়ে শুরু করেছি, তবে বিষয়বস্তু ফিট করার সাথে এটি বহু-লাইন পাঠ্য ক্ষেত্র হিসাবে সত্যই দেখতে এবং বোধ করা দরকার I've আমি যা পেয়েছি তা এখানে। আশা করি এটি অন্য কারও জন্য সহায়ক হবে ... ব্যবহৃত এক্সকোড 11.1।

প্রদত্ত কাস্টম মাল্টলাইনটেক্সটফিল্ডটিতে রয়েছে:
1. কন্টেন্ট ফিট
2. অটোফোকাস
3. স্থানধারক
4. প্রতিশ্রুতিবদ্ধ

কন্টেন্ট ফিটের সাথে সুইফটুই মাল্টলাইন টেক্সটফিল্ডের পূর্বরূপ স্থানধারক যুক্ত হয়েছে

import SwiftUI
import UIKit

fileprivate struct UITextViewWrapper: UIViewRepresentable {
    typealias UIViewType = UITextView

    @Binding var text: String
    @Binding var calculatedHeight: CGFloat
    var onDone: (() -> Void)?

    func makeUIView(context: UIViewRepresentableContext<UITextViewWrapper>) -> UITextView {
        let textField = UITextView()
        textField.delegate = context.coordinator

        textField.isEditable = true
        textField.font = UIFont.preferredFont(forTextStyle: .body)
        textField.isSelectable = true
        textField.isUserInteractionEnabled = true
        textField.isScrollEnabled = false
        textField.backgroundColor = UIColor.clear
        if nil != onDone {
            textField.returnKeyType = .done
        }

        textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        return textField
    }

    func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<UITextViewWrapper>) {
        if uiView.text != self.text {
            uiView.text = self.text
        }
        if uiView.window != nil, !uiView.isFirstResponder {
            uiView.becomeFirstResponder()
        }
        UITextViewWrapper.recalculateHeight(view: uiView, result: $calculatedHeight)
    }

    fileprivate static func recalculateHeight(view: UIView, result: Binding<CGFloat>) {
        let newSize = view.sizeThatFits(CGSize(width: view.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        if result.wrappedValue != newSize.height {
            DispatchQueue.main.async {
                result.wrappedValue = newSize.height // !! must be called asynchronously
            }
        }
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(text: $text, height: $calculatedHeight, onDone: onDone)
    }

    final class Coordinator: NSObject, UITextViewDelegate {
        var text: Binding<String>
        var calculatedHeight: Binding<CGFloat>
        var onDone: (() -> Void)?

        init(text: Binding<String>, height: Binding<CGFloat>, onDone: (() -> Void)? = nil) {
            self.text = text
            self.calculatedHeight = height
            self.onDone = onDone
        }

        func textViewDidChange(_ uiView: UITextView) {
            text.wrappedValue = uiView.text
            UITextViewWrapper.recalculateHeight(view: uiView, result: calculatedHeight)
        }

        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            if let onDone = self.onDone, text == "\n" {
                textView.resignFirstResponder()
                onDone()
                return false
            }
            return true
        }
    }

}

struct MultilineTextField: View {

    private var placeholder: String
    private var onCommit: (() -> Void)?

    @Binding private var text: String
    private var internalText: Binding<String> {
        Binding<String>(get: { self.text } ) {
            self.text = $0
            self.showingPlaceholder = $0.isEmpty
        }
    }

    @State private var dynamicHeight: CGFloat = 100
    @State private var showingPlaceholder = false

    init (_ placeholder: String = "", text: Binding<String>, onCommit: (() -> Void)? = nil) {
        self.placeholder = placeholder
        self.onCommit = onCommit
        self._text = text
        self._showingPlaceholder = State<Bool>(initialValue: self.text.isEmpty)
    }

    var body: some View {
        UITextViewWrapper(text: self.internalText, calculatedHeight: $dynamicHeight, onDone: onCommit)
            .frame(minHeight: dynamicHeight, maxHeight: dynamicHeight)
            .background(placeholderView, alignment: .topLeading)
    }

    var placeholderView: some View {
        Group {
            if showingPlaceholder {
                Text(placeholder).foregroundColor(.gray)
                    .padding(.leading, 4)
                    .padding(.top, 8)
            }
        }
    }
}

#if DEBUG
struct MultilineTextField_Previews: PreviewProvider {
    static var test:String = ""//some very very very long description string to be initially wider than screen"
    static var testBinding = Binding<String>(get: { test }, set: {
//        print("New value: \($0)")
        test = $0 } )

    static var previews: some View {
        VStack(alignment: .leading) {
            Text("Description:")
            MultilineTextField("Enter some text here", text: testBinding, onCommit: {
                print("Final text: \(test)")
            })
                .overlay(RoundedRectangle(cornerRadius: 4).stroke(Color.black))
            Text("Something static here...")
            Spacer()
        }
        .padding()
    }
}
#endif

6
এছাড়াও আপনার backgroundColorসুইফটউআই UIColor.clearব্যবহার করে কাস্টম ব্যাকগ্রাউন্ড সক্ষম করতে ইউআইটিেক্সটফিল্ড সেট করার বিষয়ে এবং অটো-প্রথম সংবাদদাতাকে অপসারণ সম্পর্কে ভাবা উচিত, কারণ এটি একসাথে একাধিক ব্যবহার করার সময় ভেঙে যায় MultilineTextFields(প্রতিটি কীস্ট্রোক, সমস্ত পাঠ্য ক্ষেত্র আবার প্রতিক্রিয়াশীলকে পাওয়ার চেষ্টা করে)।
iComputerfreak

4
@ kdion4891 অন্য প্রশ্নের উত্তর হিসাবে যেমনটি ব্যাখ্যা করা হয়েছে , আপনি কেবল textField.textContainerInset = UIEdgeInsets.zero+ করতে পারেন textField.textContainer.lineFragmentPadding = 0এবং এটি দুর্দান্ত কাজ করে 👌🏻 @ এস্পেরি যদি আপনি উল্লিখিত হিসাবে করেন তবে আপনাকে অপসারণ করতে হবে .padding(.leading, 4)এবং .padding(.top, 8)অন্যথায় এটি ভাঙা দেখবে। এছাড়াও, আপনি স্থানধারীদের রঙের সাথে মেলানোর .foregroundColor(.gray)জন্য পরিবর্তন করতে পারেন (ডার্ক মোডের সাথে আপডেট হচ্ছে কিনা তা আমি চেক করিনি)। .foregroundColor(Color(UIColor.tertiaryLabel))TextField
রামি বি

4
ওহ, এবং আমিও পরিবর্তিত @State private var dynamicHeight: CGFloat = 100জন্য @State private var dynamicHeight: CGFloat = UIFont.systemFontSizeএকটি ছোট "সামান্য ত্রুটি" ফিক্স যখন MultilineTextFieldপ্রদর্শিত হয় (এটা একটি স্বল্প সময়ের জন্য বড় দেখায় এবং তারপর সঙ্কুচিত)।
রুমী বি

4
@ কিউইয়াস, আপনি সম্পর্কিত কোড সম্পর্কিত মন্তব্য বা মুছে ফেলতে পারেনuiView.becomeFirstResponder
Asperi

4
মন্তব্যের জন্য সবাইকে ধন্যবাদ! আমি আসলেই সেটি প্রশংসা করি. প্রদত্ত স্ন্যাপশটটি পদ্ধতির একটি ডেমো যা নির্দিষ্ট উদ্দেশ্যে কনফিগার করা হয়েছিল। আপনার সমস্ত প্রস্তাবনা সঠিক, তবে আপনার উদ্দেশ্যে। আপনি এই কোডটি অনুলিপি-অনুলিপি করতে পারবেন এবং আপনার উদ্দেশ্য হিসাবে যতটা ইচ্ছা এটি পুনরায় কনফিগার করতে পারেন।
Asperi

31

একটি দিয়ে Text()আপনি এটি অর্জন করতে পারেন .lineLimit(nil), এবং ডকুমেন্টেশনগুলি এটির জন্যও কাজ করা উচিত বলে প্রস্তাব দেয় TextField()। তবে আমি নিশ্চিত করতে পারি এটি বর্তমানে প্রত্যাশার মতো কাজ করে না।

আমি একটি ত্রুটি সন্দেহ করছি - প্রতিক্রিয়া সহকারীর সাথে একটি প্রতিবেদন দায়ের করার পরামর্শ দেব। আমি এটি করেছি এবং আইডিটি FB6124711।

সম্পাদনা: আইওএস 14 এর জন্য আপডেট করুন: TextEditorপরিবর্তে নতুনটি ব্যবহার করুন ।


এফবি 6124711 আইডি ব্যবহার করে বাগটি অনুসন্ধান করতে পারে এমন কোনও উপায় আছে? আমি মতামত সহকারী হিসাবে যাচাই করছি তবে এটি খুব বেশি সহায়ক নয়
CrazyPro007

আমি বিশ্বাস করি না যে এটি করার একটি উপায় আছে। তবে আপনি নিজের প্রতিবেদনে সেই আইডি উল্লেখ করতে পারেন, আপনার ব্যাখ্যা করা একই সমস্যাটির একগুণ। এটি ট্রিাইজ দলটিকে ইস্যুটির অগ্রাধিকার বাড়াতে সহায়তা করে।
অ্যান্ড্রু এবলিং

4
নিশ্চিত হয়েছে এটি এখনও Xcode সংস্করণ 11.0 বিটা 2 (11M337n) এ একটি সমস্যা
অ্যান্ড্রু এবলিং

4
নিশ্চিত হয়ে এটি Xcode সংস্করণ 11.0 বিটা 3 (11M362v) এ এখনও একটি সমস্যা। আপনি স্ট্রিংটিকে "কিছু te ntext" এ সেট করতে পারেন এবং এটি দুটি লাইনে প্রদর্শিত হবে, তবে নতুন কন্টেন্ট টাইপ করলে আপনার ভিউটির ফ্রেমের বাইরে পাঠ্যগুলির একটি লাইন অনুভূমিকভাবে বৃদ্ধি পাবে।
মাইকেল

4
এটি এখনও এক্সকোড 11.4 এ একটি সমস্যা - সিরিয়াসলি ??? এই জাতীয় বাগগুলির সাথে উত্পাদনে আমাদের কীভাবে সুইফ্টইউআই ব্যবহার করার কথা।
Trev14

29

এটি এক্সকোড সংস্করণ 11.0 বিটা 6-এ এখনও ইউআইটিএক্সটভিউ ভিউ মোড়ানো (এখনও এক্সকোড 11 জিএম সিড 2 এ কাজ করছে):

import SwiftUI

struct ContentView: View {
     @State var text = ""

       var body: some View {
        VStack {
            Text("text is: \(text)")
            TextView(
                text: $text
            )
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        }

       }
}

struct TextView: UIViewRepresentable {
    @Binding var text: String

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextView {

        let myTextView = UITextView()
        myTextView.delegate = context.coordinator

        myTextView.font = UIFont(name: "HelveticaNeue", size: 15)
        myTextView.isScrollEnabled = true
        myTextView.isEditable = true
        myTextView.isUserInteractionEnabled = true
        myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)

        return myTextView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = text
    }

    class Coordinator : NSObject, UITextViewDelegate {

        var parent: TextView

        init(_ uiTextView: TextView) {
            self.parent = uiTextView
        }

        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            return true
        }

        func textViewDidChange(_ textView: UITextView) {
            print("text now: \(String(describing: textView.text!))")
            self.parent.text = textView.text
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

4
টেক্সটফিল্ড এখনও এক্সকোড সংস্করণ 11.0 (11 এ 420 এ), জিএম বীজ 2, সেপ্টেম্বর, 2019
লাইন

4
এটি একটি ভিস্ট্যাকে ভাল কাজ করে তবে একটি তালিকা ব্যবহার করার সময় টেক্সটভিউয়ের সমস্ত পাঠ্য দেখানোর জন্য সারিটির উচ্চতা প্রসারিত হয় না। আমি কিছু জিনিস চেষ্টা করেছি: পরিবর্তন isScrollEnabledমধ্যে TextViewবাস্তবায়ন; টেক্সটভিউ ফ্রেমে একটি নির্দিষ্ট প্রস্থ নির্ধারণ; এমনকি টেক্সটভিউ এবং পাঠ্যকে একটি জেডস্ট্যাকের মধ্যে রেখে দেওয়া (এই আশায় যে সারিটি পাঠ্য দৃশ্যের উচ্চতার সাথে মিলিয়ে প্রসারিত হবে) তবে কিছুই কার্যকর হয় না। এই উত্তরটি কীভাবে তালিকায় কাজ করতে পারে সে সম্পর্কে কী কারও পরামর্শ আছে?
ম্যাথিউএস

@ মিও বাঁশিটি সামগ্রীর সাথে উচ্চতার সাথে মিল রেখে দূরে রয়েছে away
আবদুল্লাহ

আমি এসক্রলএনেবলকে ভুয়াতে পরিবর্তন করেছি এবং এটি কাজ করে, ধন্যবাদ।
আবদুল্লাহ

28

আইওএস 14

এটা কে বলে TextEditor

struct ContentView: View {
    @State var text: String = "Multiline \ntext \nis called \nTextEditor"

    var body: some View {
        TextEditor(text: $text)
    }
}

গতিশীল ক্রমবর্ধমান উচ্চতা:

আপনি টাইপ করার সাথে সাথে এটি বাড়তে চাইলে নীচের মতো লেবেল দিয়ে এম্বেড করুন:

ZStack {
    TextEditor(text: $text)
    Text(text).opacity(0).padding(.all, 8) // <- This will solve the issue if it is in the same ZStack
}

ডেমো

ডেমো


আইওএস 13

নেটিভ ইউআইটিেক্সটভিউ ব্যবহার করা

আপনি এই স্ট্রাক্টের সাহায্যে সরাসরি সুইফটইউআই কোডে নেটিভ ইউআইটিেক্সটভিউটি ব্যবহার করতে পারেন:

struct TextView: UIViewRepresentable {
    
    typealias UIViewType = UITextView
    var configuration = { (view: UIViewType) in }
    
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIViewType {
        UIViewType()
    }
    
    func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<Self>) {
        configuration(uiView)
    }
}

ব্যবহার

struct ContentView: View {
    var body: some View {
        TextView() {
            $0.textColor = .red
            // Any other setup you like
        }
    }
}

সুবিধাদি:

  • আইওএস 13 এর জন্য সমর্থন
  • উত্তরাধিকার কোড সহ ভাগ করা হয়েছে
  • বছরের পর বছর ধরে পরীক্ষিত UIKit
  • সম্পূর্ণ কাস্টমাইজযোগ্য
  • মূল অন্যান্য সমস্ত সুবিধা UITextView

4
যদি কেউ এই উত্তরের দিকে নজর দিচ্ছেন এবং ভাবছেন যে কীভাবে পাঠ্যদর্শন কাঠামায় প্রকৃত পাঠ্যটি প্রেরণ করা যায় তবে পাঠ্যের রঙ নির্ধারণ করে এমন একের নীচে নিম্নলিখিত লাইনটি যুক্ত করুন: $ 0.text = "কিছু পাঠ্য"
ম্যাটল

4
আপনি কীভাবে কোনও চলকটিকে পাঠ্যটিকে আবদ্ধ করেন? নাহলে লেখাটি পুনরুদ্ধার করবেন?
বায়োমিকার

4
প্রথম বিকল্পটিতে ইতিমধ্যে পাঠ্য বন্ধন রয়েছে। দ্বিতীয়টি একটি মান UITextView। আপনি সাধারণত ইউআইকিটিতে যেমন করেন তেমন আপনি তার সাথে ইন্টারঅ্যাক্ট করতে পারেন।
মোজতাবা হোসেইনি

13

বর্তমানে, টেক্সটভিউ নামে পরিচিত এই প্যাকেজটি ব্যবহার করা সবচেয়ে ভাল সমাধান ।

আপনি এটি সুইফট প্যাকেজ ম্যানেজার ব্যবহার করে ইনস্টল করতে পারেন (README তে বর্ণিত)। এটি টগল-সক্ষম সম্পাদনা স্থিতি এবং অসংখ্য কাস্টমাইজেশন (README তেও বিশদ) মঞ্জুরি দেয়।

এখানে একটি উদাহরণ:

import SwiftUI
import TextView

struct ContentView: View {
    @State var input = ""
    @State var isEditing = false

    var body: some View {
        VStack {
            Button(action: {
                self.isEditing.toggle()
            }) {
                Text("\(isEditing ? "Stop" : "Start") editing")
            }
            TextView(text: $input, isEditing: $isEditing)
        }
    }
}

এই উদাহরণে, আপনি প্রথমে দুটি @Stateভেরিয়েবল নির্ধারণ করুন । একটি হ'ল পাঠ্যের জন্য, যা পাঠ্য ভিউ যখনই টাইপ করা হয় তখন তা লিখে দেয় এবং অন্যটি isEditingটেক্সটভিউয়ের অবস্থার জন্য।

পাঠ্যদর্শনটি যখন নির্বাচিত হয় তখন isEditingরাষ্ট্রটিকে টগল করে । আপনি যখন বোতামটি ক্লিক করেন, এটি সেই স্থানে টোগল করে isEditingযা কীবোর্ডটি প্রদর্শন করবে এবং কখন পাঠ্যদর্শনটি নির্বাচন করবে trueএবং কখন পাঠ্যদর্শনটি অপসারণ করবে false


4
আমি রেপোতে একটি সমস্যা যুক্ত করব, তবে এটি Asperi এর মূল সমাধানের সাথে একই সমস্যা রয়েছে, এটি একটি ভিস্ট্যাকে দুর্দান্ত কাজ করে তবে কোনও স্ক্রোলভিউতে নয়।
রজার TheShrubber


সম্পাদনা করুন: আপনি ম্যাকোসকে লক্ষ্য করছেন তবে কাঠামোটি কেবল ইউআইভিউইপি সমর্থন করে ইউআইভিউর রিপ্রেজেন্টেবলের কারণে
অ্যালেক্স বার্তি

11

@ মিও বাঁশিটির উত্তর দুর্দান্ত! তবে এটি মাল্টিস্টেজ পাঠ্য ইনপুটটির জন্য কাজ করে না। এবং @ এস্পেরির উত্তরের সাথে মিলিত, এটির জন্য এখানেই স্থির এবং আমি কেবল মজাদার জন্য স্থানধারকের জন্য সমর্থনও যুক্ত করেছি!

struct TextView: UIViewRepresentable {
    var placeholder: String
    @Binding var text: String

    var minHeight: CGFloat
    @Binding var calculatedHeight: CGFloat

    init(placeholder: String, text: Binding<String>, minHeight: CGFloat, calculatedHeight: Binding<CGFloat>) {
        self.placeholder = placeholder
        self._text = text
        self.minHeight = minHeight
        self._calculatedHeight = calculatedHeight
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.delegate = context.coordinator

        // Decrease priority of content resistance, so content would not push external layout set in SwiftUI
        textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

        textView.isScrollEnabled = false
        textView.isEditable = true
        textView.isUserInteractionEnabled = true
        textView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)

        // Set the placeholder
        textView.text = placeholder
        textView.textColor = UIColor.lightGray

        return textView
    }

    func updateUIView(_ textView: UITextView, context: Context) {
        textView.text = self.text

        recalculateHeight(view: textView)
    }

    func recalculateHeight(view: UIView) {
        let newSize = view.sizeThatFits(CGSize(width: view.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        if minHeight < newSize.height && $calculatedHeight.wrappedValue != newSize.height {
            DispatchQueue.main.async {
                self.$calculatedHeight.wrappedValue = newSize.height // !! must be called asynchronously
            }
        } else if minHeight >= newSize.height && $calculatedHeight.wrappedValue != minHeight {
            DispatchQueue.main.async {
                self.$calculatedHeight.wrappedValue = self.minHeight // !! must be called asynchronously
            }
        }
    }

    class Coordinator : NSObject, UITextViewDelegate {

        var parent: TextView

        init(_ uiTextView: TextView) {
            self.parent = uiTextView
        }

        func textViewDidChange(_ textView: UITextView) {
            // This is needed for multistage text input (eg. Chinese, Japanese)
            if textView.markedTextRange == nil {
                parent.text = textView.text ?? String()
                parent.recalculateHeight(view: textView)
            }
        }

        func textViewDidBeginEditing(_ textView: UITextView) {
            if textView.textColor == UIColor.lightGray {
                textView.text = nil
                textView.textColor = UIColor.black
            }
        }

        func textViewDidEndEditing(_ textView: UITextView) {
            if textView.text.isEmpty {
                textView.text = parent.placeholder
                textView.textColor = UIColor.lightGray
            }
        }
    }
}

এটি এর মতো ব্যবহার করুন:

struct ContentView: View {
    @State var text: String = ""
    @State var textHeight: CGFloat = 150

    var body: some View {
        ScrollView {
            TextView(placeholder: "", text: self.$text, minHeight: self.textHeight, calculatedHeight: self.$textHeight)
            .frame(minHeight: self.textHeight, maxHeight: self.textHeight)
        }
    }
}

আমি এই পছন্দ। স্থানধারকটি কাজ করছে বলে মনে হচ্ছে না তবে এটি থেকে কার্যকর হয়েছিল। আমি ইউআইসিএলআর.লাইটের পরিবর্তে ইউআইসিওলর.লাইট্রে গ্রে এবং ইউআইসিওলর.লাবেলের পরিবর্তে ইউআইসিওলর.আরটিরিয়াল লেবেলের মতো শব্দার্থক রঙগুলি ব্যবহার করার পরামর্শ দিচ্ছি যাতে হালকা এবং গা dark় উভয় মোডই সমর্থনযোগ্য।
হেলাম

@ হেলাম আপনি বুঝতে পারছেন যে স্থানধারক কীভাবে কাজ করছেন না?
ড্যানিয়েল শেং

@DanielTseng এটি দেখায় না। এটা কেমন আচরণ করার কথা? আমি পাঠ্যটি খালি আছে কিনা তা দেখানোর প্রত্যাশা করছিলাম তবে এটি কখনই আমার জন্য প্রদর্শিত হয় না।
হেলাম

@ হেলাম, আমার উদাহরণে আমার কাছে স্থানধারক খালি থাকতে হবে। আপনি কি এটি অন্য কিছুতে পরিবর্তন করার চেষ্টা করেছেন? ("" এর পরিবর্তে "হ্যালো ওয়ার্ল্ড!")
ড্যানিয়েল তাসেং

হ্যাঁ আমার মধ্যে আমি এটি অন্য কিছু হতে সেট করেছি।
হেলাম

3

নিম্নলিখিত প্যারামিটারগুলির সাথে সুইফটউআই টেক্সটভিউ (ইউআইভিউউ রিসার্ভেটেবল) উপলব্ধ: ফন্ট স্টাইল, ইডেটেবল, ব্যাকগ্রাউন্ড কালার, বর্ডার কালার এবং বর্ডার প্রস্থ

টেক্সটভিউ (পাঠ্য: স্ব। $ ভিউমোডেল.টেক্সট, ফন্টস্টাইল: bodybody,

পাঠ্যদর্শন (ইউআইভিউর প্রত্যক্ষযোগ্য)

struct TextView: UIViewRepresentable {

@Binding var text: String
var fontStyle: UIFont.TextStyle
var isEditable: Bool
var backgroundColor: UIColor
var borderColor: UIColor
var borderWidth: CGFloat

func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

func makeUIView(context: Context) -> UITextView {

    let myTextView = UITextView()
    myTextView.delegate = context.coordinator

    myTextView.font = UIFont.preferredFont(forTextStyle: fontStyle)
    myTextView.isScrollEnabled = true
    myTextView.isEditable = isEditable
    myTextView.isUserInteractionEnabled = true
    myTextView.backgroundColor = backgroundColor
    myTextView.layer.borderColor = borderColor.cgColor
    myTextView.layer.borderWidth = borderWidth
    myTextView.layer.cornerRadius = 8
    return myTextView
}

func updateUIView(_ uiView: UITextView, context: Context) {
    uiView.text = text
}

class Coordinator : NSObject, UITextViewDelegate {

    var parent: TextView

    init(_ uiTextView: TextView) {
        self.parent = uiTextView
    }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        return true
    }

    func textViewDidChange(_ textView: UITextView) {
        self.parent.text = textView.text
    }
}

}


আমি কীভাবে মাল্টি লাইনের পাঠ্যক্ষেত্রে একটি ডিফল্ট পাঠ্য যুক্ত করব?
শিখুন কোড

3

এক্সকোড 12 এবং আইওএস 14 এর জন্য উপলব্ধ , এটি সত্যিই সহজ।

import SwiftUI

struct ContentView: View {
    
    @State private var text = "Hello world"
    
    var body: some View {
        TextEditor(text: $text)
    }
}

আপনি কেবল আইওএস 14 এর সাথে কাজ করছেন তা না হলে, ব্যবহারকারী এখনও আইওএস 13 এ থাকলে কি করতে পারে
ডি

3

MacOS বাস্তবায়ন

struct MultilineTextField: NSViewRepresentable {
    
    typealias NSViewType = NSTextView
    private let textView = NSTextView()
    @Binding var text: String
    
    func makeNSView(context: Context) -> NSTextView {
        textView.delegate = context.coordinator
        return textView
    }
    func updateNSView(_ nsView: NSTextView, context: Context) {
        nsView.string = text
    }
    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }
    class Coordinator: NSObject, NSTextViewDelegate {
        let parent: MultilineTextField
        init(_ textView: MultilineTextField) {
            parent = textView
        }
        func textDidChange(_ notification: Notification) {
            guard let textView = notification.object as? NSTextView else { return }
            self.parent.text = textView.string
        }
    }
}

এবং কিভাবে ব্যবহার করতে হয়

struct ContentView: View {

    @State var someString = ""

    var body: some View {
         MultilineTextField(text: $someString)
    }
}

0

আপনি কেবল ব্যবহার করতে পারেন TextEditor(text: $text)এবং তারপরে উচ্চতার মতো জিনিসের জন্য কোনও পরিবর্তনকারী যুক্ত করতে পারেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.