2010-04-14 32 views
22

ऑनइटम चयनकर्ता लिस्टनर इवेंट हैंडलर दोनों को बुलाया जाता है जब स्पिनर चयन प्रोग्रामेटिक रूप से बदल जाता है, और जब कोई उपयोगकर्ता शारीरिक रूप से स्पिनर नियंत्रण पर क्लिक करता है। यह निर्धारित करना संभव है कि किसी उपयोगकर्ता द्वारा चयन किसी ईवेंट द्वारा ट्रिगर किया गया था या नहीं?एंड्रॉइड स्पिनर चयन

या स्पिनर उपयोगकर्ता चयनों को संभालने का कोई और तरीका है?

+0

यह मैं के लिए काम किया साथ सेटिंग चयनित runnable http://stackoverflow.com/a/13528576/1104279 – Gil

उत्तर

49

काम करने के लिए आपको अंतिम चयनित स्थिति को याद रखने की आवश्यकता है। फिर अपने स्पिनर श्रोता के अंदर अंतिम चयनित स्थिति की तुलना नए के साथ करें। यदि वे अलग हैं, तो ईवेंट को संसाधित करें और अंतिम स्थिति के साथ अंतिम चयनित स्थिति को अपडेट करें, अन्यथा ईवेंट प्रसंस्करण को छोड़ दें।

यदि कोड के भीतर कहीं भी आप प्रोग्रामर रूप से स्पिनर चयनित स्थिति को बदलने के लिए जा रहे हैं और आप नहीं चाहते हैं कि श्रोता घटना को संसाधित करे, तो बस अंतिम चयनित स्थिति को उस सेट पर रीसेट करें जिसे आप सेट करने जा रहे हैं।

हां, एंड्रॉइड में स्पिनर दर्दनाक है। मैं यह भी कहूंगा कि दर्द उसके नाम से शुरू होता है - "स्पिनर"। क्या यह थोड़ा भ्रामक नहीं है? :) जहां तक ​​हम इसके बारे में बात कर रहे हैं, आपको यह भी पता होना चाहिए कि एक बग है - स्पिनर अपने राज्य (डिवाइस रोटेशन पर) को पुनर्स्थापित नहीं कर सकता है, इसलिए सुनिश्चित करें कि आप स्पिनर के राज्य को मैन्युअल रूप से संभाल लें।

+0

क्या होगा यदि उपयोगकर्ता स्थिति 0 पर आइटम का चयन करना चाहता है? जहां तक ​​मैं आपके समाधान को समझता हूं, इसे –

+0

@ निकोलस कर्रासको को अनदेखा कर दिया जाएगा, यह 6 साल पहले था .. मैं बस संदर्भ को याद नहीं कर सकता, लेकिन निश्चित रूप से मुझे समाधान के साथ कोई समस्या नहीं थी। शायद अंतिम चयनित स्थिति के लिए प्रारंभिक मान के रूप में -1 का उपयोग करने पर विचार करें। –

+0

यदि आप मान -1 के रूप में शुरू करते हैं तो स्पिनर को रखे जाने पर श्रोता को पैरामीटर के रूप में स्थिति = 0 के साथ बुलाया जाएगा। बेशक -1! = 0, तो घटना आग लग जाएगी और इस प्रश्न पर उल्लिखित मुद्दा अभी भी अनसुलझा है। मैं यह नहीं कहना चाहता कि आपका जवाब गलत है, लेकिन यह पूरा नहीं हुआ है –

2

अतीत मैं पाठ बॉक्स के श्रोता

if (internal == 0) { 
    // ... Act on user change action 
} 

मैं उपयोग में

internal++; // 'internal' is an integer field initialized to 0 
textBox.setValue("...."); // listener should not act on this internal setting 
internal--; 

तब भेद करने के लिए इस तरह कार्य कर लेते हैं ++ में और - बल्कि 'सत्य पर एक बूलियन मान की स्थापना से 'ताकि कोई चिंता न हो जब विधियों ने अन्य विधियों को घोंसला दिया जो आंतरिक परिवर्तन संकेतक भी सेट कर सकते हैं।

+6

यह स्पिनर पर काम नहीं करता क्योंकि जब इस घटना को प्रेषित किया जाता है तो इटैम चयन विधि को असीमित रूप से कहा जाता है। – Arutha

20

हार्ड विश्वास है कि एक डेढ़ साल बाद, समस्या अभी भी मौजूद है और लोगों को संदेह बना हुआ है ...

सोचा मैं वैकल्पिक हल मैं Arhimed के सबसे उपयोगी पोस्ट को पढ़ने के बाद के साथ आया था का हिस्सा चाहते हैं (धन्यवाद , और मैं स्पिनरों के दर्दनाक होने के बारे में सहमत हूं!)। एक ही स्थिति है कि पहले से ही चयनित किया गया था के लिए

import android.util.Log; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemSelectedListener; 

public class OnItemSelectedListenerWrapper implements OnItemSelectedListener { 

    private int lastPosition; 
    private OnItemSelectedListener listener; 

    public OnItemSelectedListenerWrapper(OnItemSelectedListener aListener) { 
     lastPosition = 0; 
     listener = aListener; 
    } 

    @Override 
    public void onItemSelected(AdapterView<?> aParentView, View aView, int aPosition, long anId) { 
     if (lastPosition == aPosition) { 
      Log.d(getClass().getName(), "Ignoring onItemSelected for same position: " + aPosition); 
     } else { 
      Log.d(getClass().getName(), "Passing on onItemSelected for different position: " + aPosition); 
      listener.onItemSelected(aParentView, aView, aPosition, anId); 
     } 
     lastPosition = aPosition; 
    } 

    @Override 
    public void onNothingSelected(AdapterView<?> aParentView) { 
     listener.onNothingSelected(aParentView); 
    } 
} 

सभी यह करता है जाल आइटम का चयन किया घटनाओं (उदाहरण के लिए प्रारंभिक स्वचालित रूप से चालू चयन: क्या मैं इन झूठे सकारात्मक से बचने के लिए कर रहा हूँ एक सरल आवरण वर्ग का उपयोग करने के लिए है स्थिति 0), और लपेटा श्रोता के लिए अन्य घटनाओं पर गुजरती हैं। इसका इस्तेमाल करने के लिए, तुम सब करने की है, तो अपने कोड है कि श्रोता आवरण शामिल करने के लिए कहता है में रेखा को संशोधित (और निश्चित रूप से बंद कोष्ठक जोड़ें) है, इसलिए बजाय, कहते हैं:

mySpinner.setOnItemSelectedListener(new OnItemSelectedListener() { 
    ... 
}); 

आप चाहते जाहिर है एक बार आप इसे परीक्षण किया है

mySpinner.setOnItemSelectedListener(new OnItemSelectedListenerWrapper(new OnItemSelectedListener() { 
    ... 
})); 

, आप लॉग से छुटकारा मिल सकता है कहता है, और आप अंतिम स्थिति रीसेट करने की क्षमता जोड़ सकते हैं यदि आवश्यक हो (आप के लिए एक संदर्भ रखने के लिए चाहते हैं: यह है उदाहरण के लिए, निश्चित रूप से, ऑन-द-फ्लाई घोषित करने के बजाए) अरिमिद ने कहा।

आशा इस इस अजीब व्यवहार ;-)

1

मैं भी इंटरनेट पर एक अच्छा समाधान के लिए देखा, लेकिन किसी भी है कि मेरी जरूरतों को संतुष्ट नहीं मिला द्वारा पागल संचालित किया जा रहा से किसी की मदद कर सकते हैं। इसलिए मैंने इस एक्सटेंशन को स्पिनर क्लास पर लिखा है ताकि आप एक साधारण OnItemClickListener सेट कर सकें, जिसमें ListView के समान व्यवहार है।

केवल जब कोई आइटम 'चयनित' हो जाता है, तो onItemClickListener को कॉल किया जाता है।

इसके साथ मजा लें!

public class MySpinner extends Spinner 
    { 
     private OnItemClickListener onItemClickListener; 


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

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

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

     @Override 
     public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener inOnItemClickListener) 
     { 
      this.onItemClickListener = inOnItemClickListener; 
     } 

     @Override 
     public void onClick(DialogInterface dialog, int which) 
     { 
      super.onClick(dialog, which); 

      if (this.onItemClickListener != null) 
      { 
       this.onItemClickListener.onItemClick(this, this.getSelectedView(), which, this.getSelectedItemId()); 
      } 
     } 
    } 
0

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

जब मैंने ऑनइटम चयन विधि को बुलाया था तो लॉग इन किया गया था अन्यथा इसे केवल एक बार बुलाया जा रहा था।

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

क्या आप वाकई इस कोड को चाहते हैं?

1

उपरोक्त aaamos के पोस्ट पर विस्तार करने के लिए, क्योंकि मेरे पास टिप्पणी करने के लिए 50 प्रतिनिधि अंक नहीं हैं, मैं यहां एक नया उत्तर बना रहा हूं।

@Override 
public void setOnItemSelectedListener(final OnItemSelectedListener listener) 
{ 
    if (listener != null) 
     super.setOnItemSelectedListener(new OnItemSelectedListener() 
     { 
      private static final int NO_POSITION = -1; 

      private int lastPosition = NO_POSITION; 


      @Override 
      public void onItemSelected(AdapterView<?> parent, View view, int position, long id) 
      { 
       if ((lastPosition != NO_POSITION) && (lastPosition != position)) 
        listener.onItemSelected(parent, view, position, id); 

       lastPosition = position; 
      } 


      @Override 
      public void onNothingSelected(AdapterView<?> parent) 
      { 
       listener.onNothingSelected(parent); 
      } 
     }); 
    else 
     super.setOnItemSelectedListener(null); 
} 

मूल रूप से, इस कोड को बहुत पहले फायरिंग पर ध्यान नहीं देगा:

मूल रूप से, अपने कोड मामले के लिए काम करता है जब प्रारंभिक स्पिनर चयन 0. लेकिन यह सामान्य है, मैं उसके कोड निम्नलिखित तरीके में संशोधन ITemSlected(), और उसके बाद सभी "समान स्थिति" कॉल का।

बेशक

, आवश्यकता है कि यहाँ चयन प्रोग्राम के सेट कर दिया जाता है, लेकिन यह मामला किसी भी तरह होना चाहिए डिफ़ॉल्ट स्थिति नहीं है अगर 0.

2

मैं इस स्थिति हाल ही में था जब स्पिनरों का उपयोग करने और इंटरनेट नहीं था ' टी एक उपयुक्त समाधान के साथ आया था।

मेरा आवेदन परिदृश्य:

एक्स & की स्थापना सीपीयू आवृत्ति को देखने के लिए स्पिनरों (गतिशील, प्रत्येक सीपीयू के लिए 2, न्यूनतम & अधिकतम)। आवेदन शुरू होने पर वे भरे जाते हैं और उन्हें सीपीयू सेट का वर्तमान अधिकतम/न्यूनतम freq भी मिलता है। एक धागा पृष्ठभूमि में चलता है और हर सेकेंड में परिवर्तन के लिए जांच करता है और स्पिनरों को तदनुसार अपडेट करता है। यदि उपयोगकर्ता द्वारा स्पिनर के अंदर एक नई आवृत्ति सेट की जाती है तो नई आवृत्ति सेट होती है।

मुद्दा यह था कि धागे ने वर्तमान आवृत्ति को अद्यतन करने के लिए सेट चयन का उपयोग किया, जिसने बदले में मेरे श्रोता को बुलाया और मुझे यह जानने का कोई तरीका नहीं था कि यह उपयोगकर्ता या धागा जिसने मूल्य बदल दिया है। अगर यह धागा था तो मैं नहीं चाहता था कि श्रोता को बुलाया जाए क्योंकि आवृत्ति को बदलने की आवश्यकता नहीं होती थी।

मैं एक समाधान है कि मेरी जरूरतों को पूरी तरह से सूट और अपने कॉल :) पर श्रोता के आसपास काम करता है (और मैं इस समाधान आप अधिकतम नियंत्रण देती है लगता है)

मैं स्पिनर बढ़ाया के साथ आया था:

import android.content.Context; 
import android.widget.Spinner; 

public class MySpinner extends Spinner { 
    private boolean call_listener = true; 

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

    public boolean getCallListener() { 
     return call_listener; 
    } 

    public void setCallListener(boolean b) { 
     call_listener = b; 
    } 

    @Override 
    public void setSelection(int position, boolean lswitch) { 
     super.setSelection(position); 
     call_listener = lswitch; 
    } 
} 

और अपने OnItemSelectedListener बनाया:

+०१२३५१६४१०६:

import android.util.Log; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemSelectedListener; 

public class SpinnerOnItemSelectedListener implements OnItemSelectedListener { 
     public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) { 
      MySpinner spin = (MySpinner) parent.findViewById(parent.getId()); 
      if (!spin.getCallListener()) { 
       Log.w("yourapptaghere", "Machine call!"); 
       spin.setCallListener(true); 
      } else { 
       Log.w("yourapptaghere", "UserCall!"); 
      } 
     } 

     @Override 
     public void onNothingSelected(AdapterView<?> arg0) { 
     // TODO Auto-generated method stub 
     } 
} 

अब आप एक MySpinner आप इस का उपयोग कर सकते चयन स्थापित करने के लिए बनाते हैं

setSelection(position, callListener);

जहां कॉललिस्टर या तो सत्य या गलत है। ट्रू श्रोता को कॉल करेगा और डिफ़ॉल्ट है, यही कारण है कि उपयोगकर्ता इंटरैक्शन की पहचान हो रही है, झूठी श्रोता को भी कॉल करेगी लेकिन इस विशेष मामले के लिए इच्छित कोड का उपयोग करती है, उदाहरण के लिए मेरे मामले में मुफ्त: कुछ भी नहीं।

मुझे आशा है कि किसी और को इस उपयोगी पाता है और एक लंबी यात्रा बख्शा है देखने के लिए अगर कुछ इस तरह पहले से मौजूद है :)

0

मैं जानता हूँ कि यह बहुत देर हो चुकी है, लेकिन मैं यह करने के लिए एक बहुत ही सरल समाधान के साथ आया था । यह अरहिम के जवाब पर आधारित है, यह वही है। इसे भी लागू करना बहुत आसान है। देखें स्वीकार किए जाते हैं जवाब:

Undesired onItemSelected calls

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