पता लगाना जब उपयोगकर्ता ने नरम कीबोर्ड को खारिज कर दिया है


114

मेरे विचार में एक EditText विजेट है। जब उपयोगकर्ता EditText विजेट का चयन करता है, तो मैं कुछ निर्देश प्रदर्शित करता हूं और सॉफ्ट कीबोर्ड प्रकट होता है।

जब उपयोगकर्ता ने पाठ प्रविष्टि पूरी कर ली है और मैं कीबोर्ड को खारिज करता हूं, निर्देशों को छिपाता हूं और कुछ कार्रवाई करता हूं, तो यह पता लगाने के लिए मैं एक OnEditorActionListener का उपयोग करता हूं।

मेरी समस्या तब है जब उपयोगकर्ता BACK कुंजी दबाकर कीबोर्ड को हटा देता है। ओएस कीबोर्ड को खारिज कर देता है, लेकिन मेरे निर्देश (जिसे मुझे छिपाने की आवश्यकता है) अभी भी दिखाई दे रहे हैं।

मैंने OnKeyDown को ओवरराइड करने की कोशिश की है, लेकिन जब कीबोर्ड को खारिज करने के लिए BACK बटन का उपयोग किया जाता है तो उसे कॉल नहीं किया जाता है।

मैंने EditText विजेट पर एक OnKeyListener स्थापित करने की कोशिश की है, लेकिन यह भी कहा जाता है नहीं लगता है।

जब मुलायम कीबोर्ड को खारिज किया जा रहा है तो मैं कैसे पता लगा सकता हूं?

जवाबों:


160

मुझे ऐसा करने का एक तरीका पता है। EditText को सब्क्लॉस करें और लागू करें:

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
  if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
    // Do your thing.
    return true;  // So it is not propagated.
  }
  return super.dispatchKeyEvent(event);
}

अपने कस्टम दृश्यों का उपयोग करने के तरीके के बारे में यहां एक लिंक दिया गया है (जब आप EditText को उप-लिंक करते हैं): http://developer.android.com/guide/topics/ui/custom-compords.html


2
मुझे एंड्रॉइड यूजर्स से हार्डवेयर कीबोर्ड के बारे में रिपोर्ट मिल रही है जो ऐसा करने से किसी भी तरह की प्रेस में हस्तक्षेप करते हैं। मेरे पास इस समय कोई अतिरिक्त जानकारी नहीं है।
21

मैं कई समाधान देख रहा हूँ, यह अब तक का सबसे अच्छा है!
Friesgaard

10
रुको रुको रुको, मैंने अभी तीसरी बार देखा - क्या सुपर कॉल नहीं होना चाहिए onKeyPreIme? या ऐसा न होने का कोई विशेष कारण है?
एरहानिस

उपयोगी लगता है, सिवाय इसके कि जहां EditText को उप-वर्गित नहीं किया जा सकता है (जैसे किसी खोज दृश्य में)। कीबोर्ड के ख़ारिज होने पर खाली होने पर SearchView को छिपाने की कोशिश करते समय यह एक समस्या है। मुझे आश्चर्य है कि एंड्रॉइड लोग इस तरह की चीज़ के लिए बस कुछ अच्छे ओएसके एपीआई क्यों नहीं प्रदान करते हैं।
tbm

2
@tbm समान प्रभाव प्राप्त करने के लिए SearchView, कृपया stackoverflow.com/questions/9629313/…
Cheok Yan Cheng

124

जय, आपका समाधान अच्छा है! धन्यवाद :)

public class EditTextBackEvent extends EditText {

    private EditTextImeBackListener mOnImeBack;

    public EditTextBackEvent(Context context) {
        super(context);
    }

    public EditTextBackEvent(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextBackEvent(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && 
            event.getAction() == KeyEvent.ACTION_UP) {
            if (mOnImeBack != null) 
                mOnImeBack.onImeBack(this, this.getText().toString());
        }
        return super.dispatchKeyEvent(event);
    }

    public void setOnEditTextImeBackListener(EditTextImeBackListener listener) {
        mOnImeBack = listener;
    }

}

public interface EditTextImeBackListener {
    public abstract void onImeBack(EditTextBackEvent ctrl, String text);
}

कोई विशेष कारण जिसे हम भी पता लगाना चाहते हैं KeyEvent.ACTION_UP?
चोक यान चेंग

2
@CheokYanCheng यह इसलिए है क्योंकि बटन को जारी करते समय उपयोगकर्ता कार्रवाई सामान्य रूप से प्रभावी होनी चाहिए, और इसे दबाने के लिए शुरू होने पर नहीं।
जयेफकय

3
android.support.v7.widget.AppCompatEditTextटिनिंग के लिए विस्तार करना सुनिश्चित करें ।
संविवेल

बढ़ाएँ: AppCompatEditTextAndroidx के लिए
COYG

महान! मैं केवल आपके समाधान को उत्पन्न करने के लिए केवल एक सुधार का सुझाव दूंगा। मैं onKeyPreIme से "तर्कों को पारित करूंगा" जैसा कि श्रोता को होता है, इस तरह से आप अपने तर्क को अलग-अलग तरीकों से लागू कर सकते हैं जहाँ आपको ज़रूरत है।
marcRDZ

17

मैंने Super.onKeyPreIme () कॉल करके जे के समाधान पर थोड़ा बदलाव किया:

_e = new EditText(inflater.getContext()) {
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){
            cancelTextInput();
        }
        return super.onKeyPreIme(keyCode, event);
    }
};

अद्भुत समाधान, जे, +1!


14

यह पता लगाने के लिए मेरा कस्टम EditText है कि कीबोर्ड दिखा रहा है या नहीं

/**
 * Created by TheFinestArtist on 9/24/15.
 */
public class KeyboardEditText extends EditText {

    public KeyboardEditText(Context context) {
        super(context);
    }

    public KeyboardEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public KeyboardEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (listener != null)
            listener.onStateChanged(this, true);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_UP) {
            if (listener != null)
                listener.onStateChanged(this, false);
        }
        return super.onKeyPreIme(keyCode, event);
    }

    /**
     * Keyboard Listener
     */
    KeyboardListener listener;

    public void setOnKeyboardListener(KeyboardListener listener) {
        this.listener = listener;
    }

    public interface KeyboardListener {
        void onStateChanged(KeyboardEditText keyboardEditText, boolean showing);
    }
}

8

यह अब 2019 है ...
इसलिए मैंने कोटलिन के साथ एक अधिक स्वच्छ समाधान बनाया

1. एक विस्तार समारोह बनाएँ:

fun Activity.addKeyboardToggleListener(onKeyboardToggleAction: (shown: Boolean) -> Unit): KeyboardToggleListener? {
    val root = findViewById<View>(android.R.id.content)
    val listener = KeyboardToggleListener(root, onKeyboardToggleAction)
    return root?.viewTreeObserver?.run {
        addOnGlobalLayoutListener(listener)
        listener
    }
}

2. जहां टॉगल श्रोता है:

open class KeyboardToggleListener(
        private val root: View?,
        private val onKeyboardToggleAction: (shown: Boolean) -> Unit
) : ViewTreeObserver.OnGlobalLayoutListener {
    private var shown = false
    override fun onGlobalLayout() {
        root?.run {
            val heightDiff = rootView.height - height
            val keyboardShown = heightDiff > dpToPx(200f)
            if (shown != keyboardShown) {
                onKeyboardToggleAction.invoke(keyboardShown)
                shown = keyboardShown
            }
        }
    }
}

fun View.dpToPx(dp: Float) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics).roundToInt()

3. किसी भी गतिविधि में इसका प्रयोग इस तरह सरल करें :

addKeyboardToggleListener {shown ->
          // hurray! Now you know when the keyboard is shown and hidden!!
      }

कोटलिन समाधान के लिए धन्यवाद। हालाँकि जब मैंने इसे लागू किया तो मैंने देखा कि यह एक कीबोर्ड परिवर्तन के लिए श्रोता को कई बार निकालता है, और स्टार्टअप पर भी। मुझे ओपन / ओपन स्टेट को स्टोर करना था और केवल श्रोताओं का आह्वान करना था जब मूल्य वास्तव में अलग था।
randomEngy

@RandomEngy ने इसे KeyboardToggleListener में तय किया। ध्यान देने के लिए धन्यवाद
लियो डायरोडोडर

4

बस एक वर्ग बनाएं जो Edittext का विस्तार करता है और अपने कोड में उस Edittext का उपयोग करता है, आपको बस कस्टम Edittext में निम्न विधि को ओवरराइड करना चाहिए:

@Override
 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
 if (keyCode == KeyEvent.KEYCODE_BACK) {

    //Here it catch all back keys
    //Now you can do what you want.

} else if (keyCode == KeyEvent.KEYCODE_MENU) {
    // Eat the event
    return true;
}
return false;}

क्या पता चलता है कि कीबोर्ड कब खुलता है?
पाउडर 366

3

यहाँ प्रमुख श्रोता के साथ एक समाधान है। मुझे नहीं पता कि यह क्यों काम करता है लेकिन OnKeyListener काम करता है यदि आप अपने कस्टम EditText पर सिर्फ विशुद्ध रूप से onKeyPreIme को ओवरराइड करते हैं।

SomeClass.java

customEditText.setOnKeyListener((v, keyCode, event) -> {
            if(event.getAction() == KeyEvent.ACTION_DOWN) {
                switch (keyCode) {
                    case KeyEvent.KEYCODE_BACK:
                        getPresenter().onBackPressed();
                        break;
                }
            }
            return false;
        }); 

CustomEditText.java

@Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        return super.dispatchKeyEvent(event);
    }

3

@ Olivier_sdg के उत्तर का उपयोग करते हुए, लेकिन कोटलिन में परिवर्तित:

class KeyboardEditText : AppCompatEditText {

    var listener: Listener? = null
  
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
  
    override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean {
        if (event.keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
            listener?.onImeBack(this)
        }
        return super.dispatchKeyEvent(event)
    }
  
    interface Listener {
        fun onImeBack(editText: KeyboardEditText)
    }

}

उपयोग:

keyboardEditText.listener = object : KeyboardEditText.Listener {
    override fun onImeBack(editText: KeyboardEditText) {
        //Back detected
    }
}

2

किसी के लिए Xamarin में एक ही करने की तलाश में, मैंने कुछ शीर्ष उत्तरों का अनुवाद किया है क्योंकि यह थोड़ा अलग है। मैंने यहां एक जिस्ट बनाया है लेकिन संक्षेप में, आप एक कस्टम एडिट टेक्स्ट बनाएँ और इसे ओवरराइड OnKeyPreImeकरें:

public class CustomEditText : EditText
{
    public event EventHandler BackPressed;

    // ...

    public override bool OnKeyPreIme([GeneratedEnum] Keycode keyCode, KeyEvent e)
    {
        if (e.KeyCode == Keycode.Back && e.Action == KeyEventActions.Up)
        {
            BackPressed?.Invoke(this, new EventArgs());
        }

        return base.OnKeyPreIme(keyCode, e);
    }
}

... और फिर दृश्य में ...

editText = FindViewById<CustomEditText>(Resource.Id.MyEditText);
editText.BackPressed += (s, e) => 
{
    // <insert code here>
};

हालांकि यह केवल एक सरल उदाहरण है, मैं इवेंट हैंडलर में अनाम विधियों का उपयोग नहीं करने की सलाह दूंगा, क्योंकि ये मेमोरी लीक बनाते हैं, और कई लोग यहां पाए गए उदाहरणों का उपयोग करते हैं और इसे साकार किए बिना उनके साथ चलते हैं। स्रोत: docs.microsoft.com/en-us/xamarin/cross-platform/deploy-test/…
Jared

0

hideSoftInputFromWindow जब कीबोर्ड बंद हो जाता है तो इसका सही उपयोग होता है

InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

        if (imm.hideSoftInputFromWindow(findFocus().getWindowToken(),
                InputMethodManager.HIDE_NOT_ALWAYS)) {
            //keyboard is closed now do what you need here
        }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.