2014-05-12 9 views
5

दबाए जाने के लिए DispatchKeyEvent सुनने के लिए मैं एक एंड्रॉइड प्रोजेक्ट पर काम कर रहा हूं और मुझे यह जांचने की ज़रूरत है कि स्पेसबार दबाए जाने पर मुझे एक निश्चित फ़ंक्शन निष्पादित किया जा सकता है।स्पेसबार को

समस्या यह है कि यह एम्यूलेटर पर काम कर रहा था लेकिन मेरे वास्तविक डिवाइस पर नहीं। मुझे लगता है कि ऐसा इसलिए हो सकता है क्योंकि मेरा एमुलेटर एक भौतिक कीबोर्ड का उपयोग कर रहा था, न कि ऑनस्क्रीन वर्चुअल कीबोर्ड पर, लेकिन वास्तविक डिवाइस पर परीक्षण करते समय, यह वर्चुअल कीबोर्ड का उपयोग करता है।

मैं प्रेषण keyevent

@Override 
    public boolean dispatchKeyEvent(KeyEvent event) 
    { 

     if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE 
       && event.getAction() == KeyEvent.ACTION_UP) 
     { 
      QueryEditor queryEditor = (QueryEditor)getSupportFragmentManager().findFragmentById(R.id.fragment_queryEditor); 
      queryEditor.formatQueryText(); 
      return true; 
     } 
     } 

कोशिश कर रहा हूँ मैं भी

@Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) 
    { 
     if (keyCode == KeyEvent.KEYCODE_BACK) 
     { 
      disconnectDatabase(); 
     } 
     else if (keyCode == KeyEvent.KEYCODE_DEL) 
     { 
      QueryEditor queryEditor = (QueryEditor)getSupportFragmentManager().findFragmentById(R.id.fragment_queryEditor); 
      queryEditor.formatQueryText(); 
     } 

     return super.onKeyDown(keyCode, event); 
    } 

इनमें से न तो हालांकि जब तक वापस बटन दबाया जाता है निकाल दिया कुंजी पर की कोशिश की है, लेकिन मैं नीचे की जरूरत है घटना ट्रिगर करने के लिए स्पेसबार।

आपकी सहायता के लिए धन्यवाद।

अद्यतन

नीचे कैसे QueryEditor टुकड़ा बन जाता है और ईवेंट हैंडलर

@Override 
    public void onActivityCreated(Bundle savedInstanceState) 
    { 
     super.onActivityCreated(savedInstanceState); 

     iQueryEditor = (IQueryEditor)this; 
     iErrorHandler = (IErrorHandler)this; 

     txtQueryEditor = (EditText)getActivity().findViewById(R.id.query_txtQueryEditor); 

     btnSubmitQuery = (ImageButton)getActivity().findViewById(R.id.query_btnPerformQuery); 
     btnClearQuery = (ImageButton)getActivity().findViewById(R.id.query_btnDeleteQuery); 

     txtQueryEditor.addTextChangedListener(new QueryTextChanged(getActivity(), txtQueryEditor, iQueryEditor)); 
     setDatabaseUsed(); 
     txtQueryEditor.setOnEditorActionListener(new OnEditorActionListener() { 

      @Override 
      public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 
       if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) 
         || actionId == EditorInfo.IME_ACTION_DONE) 
       { 
        executeQuery(); 
        return true; 
       } 
       else if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) 
       { 
        Toast.makeText(getActivity(), "Space Bar Pressed", Toast.LENGTH_SHORT).show(); 
        return true; 
       } 
       return false; 
      } 
     }); 

     btnSubmitQuery.setOnClickListener(mBtnSubmitQueryListener); 
     btnClearQuery.setOnClickListener(mBtnDeleteQueryListener); 
    } 

बनाई गई है txtQueryEditor EditText है कि मैं पर स्पेस बार घटना प्राप्त करने के लिए कोशिश कर रहा हूँ है के लिए मेरे कोड है।

+0

इस सवाल में जानकारी और उसकी स्वीकार किए जाते हैं जवाब मदद कर सकता है: http://stackoverflow.com/questions/5419766/how-to-capture-soft-keyboard-input-in-a-view –

+0

आप लिख सकते हैं स्पेस बार दबाए रखने के लिए आप सॉफ्ट कीबोर्ड कैसे सक्रिय करते हैं? क्या यह संपादन टेक्स्ट दृश्य है या क्या यह प्रोग्रामेटिक रूप से किया जाता है? जब आप स्पेस बार दबाते हैं तो फोकस कहां है? –

+0

@ लूप यह उपयोगकर्ता द्वारा संपादित किए गए संपादन टेक्स्ट के अंदर क्लिक किया जाता है जो कीबोर्ड को पॉपअप करता है और नरम स्पेसबार दबाकर उपयोगकर्ता को ईवेंट ट्रिगर करना चाहिए। – Boardy

उत्तर

2

अपनी गतिविधि में इस कार्यान्वयन काम करना चाहिए:

@Override 
public boolean dispatchKeyEvent(KeyEvent event) { 
    if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) { 
     Log.d("test", "[Dispatch] Space bar pressed! " + event); 
     return true; 
    } 
    return super.dispatchKeyEvent(event); 
} 

अपने कोड में अंतर यह है कि मैं SPACE_BAR के अलावा अन्य सभी चाबी के लिए super.dispatchKeyEvent() बोल रहा हूँ है। यदि dispatchKeyEvent सत्य देता है onKeyUp() ट्रिगर नहीं किया जाएगा। तो यदि आप केवल स्पेस कुंजी ईवेंट की निगरानी करना चाहते हैं तो बस टिप्पणी करें //return true;

यदि आप onKeyUp() विधि का उपयोग करते हैं तो यह भी ठीक काम करेगा। onKeyDown() का उपयोग न करें, यदि उपयोगकर्ता अपनी अंगुली को बहुत लंबा रखता है तो इसे कुछ बार कहा जा सकता है।

@Override 
public boolean onKeyUp(int keyCode, KeyEvent event) { 
    if (keyCode == KeyEvent.KEYCODE_SPACE) { 
     Log.d("test", "Space bar pressed!"); 
     return true; 
    } 
    return super.onKeyUp(keyCode, event); 
} 

यहां मैं समान दृष्टिकोण का उपयोग करता हूं। यदि आपका अगर कथन सत्य हैंडल इवेंट है और सत्य लौटाता है। आपकी बाकी की चाबियों के लिए super.onKeyUp();

कम से कम, लेकिन सबसे महत्वपूर्ण, यदि आपके पास वर्तमान फोकस और कीबोर्ड का स्वामित्व है (उदाहरण के लिए संपादन टेक्स्ट) जो उस दृश्य के लिए दिखाया गया है तो उपर्युक्त कोड को सभी में नहीं बुलाया जाएगा गतिविधि)। यदि ऐसा है तो आपको श्रोता TextView.OnEditorActionListener लागू करना होगा और setOnEditorActionListener(TextView.OnEditorActionListener l) पर कॉल करने के लिए उस दृश्य के लिए पंजीकरण करना होगा।

viewWithFocus.setOnEditorActionListener(new TextView.OnEditorActionListener() { 
    @Override 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 
     if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) { 
      Log.d("test", "[Editor] Space bar pressed! " + event); 
      //TODO implement your action here 
      return true;//remove this line if you want edit text to create space 
     } 
     return false; 
    } 
}); 

विकल्प के रूप में आप इस दृश्य को ओवरराइड और इसके बाद के संस्करण की तरह onKepUp() लागू कर सकते हैं।

अद्यतन

समाधान ऊपर हार्डवेयर कीबोर्ड के लिए काम करता है। इसे और अधिक ध्यान से जांचने के लिए खेद है।

एंड्रॉयड प्रलेखन से

नोट: जब KeyEvent वर्ग और संबंधित API के साथ कीबोर्ड की घटनाओं से निपटने के लिए, आप की उम्मीद करनी चाहिए कि इस तरह के कीबोर्ड की घटनाओं एक हार्डवेयर कुंजीपटल से केवल आते हैं। मुलायम इनपुट विधि (ऑन-स्क्रीन कीबोर्ड) पर किसी भी कुंजी के लिए आपको कुंजी ईवेंट प्राप्त करने पर कभी भरोसा नहीं करना चाहिए।

हालांकि, मैंने पाया है कि कैसे इस समस्या को दूर करने के लिए। मैं SearchView घटक पर अपना शोध आधारित और पाया कि निम्न कोड काम करेगा है

editText.addTextChangedListener(new TextWatcher() { 
    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
    } 

    @Override 
    public void onTextChanged(CharSequence s, int start, int before, int count) { 
     char last = s.charAt(s.length()-1); 
     if (' ' == last) { 
      Log.i("test", "space pressed"); 
     } 
    } 

    @Override 
    public void afterTextChanged(Editable s) { 
    } 
}); 

IME कार्यों के लिए TextView.OnEditorActionListener ही बरकरार रखें।

+0

आपकी मदद के लिए धन्यवाद मैंने कोशिश की है। ऐसा लगता है कि यह मेरे लिए काम नहीं कर रहा है। मुझे लगता है कि मैं उल्लेख करना भूल गया था, यह नहीं पता कि इसका कारण क्या है, लेकिन एडिटटेक्स्ट एक गतिविधि द्वारा होस्ट किए गए टुकड़े के अंदर है। मैंने ईवेंट श्रोता को टुकड़े के माध्यम से और गतिविधि के माध्यम से सेट करने का प्रयास किया है, लेकिन न तो ईवेंट – Boardy

+0

निकाल दिया है क्या आप अधिक कोड पेस्ट कर सकते हैं? विशेष रूप से जहां EditText सेटअप और XML फ़ाइल है जो इस संपादन टेक्स्ट का उपयोग करती है। TextView.OnEditorActionListener निश्चित रूप से सही विकल्प है, आपको कुछ और करना होगा जो इसे अवरुद्ध करता है। –

+0

मैंने – Boardy

-1

मैंने दोनों विधियों प्रेषण और ऑनकीडाउन की कोशिश की और सॉफ्टकीबोर्ड के लिए उन्होंने काम नहीं किया। कम से कम नेक्सस 7 में नहीं। काम करने वाला एकमात्र समाधान संपादन में टेक्स्टवॉचर जोड़ रहा था। नीचे दिए गए कोड है:

जवाब का
public class MainActivity extends ActionBarActivity { 
EditText editText1; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    editText1 = (EditText) findViewById(R.id.editText1); 
    editText1.addTextChangedListener(new TextWatcher() { 

     @Override 
     public void afterTextChanged(Editable arg0) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, 
       int after) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, 
       int count) { 
      // TODO Auto-generated method stub 
      String lastChar = s.toString().substring(s.length() - 1); 
      if (lastChar.equals(" ")) { 
       Toast.makeText(MainActivity.this, "space bar pressed", 
         Toast.LENGTH_SHORT).show(); 
      } 
     } 

    }); 
} 

} 
+0

आपका उत्तर बहुत गलत है। कुंजी कोड और कार्य पूरी तरह से अलग चीजें हैं और उन्हें अलग से प्रदान नहीं किया जाता है। इसके अलावा, ACTION_UP के साथ कीकोड मान की तुलना करना कोई समझ नहीं आता है। –

6

भाग में KeyEvent API documentation निहित है:

के रूप में मुलायम इनपुट विधि पाठ inputting के कई और मौलिक तरीकों का उपयोग कर सकते हैं, वहाँ कोई गारंटी नहीं है कि किसी भी कुंजी दबाएँ एक सॉफ्ट कीबोर्ड पर एक महत्वपूर्ण घटना उत्पन्न करेगा: यह आईएमई के विवेक के लिए छोड़ा गया है, और में ऐसी घटनाएं भेजने से तथ्य निराश हो गया है। मुलायम इनपुट विधि पर किसी भी कुंजी के लिए आपको पर KeyEvents प्राप्त करने पर भरोसा नहीं करना चाहिए। विशेष रूप से, डिफ़ॉल्ट सॉफ़्टवेयर कीबोर्ड कभी भी एप्लिकेशन लक्ष्यीकरण जेली बीन या बाद में कोई भी महत्वपूर्ण ईवेंट नहीं भेजेगा, और हटाए गए कुछ प्रेस और को आइस क्रीम सैंडविच या इससे पहले लक्ष्य के लिए रिटर्न कुंजियों के लिए ईवेंट भेज देगा। ध्यान रखें कि अन्य सॉफ़्टवेयर इनपुट विधियां संस्करण के बावजूद कभी भी महत्वपूर्ण ईवेंट नहीं भेज सकती हैं। यदि आप सॉफ़्टवेयर कीबोर्ड के साथ विशिष्ट इंटरैक्शन की आवश्यकता है, तो मुझे उपयोगकर्ता की दृश्यता देता है कि आपका एप्लिकेशन कुंजी प्रेस पर कैसे प्रतिक्रिया करेगा, इस बारे में आपको विशिष्ट इंटरैक्शन की आवश्यकता है।

यहाँ एक comment एक Google इंजीनियर द्वारा छोड़ा है:

जवाब बहुत सरल है। अनुप्रयोगों को कभी उपयोगकर्ता इनपुट प्रबंधित करने के लिए कुंजी ईवेंट पर भरोसा करना चाहिए। इसका कारण यह है कि इसका परिणाम बहुत खराब उपयोगकर्ता अनुभव में होता है।

साथ शुरू करने के लिए, ऐसे कई मामले हैं जहां यह काम नहीं करता है। यह सीजेके भाषाओं के लिए उचित रूप से काम नहीं करता है। यह सही ढंग से इशारा इनपुट, या ध्वनि इनपुट के साथ, या इनपुट टॉगल के साथ काम नहीं करता है, या भविष्य में कोई भी नया आविष्कारक इनपुट विधि डेवलपर के साथ आ सकता है। वास्तव में, यह केवल एकमात्र मामला है जहां यह काम करता है केवल सबसे गरीब इनपुट अनुभव के प्रतिबंधित मामलों के लिए है: एक विरासत हार्डवेयर-कीबोर्ड-जैसी इनपुट विधि, जो मोबाइल युग के लिए एक खराब फिट है।

यही कारण है कि एंड्रॉइड एक समृद्ध एपीआई परिभाषित करता है जिसके माध्यम से आईएमई अनुप्रयोगों को संवाद करता है। यह विधि अज्ञेयवादी और भाषा अज्ञेयवादी है, और सभी सॉफ़्टवेयर इनपुट विधियां इसे कार्यान्वित कर रही हैं। एप्लिकेशन इस एपीआई का उपयोग करने के लिए माना जाता है, और संपादन टेक्स्ट का उपयोग करना सबसे आसान ऐसा करने का तरीका है (नीचे इस पर अधिक)।

कृपया पाठ प्रविष्टि के लिए विरासत कुंजी घटनाओं पर भरोसा करना बंद करें - सभी पर। यह उनका समर्थन करने के लिए अच्छा है, लेकिन उन्हें आवश्यक सभी के लिए बुरा है। यह ब्रेक स्थिरता है, यह आपके ऐप से कुछ भाषाओं को लॉक करता है, और उपयोगकर्ताओं को एंड्रॉइड पर अपेक्षा से अधिक गरीब अनुभव में मजबूर करता है। और जैसा कि टिप्पणी # 14 में उल्लेख किया गया है, इनपुट विधियां स्पष्ट रूप से महत्वपूर्ण घटनाओं को भेजने के लिए कोई दायित्व नहीं है, हालांकि कुछ इसे करने के लिए चुन सकते हैं।

समृद्ध टेक्स्ट इनपुट एपीआई को लागू करने के दो सरल तरीके हैं। दोनों को जावा भूमि में ऐसा करने की आवश्यकता होगी। संपादन टेक्स्ट का उपयोग करने के लिए पहला वाला है। यदि आपके ऐप को अपनी प्रतिपादन करने की आवश्यकता है, तो आप या तो इसे सूट कर सकते हैं यदि यह आपको उपयुक्त बनाता है, या टेक्स्ट में कोई भी परिवर्तन प्रस्तुत करते समय इसे छुपाता है। आप उसी प्रभाव को प्राप्त करने के लिए डायनामिक लेआउट और संपादन योग्य भी उपयोग कर सकते हैं। एक और संभावना BaseInputConnection बढ़ा कर सीधे InputConnection API के कार्यान्वयन के लिए है, लेकिन यह एक बहुत कड़ी मेहनत के है और आम तौर पर केवल अनुप्रयोगों पाठ संस्करण के संबंध में, एक तरह के साथ बहुत विशिष्ट जरूरतें होती हैं कि द्वारा किया जा करने की जरूरत है चाहिए आईडीई या एक शब्द प्रोसेसर।

संबंधित मुद्दे