SwiftUI ব্যবহার করার সময় কীবোর্ডটি কীভাবে আড়াল করবেন?


96

নীচের ক্ষেত্রে keyboardব্যবহার করে কীভাবে আড়াল SwiftUIকরবেন?

মামলা 1

যখন ব্যবহারকারী বাটনটি ক্লিক করেন তখন আমার কাছে TextFieldএবং আমার লুকানো দরকার ।keyboardreturn

মামলা 2

আমার আছে TextFieldএবং keyboardযখন ব্যবহারকারী বাইরে ট্যাপ করে তখন আমাকে লুকিয়ে রাখা দরকার ।

আমি কীভাবে এটি ব্যবহার করে করতে পারি SwiftUI?

বিঃদ্রঃ:

আমি কোন প্রশ্ন জিজ্ঞাসা করা হয়নি UITextField। আমি এটি ব্যবহার করে করতে চাই SwifUI.TextField


29
@ ড্যানিবুউনোকোর আমার প্রশ্নটি আবার মনোযোগ দিয়ে পড়ুন!
हितেশ সুরানী

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

4
@ ড্যানিবুউনোকোর ইউআইকিট এবং সুইফটইআইয়ের মধ্যে পার্থক্য জানতে দয়া করে বিকাশকারী.অ্যাপল .com/ ডকুমেন্টেশন / সুইফটুইয়ের দিকে নজর রেখেছেন। ধন্যবাদ
হিতেশ সুরানী

আমি আমার সমাধানটি এখানে যুক্ত করেছি আশা করি এটি আপনাকে সহায়তা করবে।
ভিক্টর কুশনারভ

এখানে বেশিরভাগ সমাধান পছন্দসই হিসাবে কাজ করে না, কারণ তারা অন্যান্য নিয়ন্ত্রণ নলের উপর পছন্দসই প্রতিক্রিয়া অক্ষম করে। একটি কার্যক্ষম সমাধান এখানে পাওয়া যাবে: forums.developer.apple.com/thread/127196
হার্ডি

উত্তর:


85

আপনি প্রথম উত্তরদাতাকে ভাগ করে নেওয়া অ্যাপ্লিকেশনটিতে কোনও পদক্ষেপ পাঠিয়ে পদত্যাগ করতে বাধ্য করতে পারেন:

extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

আপনি যখন ইচ্ছা তখন কীবোর্ডটি বন্ধ করতে এই পদ্ধতিটি ব্যবহার করতে পারেন:

struct ContentView : View {
    @State private var name: String = ""

    var body: some View {
        VStack {
            Text("Hello \(name)")
            TextField("Name...", text: self.$name) {
                // Called when the user tap the return button
                // see `onCommit` on TextField initializer.
                UIApplication.shared.endEditing()
            }
        }
    }
}

আপনি যদি কোনও টেপ আউট দিয়ে কীবোর্ডটি বন্ধ করতে চান, আপনি একটি ট্যাপ অ্যাকশন সহ একটি পূর্ণ স্ক্রিন সাদা ভিউ তৈরি করতে পারেন, এটি ট্রিগার করবে endEditing(_:):

struct Background<Content: View>: View {
    private var content: Content

    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content()
    }

    var body: some View {
        Color.white
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        .overlay(content)
    }
}

struct ContentView : View {
    @State private var name: String = ""

    var body: some View {
        Background {
            VStack {
                Text("Hello \(self.name)")
                TextField("Name...", text: self.$name) {
                    self.endEditing()
                }
            }
        }.onTapGesture {
            self.endEditing()
        }
    }

    private func endEditing() {
        UIApplication.shared.endEditing()
    }
}

4
.keyWindowএখন অবচয় করা হয়েছে। দেখুন Lorenzo, Santini এর উত্তর
লিনাসগফার্থ

4
এছাড়াও, .tapActionনামকরণ করা হয়েছে.onTapGesture
লিনাসগফার্থ

একটি বিকল্প নিয়ন্ত্রণ সক্রিয় হয়ে গেলে কিবোর্ডটি বরখাস্ত করা যেতে পারে? stackoverflow.com/questions/58643512/...
Yarm,

4
হোয়াইটব্যাকগ্রাউন্ড ছাড়াই এটি করার কোনও উপায় আছে, আমি স্পেসার ব্যবহার করছি এবং স্পেসারের উপর একটি ট্যাপ ইশারা শনাক্ত করার জন্য আমার এটির প্রয়োজন। এছাড়াও সাদা ব্যাকগ্রাউন্ড কৌশলটি নতুন আইফোনগুলিতে একটি সমস্যা তৈরি করে যেখানে এখন উপরে স্ক্রিনের অতিরিক্ত স্থান রয়েছে। কোন সাহায্য প্রশংসা!
জোসেফ আস্ট্রাহান

4
সম্ভবত এটি UIApplicationইউআইকিটির অংশ হিসাবেও লক্ষ্য করা উচিত, সুতরাং এটির প্রয়োজন import UIKit
Alienbash

62

অনেক চেষ্টার পরে আমি একটি সমাধান পেয়েছি যা (বর্তমানে) কোনও নিয়ন্ত্রণকে ব্লক করে না - এতে অঙ্গভঙ্গি সনাক্তকারীকে যুক্ত করে UIWindow

  1. আপনি যদি কেবল ট্যাপের বাইরের (ড্র্যাগগুলি পরিচালনা না করে) কীবোর্ডটি বন্ধ করতে চান - তবে এটি কেবল মাত্র UITapGestureRecognizerএবং কেবলমাত্র পদক্ষেপ 3 অনুলিপি করার জন্য যথেষ্ট :
  2. যে কোনও স্পর্শের সাথে কাজ করে এমন কাস্টম অঙ্গভঙ্গি সনাক্তকারী শ্রেণি তৈরি করুন:

    class AnyGestureRecognizer: UIGestureRecognizer {
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
            if let touchedView = touches.first?.view, touchedView is UIControl {
                state = .cancelled
    
            } else if let touchedView = touches.first?.view as? UITextView, touchedView.isEditable {
                state = .cancelled
    
            } else {
                state = .began
            }
        }
    
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
           state = .ended
        }
    
        override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
            state = .cancelled
        }
    }
    
  3. এর SceneDelegate.swiftমধ্যে func scene, পরবর্তী কোড যুক্ত করুন:

    let tapGesture = AnyGestureRecognizer(target: window, action:#selector(UIView.endEditing))
    tapGesture.requiresExclusiveTouchType = false
    tapGesture.cancelsTouchesInView = false
    tapGesture.delegate = self //I don't use window as delegate to minimize possible side effects
    window?.addGestureRecognizer(tapGesture)  
    
  4. UIGestureRecognizerDelegateএকযোগে ছোঁয়া দেওয়ার জন্য প্রয়োগ করুন ।

    extension SceneDelegate: UIGestureRecognizerDelegate {
        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
    }
    

এখন যে কোনও ভিউয়ের যে কোনও কীবোর্ড স্পর্শে বা বাইরে টানতে বন্ধ হবে।

পিএস যদি আপনি কেবলমাত্র নির্দিষ্ট পাঠ্যফিল্ডগুলি বন্ধ করতে চান - তবে যখনই পাঠ্যফিল্ডের কলব্যাক বলা হবে তখন উইন্ডোতে অঙ্গভঙ্গি সনাক্তকারী যুক্ত করুন এবং সরান onEditingChanged


4
এই উত্তরটি শীর্ষে থাকা উচিত। যখন ভিউতে অন্যান্য নিয়ন্ত্রণ থাকে তখন অন্যান্য উত্তরগুলি ব্যর্থ হয়।
ইমথাথ

4
@ রোল্যান্ডলারিওটি ​​এই আচরণটি ঠিক করার জন্য উত্তর আপডেট করেছেন, যেকোন জেচার রিকনগাইজার
মিখাইল

4
দুর্দান্ত উত্তর। নির্দোষভাবে কাজ করে। @ মিখাইল আসলে কীভাবে আপনি কিছু পাঠ্যক্ষেত্রের জন্য অঙ্গভঙ্গি সনাক্তকারীকে সরিয়ে ফেলবেন তা জানতে আগ্রহী (আমি ট্যাগগুলির সাথে একটি স্বয়ংসম্পূর্ণ তৈরি করেছি, তাই আমি যখনই তালিকায় কোনও উপাদান ট্যাপ করি, আমি চাই না যে এই নির্দিষ্ট পাঠ্য ক্ষেত্রটি ফোকাস হারাতে চাই)
পাস্তা

4
এই সমাধানটি আসলে দুর্দান্ত, তবে এটি 3 মাসের মতো ব্যবহারের পরে, দুর্ভাগ্যক্রমে আমি একটি বাগ খুঁজে পেয়েছি, যা সরাসরি এই ধরণের হ্যাকের কারণে ঘটে। দয়া করে, আপনার সাথে একই ঘটনা সম্পর্কে সচেতন থাকুন
কাচমোস

4
চমত্কার উত্তর! আমি অবাক হয়েছি কীভাবে এই সিন্ডিনিগ্রেট ছাড়াই আইওএস 14 দিয়ে প্রয়োগ করা হবে?
ডোম

27

@ আরয়ানটিসিবির উত্তর ভাল; এখানে কয়েকটি সংশোধন রয়েছে যা সম্ভাব্য ক্রাশটিকে ব্যবহার এবং এড়ানো সহজ করে তুলেছে:

struct DismissingKeyboard: ViewModifier {
    func body(content: Content) -> some View {
        content
            .onTapGesture {
                let keyWindow = UIApplication.shared.connectedScenes
                        .filter({$0.activationState == .foregroundActive})
                        .map({$0 as? UIWindowScene})
                        .compactMap({$0})
                        .first?.windows
                        .filter({$0.isKeyWindow}).first
                keyWindow?.endEditing(true)                    
        }
    }
}

'বাগ ফিক্স' কেবল এটি keyWindow!.endEditing(true)সঠিকভাবে হওয়া উচিত keyWindow?.endEditing(true)(হ্যাঁ, আপনি তর্ক করতে পারেন যে এটি হতে পারে না।)

আরও আকর্ষণীয় হ'ল আপনি কীভাবে এটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, ধরুন আপনার একাধিক সম্পাদনযোগ্য ক্ষেত্র রয়েছে। কেবল এটির মতো মোড়ানো:

Form {
    .
    .
    .
}
.modifier(DismissingKeyboard())

এখন, যে কন্ট্রোল নিজেই কোনও কীবোর্ড উপস্থাপন করে না তাতে আলতো চাপানো উপযুক্ত বরখাস্ত করবে।

(বিটা 7 দিয়ে পরীক্ষিত)


6
হুমম - অন্যান্য নিয়ন্ত্রণগুলিতে আলতো চাপলে আর নিবন্ধভুক্ত হয় না। অনুষ্ঠানটি গ্রাস করা হয়েছে।
Yarm,

আমি এটির অনুলিপি করতে পারি না - এটি এখনও 11/1 এর মধ্যে অ্যাপল থেকে সর্বশেষ ফোঁটাগুলি ব্যবহার করে আমার জন্য কাজ করছে। এটি কি কাজ করে এবং কেবল আপনার জন্য কাজ করা বন্ধ করে দিয়েছে, নাকি ??
ফিল্ডুর

ফর্মটিতে আপনার যদি ডেটপিকার থাকে তবে ডেটপিকারটি আর দেখানো হবে না
অ্যালবার্ট

@ অ্যালবার্ট - এটি সত্য; এই পদ্ধতির ব্যবহার করতে, আপনাকে বিচ্ছেদ করতে হবে যেখানে আইটেমগুলিকে DismissingKeyboard () দিয়ে সজ্জিত করা হবে একটি সূক্ষ্ম দানাদার স্তরে যা ডেটপিকারকে বরখাস্ত করা উচিত এবং এড়ানো উচিত to
ফিল্ডুর

এই কোডের ব্যবহার সতর্কতা পুনরুত্পাদন করবেCan't find keyplane that supports type 4 for keyboard iPhone-PortraitChoco-NumberPad; using 25686_PortraitChoco_iPhone-Simple-Pad_Default
np2314

25

নেভিগেশনভিউয়ের অভ্যন্তরে একটি টেক্সটফিল্ড ব্যবহার করার সময় আমি এটি অনুভব করেছি। এটি তার জন্য আমার সমাধান। আপনি স্ক্রোলিং শুরু করার সময় এটি কীবোর্ডকে বরখাস্ত করবে।

NavigationView {
    Form {
        Section {
            TextField("Receipt amount", text: $receiptAmount)
            .keyboardType(.decimalPad)
           }
        }
     }
     .gesture(DragGesture().onChanged{_ in UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)})

4
এটি অদ্ভুত আচরণে অনুলিপি (মুছতে মুছতে সোয়াইপ) করবে।
তারেক হাল্লাক

এটি দুর্দান্ত, তবে ট্যাপের কী হবে?
ড্যানিয়েলজানচি

21

কীবোর্ড খারিজ করার জন্য আমি অন্য একটি উপায় পেয়েছি যার জন্য keyWindowসম্পত্তি অ্যাক্সেসের প্রয়োজন নেই ; বিষয় হিসাবে সংকলক ব্যবহার করে একটি সতর্কতা ফিরে দেয়

UIApplication.shared.keyWindow?.endEditing(true)

আইওএস ১৩.০-তে 'কী উইন্ডো' অবমূল্যায়ন করা হয়েছিল: একাধিক দৃশ্যের সমর্থনকারী অ্যাপ্লিকেশনগুলির জন্য ব্যবহার করা উচিত নয় কারণ এটি সমস্ত সংযুক্ত দৃশ্যে কী উইন্ডোটি ফেরত দেয়

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

UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)

21

সুইফটুআই 2

এখানে সুইফ্টইউআই 2 / আইওএস 14 (মূলত এখানে মিখাইল দ্বারা প্রস্তাবিত ) এর একটি আপডেট সমাধান রয়েছে ।

আপনি যদি সুইফটইউআই লাইফেসাইকেলটি ব্যবহার করেন তবে এটি অনুপস্থিত AppDelegateএবং SceneDelegateযেটি অনুপস্থিত তা ব্যবহার করে না :

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
        }
    }
}

extension UIApplication {
    func addTapGestureRecognizer() {
        guard let window = windows.first else { return }
        let tapGesture = UITapGestureRecognizer(target: window, action: #selector(UIView.endEditing))
        tapGesture.requiresExclusiveTouchType = false
        tapGesture.cancelsTouchesInView = false
        tapGesture.delegate = self
        window.addGestureRecognizer(tapGesture)
    }
}

extension UIApplication: UIGestureRecognizerDelegate {
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true // set to `false` if you don't want to detect tap during other gestures
    }
}

লং প্রেসের অঙ্গভঙ্গি ব্যতীত একসাথে অঙ্গভঙ্গিগুলি কীভাবে সনাক্ত করা যায় তার একটি উদাহরণ এখানে রয়েছে:

extension UIApplication: UIGestureRecognizerDelegate {
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return !otherGestureRecognizer.isKind(of: UILongPressGestureRecognizer.self)
    }
}

4
এটি শীর্ষে থাকা উচিত কারণ নতুন সুইফটইউআই লাইফসাইকেলটি মনে রাখে।
carlosobedgomez

এটি দুর্দান্ত কাজ করে। তবে আমি যদি কোনও পাঠ্য ক্ষেত্রে ডাবল ট্যাপ করি, পরিবর্তে পাঠ্যটি নির্বাচন না করে এখন কীবোর্ডটি অদৃশ্য হয়ে যায়। আমি কীভাবে নির্বাচনের জন্য ডাবল আলতো চাপতে পারি?
গ্যারি

@ গ্যারি নীচের এক্সটেনশনে আপনি মন্তব্যটি মিথ্যাতে সেট করেছেন এমন লাইনটি দেখতে পাবেন যদি আপনি অন্য অঙ্গভঙ্গির সময় ট্যাপটি সনাক্ত করতে না চান । ঠিক সেট করা return false
pawello2222

এটি মিথ্যা কাজগুলিতে সেট করা, তবে তারপরে কেউ পাঠ্য অঞ্চলের বাইরে দীর্ঘ প্রেস বা ড্র্যাগ বা স্ক্রোল করে থাকলে কীবোর্ডটিও খারিজ হয় না। কেবলমাত্র ডাবল ক্লিকের জন্য এটিকে মিথ্যাতে সেট করার কোনও উপায় আছে (পাঠ্যের ক্ষেত্রের ভিতরে ডাবল ক্লিকগুলি কেবলমাত্র সমস্ত ডাবল ক্লিকগুলি করতে পারে)।
গ্যারি

4
আমার নিজের প্রশ্নের উত্তরের জন্য, আমি এটিকে আবার সত্যে সেট করে রেখেছি এবং তারপরে আমি টেপগেষ্টার = যিনিওগ্রেচারআরকনাইজার (...) সেট করেছিলাম যা মাইখাইল তার উত্তরে ট্যাপস্টেস্ট = ইউআইটিএপজেচার রেকগনিজার (...) এর পরিবর্তে তৈরি করেছিল। এটি ডাবল ট্যাপগুলি পাঠ্য ক্ষেত্রের মধ্যে পাঠ্য নির্বাচন করতে দেয় এবং বিভিন্ন অঙ্গভঙ্গিগুলি পাঠ্য ক্ষেত্রের বাইরে কীবোর্ডটি আড়াল করার অনুমতি দেয়।
গ্যারি

15

'SceneDelegate.swift' ফাইলটিতে SwiftUI কেবল যুক্ত করুন: .onTapGesture {window.endEditing (সত্য)}

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(
                rootView: contentView.onTapGesture { window.endEditing(true)}
            )
            self.window = window
            window.makeKeyAndVisible()
        }
    }

আপনার অ্যাপ্লিকেশনটিতে কীবোর্ড ব্যবহার করে প্রতিটি দর্শনের জন্য এটি যথেষ্ট is


4
এটি আরেকটি সমস্যা দেয় - আমার টেক্সটফিল্ডের পাশাপাশি ফর্ম {in এ একটি পিকার রয়েছে, এটি প্রতিক্রিয়াবিহীন হয়ে পড়ে। আমি এই বিষয়ের সমস্ত উত্তর ব্যবহার করে এর কোনও সমাধান পাইনি। তবে আপনার উত্তরটি অন্য কোনও কলের সাথে কীবোর্ড খারিজ করার জন্য ভাল - যদি আপনি পিকারগুলি ব্যবহার না করেন।
নালোভ

হ্যালো. আমার কোড `` `var বডি: কিছু দেখুন {নেভিগেশনভিউ {ফর্ম {বিভাগ {টেক্সটফিল্ড (" টাইপসমুথিং ", পাঠ্য: $ সি)} বিভাগ {পিকার (" নাম ", নির্বাচন: $ বিক্রয়) {ফ্রিচ (0 .. <200) ) {পাঠ্য ("(self.array [$ 0])%") where}} `` `অন্য কোথাও ট্যাপ করার সময় কীবোর্ডটি বরখাস্ত করা হয়, তবে পিক প্রতিক্রিয়াবিহীন হয়ে পড়ে। এটি কাজ করার কোনও উপায় আমি পাইনি।
নালোভ

4
হাই আবার, এই মুহূর্তে আমার দুটি সমাধান রয়েছে: প্রথমটি - হ'ল রিটার্ন বোতামে নেটিভ কীবোর্ড ব্যবহার করা, দ্বিতীয় - টিপিং হ্যান্ডলিংটি সামান্য পরিবর্তন করা হয় (ওরফে 'костыль') - উইন্ডো.রোটভিউকন্ট্রোলার = ইউআইহোস্টিংকন্ট্রোলার (রুটভিউ : কন্টেন্টভিউ.অনট্যাপজেষ্টার (গণনা: 2, সঞ্চালন: {উইন্ডো.এন্ডএডিটিং (সত্য)})) আশা করি এটি আপনাকে সহায়তা করবে ...
ডিম নোভো

হ্যালো. ধন্যবাদ. দ্বিতীয় উপায় এটি সমাধান। আমি সংখ্যাসূচক প্যাড ব্যবহার করছি, যাতে ব্যবহারকারীরা কেবল সংখ্যা লিখতে পারেন, এতে রিটার্ন কী নেই। টেপিংয়ের সাথে খারিজ করা যা আমি অনুসন্ধান করছিলাম।
নালোভ

এই কারণে নেভিগেট করা যাবে না কারণ।
চুই মিংদা

11

যখন ব্যবহারকারীরা বাইরে ট্যাপ করেন তখন কীভাবে সফ্টওয়্যার কীবোর্ডটি লুকানো যায় সে বিষয়ে আমার সমাধান। পুরো ভিউ কনটেইনার সনাক্ত করতে আপনাকে এটি ব্যবহার contentShapeকরতে onLongPressGestureহবে। onTapGestureফোকাস অবরুদ্ধ এড়ানো প্রয়োজন TextField। আপনি onTapGestureপরিবর্তে ব্যবহার করতে পারেন onLongPressGestureতবে নেভিগেশনবার আইটেমগুলি কাজ করবে না।

extension View {
    func endEditing() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

struct KeyboardAvoiderDemo: View {
    @State var text = ""
    var body: some View {
        VStack {
            TextField("Demo", text: self.$text)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .contentShape(Rectangle())
        .onTapGesture {}
        .onLongPressGesture(
            pressing: { isPressed in if isPressed { self.endEditing() } },
            perform: {})
    }
}

এটি দুর্দান্তভাবে কাজ করেছে, আমি এটি কিছুটা আলাদাভাবে ব্যবহার করেছি এবং এটি নিশ্চিত হওয়া উচিত যে এটি মূল থ্রেডে ডাকা হয়েছিল।
keegan3d

7

আপনি ব্যবহারকারীর টেপগুলি সনাক্ত করতে চান এমন দৃশ্যে এই সংশোধক যুক্ত করুন

.onTapGesture {
            let keyWindow = UIApplication.shared.connectedScenes
                               .filter({$0.activationState == .foregroundActive})
                               .map({$0 as? UIWindowScene})
                               .compactMap({$0})
                               .first?.windows
                               .filter({$0.isKeyWindow}).first
            keyWindow!.endEditing(true)

        }

7

আমি এটি ব্যবহার করতে পছন্দ করি .onLongPressGesture(minimumDuration: 0), যার ফলে অন্যটি TextViewসক্রিয় হওয়ার সময় কীবোর্ডটি জ্বলজ্বল করে না (এর পার্শ্ব প্রতিক্রিয়া .onTapGesture)। হাইড কীবোর্ড কোডটি পুনরায় ব্যবহারযোগ্য ফাংশন হতে পারে।

.onTapGesture(count: 2){} // UI is unresponsive without this line. Why?
.onLongPressGesture(minimumDuration: 0, maximumDistance: 0, pressing: nil, perform: hide_keyboard)

func hide_keyboard()
{
    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}

এখনও এই পদ্ধতিটি ব্যবহার করে একটি ঝাঁকুনি।
ড্যানিয়েল রায়ান

এটি দুর্দান্তভাবে কাজ করেছে, আমি এটি কিছুটা আলাদাভাবে ব্যবহার করেছি এবং এটি নিশ্চিত হওয়া উচিত যে এটি মূল থ্রেডে ডাকা হয়েছিল।
keegan3d

6

কারণ keyWindowহ্রাস করা হয়।

extension View {
    func endEditing(_ force: Bool) {
        UIApplication.shared.windows.forEach { $0.endEditing(force)}
    }
}

4
forceপ্যারামিটার ব্যবহার করা হয় না। এটি হওয়া উচিত{ $0.endEditing(force)}
ডেভিড

5

মনে হচ্ছে endEditingসমাধানটিই কেবলমাত্র @ রারাফেলের মতোই নির্দেশিত।
আমি এখনও পর্যন্ত সবচেয়ে পরিষ্কার উদাহরণটি হ'ল এটি হ'ল:

extension View {
    func endEditing(_ force: Bool) {
        UIApplication.shared.keyWindow?.endEditing(force)
    }
}

এবং তারপরে এটি ব্যবহার করুন onCommit:


4
.keyWindowএখন অবচয় করা হয়েছে। দেখুন Lorenzo, Santini এর উত্তর
লিনাসগফার্থ

এটি আইওএস 13+
অবহিত হয়েছে

4

@ ফিল্ডুর (যা @ রায়ানটিটিবি'র উপর ভিত্তি করে তৈরি হয়েছিল) এর উত্তরটি প্রসারিত করার জন্য এখানে একটি আরও উদ্বেগজনক এবং শক্তিশালী সমাধান যা আপনাকে অন্য ইশারাগুলিতে কীবোর্ডকে বরখাস্ত করার অনুমতি দেয় onTapGesture , আপনি ফাংশন কলে যা চান তা নির্দিষ্ট করতে পারেন।

ব্যবহার

// MARK: - View
extension RestoreAccountInputMnemonicScreen: View {
    var body: some View {
        List(viewModel.inputWords) { inputMnemonicWord in
            InputMnemonicCell(mnemonicInput: inputMnemonicWord)
        }
        .dismissKeyboard(on: [.tap, .drag])
    }
}

অথবা ব্যবহার করে All.gestures(কেবলমাত্র sugar এর জন্য চিনি Gestures.allCases)

.dismissKeyboard(on: All.gestures)

কোড

enum All {
    static let gestures = all(of: Gestures.self)

    private static func all<CI>(of _: CI.Type) -> CI.AllCases where CI: CaseIterable {
        return CI.allCases
    }
}

enum Gestures: Hashable, CaseIterable {
    case tap, longPress, drag, magnification, rotation
}

protocol ValueGesture: Gesture where Value: Equatable {
    func onChanged(_ action: @escaping (Value) -> Void) -> _ChangedGesture<Self>
}
extension LongPressGesture: ValueGesture {}
extension DragGesture: ValueGesture {}
extension MagnificationGesture: ValueGesture {}
extension RotationGesture: ValueGesture {}

extension Gestures {
    @discardableResult
    func apply<V>(to view: V, perform voidAction: @escaping () -> Void) -> AnyView where V: View {

        func highPrio<G>(
             gesture: G
        ) -> AnyView where G: ValueGesture {
            view.highPriorityGesture(
                gesture.onChanged { value in
                    _ = value
                    voidAction()
                }
            ).eraseToAny()
        }

        switch self {
        case .tap:
            // not `highPriorityGesture` since tapping is a common gesture, e.g. wanna allow users
            // to easily tap on a TextField in another cell in the case of a list of TextFields / Form
            return view.gesture(TapGesture().onEnded(voidAction)).eraseToAny()
        case .longPress: return highPrio(gesture: LongPressGesture())
        case .drag: return highPrio(gesture: DragGesture())
        case .magnification: return highPrio(gesture: MagnificationGesture())
        case .rotation: return highPrio(gesture: RotationGesture())
        }

    }
}

struct DismissingKeyboard: ViewModifier {

    var gestures: [Gestures] = Gestures.allCases

    dynamic func body(content: Content) -> some View {
        let action = {
            let forcing = true
            let keyWindow = UIApplication.shared.connectedScenes
                .filter({$0.activationState == .foregroundActive})
                .map({$0 as? UIWindowScene})
                .compactMap({$0})
                .first?.windows
                .filter({$0.isKeyWindow}).first
            keyWindow?.endEditing(forcing)
        }

        return gestures.reduce(content.eraseToAny()) { $1.apply(to: $0, perform: action) }
    }
}

extension View {
    dynamic func dismissKeyboard(on gestures: [Gestures] = Gestures.allCases) -> some View {
        return ModifiedContent(content: self, modifier: DismissingKeyboard(gestures: gestures))
    }
}

সাবধানতা শব্দ

দয়া করে মনে রাখবেন যে আপনি যদি সমস্ত অঙ্গভঙ্গি ব্যবহার করেন তবে তারা দ্বন্দ্ব বোধ করতে পারে এবং আমি এটিকে সমাধান করার জন্য কোনও ঝরঝরে সমাধান নিয়ে আসি নি।


এর অর্থ কী eraseToAny()
রবীন্দ্র_ভাটি

2

এই পদ্ধতি আপনি করতে পারবেন কীবোর্ড লুকাতে উপর ব্যবধান!

প্রথমে এই ফাংশনটি যুক্ত করুন (ক্রেডিট দেওয়া হয়েছে: ক্যাস্পার জ্যানডবারজান , সুইফটইউআই থেকে এইচস্ট্যাকের স্পেসারে ট্যাপ করতে পারবেন না )

extension Spacer {
    public func onTapGesture(count: Int = 1, perform action: @escaping () -> Void) -> some View {
        ZStack {
            Color.black.opacity(0.001).onTapGesture(count: count, perform: action)
            self
        }
    }
}

এরপরে নিম্নলিখিত 2 টি ফাংশন যুক্ত করুন (এতে ক্রেডিট দেওয়া হয়েছে: রাফেল, এই প্রশ্ন থেকে)

extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

নীচের ফাংশনটি আপনার ভিউ ক্লাসে যুক্ত করা হবে, আরও তথ্যের জন্য কেবল রাফেল থেকে এখানে শীর্ষের উত্তরটি দেখুন।

private func endEditing() {
   UIApplication.shared.endEditing()
}

অবশেষে, আপনি এখন কেবল কল করতে পারেন ...

Spacer().onTapGesture {
    self.endEditing()
}

এটি যে কোনও স্পেসার অঞ্চল এখনই কীবোর্ডটি বন্ধ করে দেবে। বড় সাদা পটভূমি আর দেখার দরকার নেই!

আপনি extensionবর্তমানে টেপগাস্টারগুলিকে সমর্থন করার দরকার নেই এমন কোনও নিয়ন্ত্রণে হাইপটিকভাবে এই কৌশলটি প্রয়োগ করতে পারেন যা আপনার ইচ্ছুক পরিস্থিতিতে কীবোর্ডটি বন্ধ করার onTapGestureসাথে ফাংশনটিকে একত্রে কল করে self.endEditing()


এখন আমার প্রশ্ন হ'ল আপনি কী-বোর্ডটি এভাবে চলে যেতে যেতে পাঠ্যক্ষেত্রের প্রতিশ্রুতিটি কীভাবে ট্রিগার করবেন? আপনি যদি আইওএস কীবোর্ডে রিটার্ন কীটি চাপান তবে কেবল 'কমিট' কেবল ট্রিগার করবে।
জোসেফ আস্ট্রাহান

2

দয়া করে https://github.com/michaelhenry/KeyboardAvoider দেখুন

কেবলমাত্র KeyboardAvoider {}আপনার মূল দর্শনের উপরে অন্তর্ভুক্ত করুন এবং এটিই।

KeyboardAvoider {
    VStack { 
        TextField()
        TextField()
        TextField()
        TextField()
    }

}

এটি টেক্সটফিল্ড সহ কোনও ফর্ম দৃশ্যের জন্য কাজ করে না। ফর্ম প্রদর্শিত হবে না।
নীল

2

@ সাজোনের উত্তরের ভিত্তিতে, এখানে এমন একটি সমাধান রয়েছে যা আপনাকে আপনার পছন্দ অনুসারে ট্যাপ, লম্বা প্রেস, ড্রাগ, ম্যাগনিফিকেশন এবং রোটেশনের অঙ্গভঙ্গিতে কীবোর্ড খারিজ করতে দেয়।

এই সমাধানটি এক্সকোড 11.4 এ কাজ করছে

@ আইএমহিটেশুরানী জিজ্ঞাসা করা আচরণটি পাওয়ার জন্য ব্যবহার

struct MyView: View {
    @State var myText = ""

    var body: some View {
        VStack {
            DismissingKeyboardSpacer()

            HStack {
                TextField("My Text", text: $myText)

                Button("Return", action: {})
                    .dismissKeyboard(on: [.longPress])
            }

            DismissingKeyboardSpacer()
        }
    }
}

struct DismissingKeyboardSpacer: View {
    var body: some View {
        ZStack {
            Color.black.opacity(0.0001)

            Spacer()
        }
        .dismissKeyboard(on: Gestures.allCases)
    }
}

কোড

enum All {
    static let gestures = all(of: Gestures.self)

    private static func all<CI>(of _: CI.Type) -> CI.AllCases where CI: CaseIterable {
        return CI.allCases
    }
}

enum Gestures: Hashable, CaseIterable {
    case tap, longPress, drag, magnification, rotation
}

protocol ValueGesture: Gesture where Value: Equatable {
    func onChanged(_ action: @escaping (Value) -> Void) -> _ChangedGesture<Self>
}

extension LongPressGesture: ValueGesture {}
extension DragGesture: ValueGesture {}
extension MagnificationGesture: ValueGesture {}
extension RotationGesture: ValueGesture {}

extension Gestures {
    @discardableResult
    func apply<V>(to view: V, perform voidAction: @escaping () -> Void) -> AnyView where V: View {

        func highPrio<G>(gesture: G) -> AnyView where G: ValueGesture {
            AnyView(view.highPriorityGesture(
                gesture.onChanged { _ in
                    voidAction()
                }
            ))
        }

        switch self {
        case .tap:
            return AnyView(view.gesture(TapGesture().onEnded(voidAction)))
        case .longPress:
            return highPrio(gesture: LongPressGesture())
        case .drag:
            return highPrio(gesture: DragGesture())
        case .magnification:
            return highPrio(gesture: MagnificationGesture())
        case .rotation:
            return highPrio(gesture: RotationGesture())
        }
    }
}

struct DismissingKeyboard: ViewModifier {
    var gestures: [Gestures] = Gestures.allCases

    dynamic func body(content: Content) -> some View {
        let action = {
            let forcing = true
            let keyWindow = UIApplication.shared.connectedScenes
                .filter({$0.activationState == .foregroundActive})
                .map({$0 as? UIWindowScene})
                .compactMap({$0})
                .first?.windows
                .filter({$0.isKeyWindow}).first
            keyWindow?.endEditing(forcing)
        }

        return gestures.reduce(AnyView(content)) { $1.apply(to: $0, perform: action) }
    }
}

extension View {
    dynamic func dismissKeyboard(on gestures: [Gestures] = Gestures.allCases) -> some View {
        return ModifiedContent(content: self, modifier: DismissingKeyboard(gestures: gestures))
    }
}

2

আপনি সম্পূর্ণরূপে UIKit এর সাথে মিথস্ক্রিয়া এড়াতে এবং খাঁটি SwiftUI এ এটি প্রয়োগ করতে পারেন । কেবল .id(<your id>)আপনার একটি TextFieldপরিবর্তনকারী যুক্ত করুন এবং যখনই আপনি কীবোর্ডকে বরখাস্ত করতে চান তখনই এর মান পরিবর্তন করুন (সোয়াইপে, টিপুন, বোতামের ক্রিয়া, ..)।

নমুনা বাস্তবায়ন:

struct MyView: View {
    @State private var text: String = ""
    @State private var textFieldId: String = UUID().uuidString

    var body: some View {
        VStack {
            TextField("Type here", text: $text)
                .id(textFieldId)

            Spacer()

            Button("Dismiss", action: { textFieldId = UUID().uuidString })
        }
    }
}

মনে রাখবেন যে আমি এটি সর্বশেষতম এক্সকোড 12 বিটাতে পরীক্ষা করেছি, তবে এটি কোনও সমস্যা ছাড়াই পুরানো সংস্করণগুলি (এমনকি এক্সকোড 11) দিয়ে কাজ করা উচিত।


1

কীবোর্ডের Returnকী

টেক্সটফিল্ডের বাইরে আলতো চাপতে সমস্ত উত্তর ছাড়াও, ব্যবহারকারী যখন কীবোর্ডে রিটার্ন কীটি টিপেন তখন আপনি কীবোর্ডটি খারিজ করতে চাইতে পারেন:

এই গ্লোবাল ফাংশনটি সংজ্ঞায়িত করুন:

func resignFirstResponder() {
    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}

এবং onCommitযুক্তিতে এটি যুক্ত করুন:

TextField("title", text: $text, onCommit:  {
    resignFirstResponder()
})

উপকারিতা

  • আপনি যে কোনও জায়গা থেকে কল করতে পারেন
  • এটি ইউআইকিট বা সুইফটুআইয়ের উপর নির্ভরশীল নয় (ম্যাক অ্যাপ্লিকেশনে ব্যবহার করা যেতে পারে)
  • এটি আইওএস 13 তেও কাজ করে

ডেমো

ডেমো


0

এখন পর্যন্ত উপরের বিকল্পগুলি আমার পক্ষে কার্যকর হয়নি, কারণ আমার ফর্ম এবং ভিতরে বোতাম, লিঙ্ক, চয়নকারী ...

আমি নীচের কোডগুলি তৈরি করছি যা উপরের উদাহরণগুলির সাহায্যে কাজ করছে।

import Combine
import SwiftUI

private class KeyboardListener: ObservableObject {
    @Published var keyabordIsShowing: Bool = false
    var cancellable = Set<AnyCancellable>()

    init() {
        NotificationCenter.default
            .publisher(for: UIResponder.keyboardWillShowNotification)
            .sink { [weak self ] _ in
                self?.keyabordIsShowing = true
            }
            .store(in: &cancellable)

       NotificationCenter.default
            .publisher(for: UIResponder.keyboardWillHideNotification)
            .sink { [weak self ] _ in
                self?.keyabordIsShowing = false
            }
            .store(in: &cancellable)
    }
}

private struct DismissingKeyboard: ViewModifier {
    @ObservedObject var keyboardListener = KeyboardListener()

    fileprivate func body(content: Content) -> some View {
        ZStack {
            content
            Rectangle()
                .background(Color.clear)
                .opacity(keyboardListener.keyabordIsShowing ? 0.01 : 0)
                .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
                .onTapGesture {
                    let keyWindow = UIApplication.shared.connectedScenes
                        .filter({ $0.activationState == .foregroundActive })
                        .map({ $0 as? UIWindowScene })
                        .compactMap({ $0 })
                        .first?.windows
                        .filter({ $0.isKeyWindow }).first
                    keyWindow?.endEditing(true)
                }
        }
    }
}

extension View {
    func dismissingKeyboard() -> some View {
        ModifiedContent(content: self, modifier: DismissingKeyboard())
    }
}

ব্যবহার:

 var body: some View {
        NavigationView {
            Form {
                picker
                button
                textfield
                text
            }
            .dismissingKeyboard()

-2

এক্সকোড 12 এবং আইওএস 14 এর সাথে জুন / 2020 এ প্রকাশিত সুইফটআইআই হাইডকিয়ারবোর্ডঅনট্যাপ () সংশোধক যুক্ত করেছে। এটি আপনার কেস নম্বরটি সমাধান করবে 2 আপনার কেস নম্বর 1 এর সমাধানটি এক্সকোড 12 এবং আইওএস 14 এর সাথে বিনামূল্যে আসে: রিটার্ন বোতাম টিপলে টেক্সটফিল্ডের ডিফল্ট কীবোর্ড স্বয়ংক্রিয়ভাবে লুকায়।


4
আইওএস 14 এ কোনও হাইডকি-বোর্ডবোর্ডঅনট্যাপ মডিফায়ার নেই
টিও

সম্ভবত বিভ্রান্ত হয়ে পড়ে: github.com/jeroenzonneveld/SwiftUIFormHelper/blob/develop/…
জেসি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.