কীভাবে অনির্দিষ্ট ইনস্ট্যান্টেড স্পিনারকে গুলি চালানো থেকে আইটেম নির্বাচন করা যায়?


419

আমি এটি সমাধানের মার্জিত উপায়গুলির চেয়ে কিছুটা কম ভেবেছি, তবে আমি জানি যে আমি অবশ্যই কিছু অনুপস্থিত।

onItemSelectedব্যবহারকারীর সাথে কোনও ইন্টারঅ্যাকশন ছাড়াই আমার অগ্নিকাণ্ড বন্ধ হয়ে যায় এবং এটি অনাকাঙ্ক্ষিত আচরণ। আমি ইউআইয়ের জন্য অপেক্ষা করি যেন তারা কিছু করার আগে ব্যবহারকারী কিছু না বাছাই করে।

এমনকি শ্রোতাদের সেট আপ করার চেষ্টা করেছি onResume(), এই আশায় যে এটি সাহায্য করবে, তবে তা হয় না।

ব্যবহারকারীর নিয়ন্ত্রণের ছোঁয়া দেওয়ার আগে আমি কীভাবে এটিকে গুলি চালানো থেকে আটকাতে পারি?

public class CMSHome extends Activity { 

private Spinner spinner;

@Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Heres my spinner ///////////////////////////////////////////
    spinner = (Spinner) findViewById(R.id.spinner);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.pm_list, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    };

public void onResume() {
    super.onResume();
    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}

    public class MyOnItemSelectedListener implements OnItemSelectedListener {

    public void onItemSelected(AdapterView<?> parent,
        View view, int pos, long id) {

     Intent i = new Intent(CMSHome.this, ListProjects.class);
     i.putExtra("bEmpID", parent.getItemAtPosition(pos).toString());
        startActivity(i);

        Toast.makeText(parent.getContext(), "The pm is " +
          parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
    }

    public void onNothingSelected(AdapterView parent) {
      // Do nothing.
    }
}
}

2
আপনি এই সমাধানটি দেখতে পারেন, এটি সহজ এবং বাস্তব। stackoverflow.com/a/10102356/621951
Günay গুলতেকিন

1
একটি সহজ সমাধান হ'ল প্রথম আইটেমটি Spinnerখালি তৈরি করা উচিত এবং ভিতরে onItemSelectedআপনি সনাক্ত করতে পারবেন স্ট্রিংটি খালি না থাকলে startActivity!
মুহাম্মদ বাবর

এই প্যাটার্ন সঠিকভাবে কাজ stackoverflow.com/questions/13397933/...
saksham

উত্তর:


78

আমি আপনার সমাধানটি কাজ করার প্রত্যাশা করতাম - আমি শ্রোতাদের সেট আপ করার আগে আপনি অ্যাডাপ্টারটি সেট করে নিলে নির্বাচনের ইভেন্টটি আগুন নেবে না।

বলা হচ্ছে, একটি সাধারণ বুলিয়ান পতাকা আপনাকে দুর্বৃত্তদের প্রথম নির্বাচন ইভেন্ট সনাক্ত করতে এবং এটিকে উপেক্ষা করার অনুমতি দেবে।


15
ওহ, হ্যাঁ একটি অদৃশ্য সমাধান দ্বারা আমি বোঝাতে চাই ts মনে হয় আরও ভাল উপায় থাকতে হবে। ধন্যবাদ যদিও.
ফক্সরিল

5
দেব মিলিতে এই থ্রেডটি সম্পর্কে আরও অন্তর্দৃষ্টি রয়েছে: গ্রুপ. google.com/group/android-developers/browse_thread/thread/… - দুর্ভাগ্যক্রমে কোনও সমাধান দেওয়া হয়নি ...
BoD

25
উপাদানগুলি রাখার প্রক্রিয়াটি নির্বাচনের শ্রোতাকে আগুন ধরিয়ে দেয়। লেআউটটি শেষ হওয়ার পরে আপনাকে শ্রোতাদের যুক্ত করতে হবে। আমি এই কাজ করতে উপযুক্ত, সহজবোধ্য জায়গা খুঁজে পেতে অসমর্থ হয়েছে যেমন বিন্যাস পরে কিছু সময়ে ঘটবে বলে মনে হয় আছে onResume()এবং onPostResume()তাই স্বাভাবিক আঙ্গুলসমূহ সব সময় বিন্যাস ঘটে দ্বারা সম্পন্ন হয়েছে।
ড্যান ডায়ার

28
আমি এই বুলিয়ান পতাকা থেকে দূরে থাকব - যেন ভবিষ্যতে আচরণের পরিবর্তন ঘটে এটি একটি ত্রুটির কারণ হতে পারে। একটি আরও বুলেট প্রুফ সমাধান হ'ল নির্বাচিত প্রথম আইটেমটি থেকে শুরু করে "বর্তমান নির্বাচিত সূচী" দিয়ে একটি পরিবর্তনশীল রাখা। তারপরে বাছাই ইভেন্ট - এটি নতুন অবস্থানের সমান কিনা তা পরীক্ষা করে দেখুন - ফিরে আসুন এবং কিছুই করবেন না। অবশ্যই নির্বাচনের ক্ষেত্রে পরিবর্তনশীল আপডেট করুন।
daniel.gindi

2
এটা কাজ করে না. @ ক্যাসানোভা দ্বারা উত্তর কাজ করে। এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
সিদ্ধার্থ

379

রানবেবলের ব্যবহার সম্পূর্ণ ভুল।

setSelection(position, false);প্রাথমিক নির্বাচনের আগে ব্যবহার করুনsetOnItemSelectedListener(listener)

এইভাবে আপনি কোনও অ্যানিমেশন ছাড়াই আপনার নির্বাচনটি সেট করেছেন যার ফলে অন আইটেম নির্বাচিত শ্রোতাদের ডাকা হতে পারে। তবে শ্রোতা নাল তাই কিছুই চালানো হয় না। তারপরে আপনার শ্রোতা নিয়োগ করা হবে।

সুতরাং এই সঠিক ক্রম অনুসরণ করুন:

Spinner s = (Spinner)Util.findViewById(view, R.id.sound, R.id.spinner);
s.setAdapter(adapter);
s.setSelection(position, false);
s.setOnItemSelectedListener(listener);

48
+1 লুকানো রত্ন! "অ্যানিমেট" প্যারামিটার হিসাবে মিথ্যা পাস করা শ্রোতাদের কলব্যাক কল করে না। অসাধারণ!
pkk

3
+1 অদ্ভুত তবে মার্জিত সমাধান :) ভাগ্যক্রমে, আমাকে ইতিমধ্যে যাইহোক যাইহোক সেটস্লেশন কল করতে হয়েছিল ...
মার্টিন টি।

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

6
উপকারী, তবে ওপি উপস্থাপিতের চেয়ে আলাদা সমস্যা সমাধান করে। ওপি একটি নির্বাচন ইভেন্টকে বোঝায় যা প্রোগ্রামার সেটস্লেশন না করে সত্ত্বেও দৃশ্যটি প্রথম প্রদর্শিত হওয়ার পরে (দুর্ভাগ্যক্রমে) স্বয়ংক্রিয়ভাবে আগুন ছড়িয়ে যায়
টুলমেকারস্টেভ

2
সেটস্লেশন (..) পদ্ধতিতে "ভুয়া" মান প্যারামিটারটি ছিল আমার জন্য সমাধান। TY!
দানি

194

ড্যান ডায়ারের উত্তর উল্লেখ করে OnSelectListenerএকটি post(Runnable)পদ্ধতিতে নিবন্ধন করার চেষ্টা করুন :

spinner.post(new Runnable() {
    public void run() {
        spinner.setOnItemSelectedListener(listener);
    }
});

আমার জন্য এটি করার মাধ্যমে ইচ্ছাশালী আচরণটি অবশেষে ঘটল।

এক্ষেত্রে এর অর্থ এটিও হ'ল শ্রোতা কেবল পরিবর্তিত আইটেমটিতে গুলি চালায়।


1
আমি এই বলে একটি ত্রুটি পেয়েছি: অ্যাডাপ্টারভিউ <স্পিনারএডাপ্টার> টাইপটিতে পদ্ধতি সেটঅনটাইমসলেক্টডলাইজনার (অ্যাডাপ্টারভিউ.অন্টিমেটসিলেক্টলিস্টনার) প্রযোজ্য নয় (নতুন রান্নেবল () {}) কেন এটি?
Jakob

এটি মূলত রান্নেবল এবং ইউআই থ্রেডের মধ্যে কোনও রেসের শর্ত স্থাপন করছে না?
কেনে_কে

6
@ থ্যাফঙ্কিইঞ্জাইনার - এই কোডটি মূল থ্রেড পদ্ধতিগুলির মধ্যে একটি, যেমন , ইত্যাদি থেকে চালিত হওয়া উচিত that ক্ষেত্রে, এটি একটি দারুণ কৌশল, জাতিগত অবস্থার কোনও আশঙ্কা ছাড়াই। আমি সাধারণত লেআউট কোডের পরে এই কৌশলটি ব্যবহার করি । onCreate()onResume()onCreate()
রিচার্ড লে ম্যাসুরিয়ার

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

1
এটি একটি গ্রহণযোগ্য সমাধান । একটি অন্ধ শট না। অন্যান্য সমাধানগুলি ভবিষ্যতে আচরণ পরিবর্তনের সমস্যার ঝুঁকিতে বেশি।
কুলদীপ সিং Dhaka

50

Spinnerব্যবহারকারীকে না জানিয়ে নির্বাচন পরিবর্তন করার জন্য আমি একটি ছোট্ট ইউটিলিটি পদ্ধতি তৈরি করেছি :

private void setSpinnerSelectionWithoutCallingListener(final Spinner spinner, final int selection) {
    final OnItemSelectedListener l = spinner.getOnItemSelectedListener();
    spinner.setOnItemSelectedListener(null);
    spinner.post(new Runnable() {
        @Override
        public void run() {
            spinner.setSelection(selection);
            spinner.post(new Runnable() {
                @Override
                public void run() {
                    spinner.setOnItemSelectedListener(l);
                }
            });
        }
    });
}

এটি শ্রোতাকে অক্ষম করে, নির্বাচনের পরিবর্তন করে এবং এরপরে শ্রোতাকে আবার সক্ষম করে।

কৌশলটি হ'ল কলগুলি ইউআই থ্রেডের জন্য অবিচ্ছিন্ন, সুতরাং আপনাকে এটি পরপর হ্যান্ডলারের পোস্টগুলিতে করতে হবে।


অসাধারণ. আমার একাধিক স্পিনার ছিল এবং তাদের শ্রোতাদের মান নির্ধারণের আগে বাতিল করার চেষ্টা করেছিলাম, তারপরে আমি তাদের সকলকে তাদের যা বলে মনে করা হয়েছিল তা ফিরিয়ে দিলাম, তবে কোনও কারণে কার্যকর হয়নি। পরিবর্তে এই ফাংশন চেষ্টা করে এবং এটি কাজ করে। আমি জানি না কেন আমার কাজ হয়নি, তবে এটি কাজ করে তাই আমি যত্ন করি না: ডি
জেস্টেফেন

4
দ্রষ্টব্য: আপনি যদি setSpinnerSelectionWithoutCallingListenerদু'বার দ্রুত কল করেন তবে দ্বিতীয় কলটি যখন প্রথমটি শ্রোতাকে ইতিমধ্যে সেট করে দিয়েছে null, আপনার স্পিনার nullচিরকালের জন্য শ্রোতার সাথে আটকে থাকবে। আমি নিম্নলিখিত ফিক্স প্রস্তাব: if (listener == null) return;পরে যোগ করুন spinner.setSelection(selection)
ভায়োলেট জিরাফ

34

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

import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;

/**
 * Spinner Helper class that works around some common issues 
 * with the stock Android Spinner
 * 
 * A Spinner will normally call it's OnItemSelectedListener
 * when you use setSelection(...) in your initialization code. 
 * This is usually unwanted behavior, and a common work-around 
 * is to use spinner.post(...) with a Runnable to assign the 
 * OnItemSelectedListener after layout.
 * 
 * If you do not call setSelection(...) manually, the callback
 * may be called with the first item in the adapter you have 
 * set. The common work-around for that is to count callbacks.
 * 
 * While these workarounds usually *seem* to work, the callback
 * may still be called repeatedly for other reasons while the 
 * selection hasn't actually changed. This will happen for 
 * example, if the user has accessibility options enabled - 
 * which is more common than you might think as several apps 
 * use this for different purposes, like detecting which 
 * notifications are active.
 * 
 * Ideally, your OnItemSelectedListener callback should be
 * coded defensively so that no problem would occur even
 * if the callback was called repeatedly with the same values
 * without any user interaction, so no workarounds are needed.
 * 
 * This class does that for you. It keeps track of the values
 * you have set with the setSelection(...) methods, and 
 * proxies the OnItemSelectedListener callback so your callback
 * only gets called if the selected item's position differs 
 * from the one you have set by code, or the first item if you
 * did not set it.
 * 
 * This also means that if the user actually clicks the item
 * that was previously selected by code (or the first item
 * if you didn't set a selection by code), the callback will 
 * not fire.
 * 
 * To implement, replace current occurrences of:
 * 
 *     Spinner spinner = 
 *         (Spinner)findViewById(R.id.xxx);
 *     
 * with:
 * 
 *     SpinnerHelper spinner = 
 *         new SpinnerHelper(findViewById(R.id.xxx))
 *         
 * SpinnerHelper proxies the (my) most used calls to Spinner
 * but not all of them. Should a method not be available, use: 
 * 
 *      spinner.getSpinner().someMethod(...)
 *
 * Or just add the proxy method yourself :)
 * 
 * (Quickly) Tested on devices from 2.3.6 through 4.2.2
 * 
 * @author Jorrit "Chainfire" Jongma
 * @license WTFPL (do whatever you want with this, nobody cares)
 */
public class SpinnerHelper implements OnItemSelectedListener {
    private final Spinner spinner;

    private int lastPosition = -1;
    private OnItemSelectedListener proxiedItemSelectedListener = null;  

    public SpinnerHelper(Object spinner) {
         this.spinner = (spinner != null) ? (Spinner)spinner : null;        
    }

    public Spinner getSpinner() {
        return spinner;
    }

    public void setSelection(int position) { 
        lastPosition = Math.max(-1, position);
        spinner.setSelection(position);     
    }

    public void setSelection(int position, boolean animate) {
        lastPosition = Math.max(-1, position);
        spinner.setSelection(position, animate);        
    }

    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
        proxiedItemSelectedListener = listener;
        spinner.setOnItemSelectedListener(listener == null ? null : this);
    }   

    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if (position != lastPosition) {
            lastPosition = position;
            if (proxiedItemSelectedListener != null) {
                proxiedItemSelectedListener.onItemSelected(
                        parent, view, position, id
                );
            }
        }
    }

    public void onNothingSelected(AdapterView<?> parent) {
        if (-1 != lastPosition) {
            lastPosition = -1;
            if (proxiedItemSelectedListener != null) {
                proxiedItemSelectedListener.onNothingSelected(
                        parent
                );
            }
        }
    }

    public void setAdapter(SpinnerAdapter adapter) {
        if (adapter.getCount() > 0) {
            lastPosition = 0;
        }
        spinner.setAdapter(adapter);
    }

    public SpinnerAdapter getAdapter() { return spinner.getAdapter(); } 
    public int getCount() { return spinner.getCount(); }    
    public Object getItemAtPosition(int position) { return spinner.getItemAtPosition(position); }   
    public long getItemIdAtPosition(int position) { return spinner.getItemIdAtPosition(position); }
    public Object getSelectedItem() { return spinner.getSelectedItem(); }
    public long getSelectedItemId() { return spinner.getSelectedItemId(); }
    public int getSelectedItemPosition() { return spinner.getSelectedItemPosition(); }
    public void setEnabled(boolean enabled) { spinner.setEnabled(enabled); }
    public boolean isEnabled() { return spinner.isEnabled(); }
}

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

সুন্দর উত্তর। আমি এখনও অ্যাডাপ্টারে সমস্ত () যুক্ত করলে এটি এখনও 0 তম উপাদানে ট্রিগার করে তবে আমার 0 তম উপাদানটি নিরপেক্ষ (কিছু না করা) আচরণের একটি উপবৃত্ত হয়।
jwehrle

31

আমি যখন চাইনি তখন স্পিনার ফায়ারিং নিয়ে আমার প্রচুর সমস্যা ছিল এবং এখানে সমস্ত উত্তর অবিশ্বাস্য। তারা কাজ করে - তবে কেবল কখনও কখনও। আপনি শেষ পর্যন্ত এমন পরিস্থিতিতে চলে যাবেন যেখানে তারা ব্যর্থ হবে এবং আপনার কোডগুলিতে বাগগুলি প্রবর্তন করবে।

আমার পক্ষে কাজটি হ'ল সর্বশেষ নির্বাচিত সূচকটি একটি ভেরিয়েবলে সঞ্চয় করে শ্রোতার কাছে মূল্যায়ন করা। এটি যদি নতুন নির্বাচিত সূচকের মতো হয় তবে কিছু না করে ফিরে আসে, অন্যথায় শ্রোতাদের সাথে চালিয়ে যান। এটা কর:

//Declare a int member variable and initialize to 0 (at the top of your class)
private int mLastSpinnerPosition = 0;

//then evaluate it in your listener
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {

  if(mLastSpinnerPosition == i){
        return; //do nothing
  }

  mLastSpinnerPosition = i;
  //do the rest of your code now

}

আমাকে বিশ্বাস করুন যখন আমি এটি বলি, এটি এখন পর্যন্ত সবচেয়ে নির্ভরযোগ্য সমাধান। একটি হ্যাক, কিন্তু এটি কাজ করে!


আপনি যদি মান পরিবর্তন করার চেষ্টা করছেন তবে এটি কি কাজ করবে? আমার ক্ষেত্রে আমি পরিবর্তন শ্রোতাদের ট্রিগার না করে যখন এটি আসলে 0 হয় তখন 3 এর মতো কিছুতে মান সেট করার চেষ্টা করছি। আপনি কি বলছেন যে ব্যবহারকারীর দ্বারা এটি নির্বাচন করা হলে আমি কেবল একটি আলাদা মান ফিরিয়ে দেব?
জেস্টেফেন

হাই জেস্টেফেন, আপনি কী বলতে চাইছেন তা আমি 100% নিশ্চিত নই। আইটিএমএসলেক্ট ট্রিগার করা হলে আমি স্পিনারের পদে থাকব। সমস্যাটি হ'ল অন আইটেমলেক্টেড ট্রিগার করা হয় যখনই স্পিনার প্রথমে লোড করা হয়, কোনও প্রকৃত ব্যবহারকারীর মিথস্ক্রিয়া ছাড়াই এই ক্ষেত্রে অনাকাঙ্ক্ষিত আচরণের দিকে পরিচালিত করে। আমি প্রথম প্রান্তে 0 এর সমান হব কারণ স্পিনার যখন প্রথম লোড হয় এটি ডিফল্ট শুরুর সূচক। সুতরাং আমার সমাধানটি বর্তমানে নির্বাচিত আইটেমটি পুনরুদ্ধার করার পরিবর্তে সত্যিকারের আলাদা আইটেম নির্বাচন করা হয়েছে কিনা তা পরীক্ষা করে দেখুন ... এটি কি আপনার প্রশ্নের উত্তর দেয়?
ক্রিস

হাই ক্রিস, আমার একটি পৃষ্ঠা রয়েছে যা ব্যবহারকারীর সম্পাদনা করার জন্য ডাটাবেস থেকে তথ্য টেনে তোলে। পৃষ্ঠাটি যখন খোলে আমি স্পিনারদের পপুলেশন করি এবং তারপরে তাদের অবস্থানগুলিকে ডাটাবেজে থাকা মানগুলিতে সেট করি। সুতরাং যদি আমি উদাহরণে তাদের অবস্থান 3 এ সেট করি তবে এটি আইটেমসলেক্টেডের সাথে আই সেট 3 দিয়ে ট্রিগার করতে পারে যা প্রাথমিক থেকে পৃথক। আমি ভাবছিলাম আপনি বলছেন যে আমি কেবল সেট করা যদি ব্যবহারকারী প্রকৃতপক্ষে এগুলি পরিবর্তন করে।
জেস্টেফেন

4
যদি ব্যবহারকারী 0 অবস্থানটি নির্বাচন করেন? তারা উপেক্ষা করা হবে।
yetti99

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

26

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

এটি পদ্ধতির মতো বলে মনে হয় setSelection(int position)এবং এর setSelected(int position, boolean animate)অভ্যন্তরীণ বাস্তবায়ন বিভিন্ন রকম।

আপনি যখন setSelected(int position, boolean animate)মিথ্যা অ্যানিমেট পতাকা সহ দ্বিতীয় পদ্ধতিটি ব্যবহার করেন , আপনি onItemSelectedশ্রোতাদের গুলি ছাড়াই নির্বাচনটি পান ।


অন ​​আইটেমসলেক্টেডের অতিরিক্ত কলগুলি সম্পর্কে উদ্বিগ্ন না হওয়া, তবে এটি সঠিক নির্বাচনটি দেখায় তা নিশ্চিত করা ভাল better সুতরাং, শ্রোতা যুক্ত করার আগে স্পিনার.সেটলেশন (নির্বাচিত সূচক) কল করা এটি আমার পক্ষে ধারাবাহিকভাবে কাজ করে।
andude

1
স্পিনার
শিফট

4
আপনার আসল কলটি প্রয়োজনsetSelection(int position, boolean animate);
ব্র্যাড

আপনার জন্য +1 কোড আরও বার সংশোধন করে স্পিনার সামগ্রী এবং নির্বাচন অন করে রেখে আইটেমটি কেবলমাত্র ব্যবহারকারী ইন্টারঅ্যাকশনের জন্য নির্বাচিত হয়
আলআরমা

4
দুর্ভাগ্যক্রমে মিথ্যা অ্যানিমেশন পতাকা এখনও onItemSelectedএপিআই 23
এমসি

23

সেটঅনটাইমসলেক্টলিস্টনার (যা ক্রিয়াকলাপ প্রারম্ভিককরণের অংশ, ইত্যাদি) এর স্বয়ংক্রিয় কলগুলির মধ্যে পার্থক্য করার জন্য অন টাচলিস্টনার ব্যবহার করার ইঙ্গিতগুলি প্রকাশ করার জন্য, প্রকৃত ব্যবহারকারীর মিথস্ক্রিয়া দ্বারা চালিত কলগুলিতে কল করা, আমি এখানে কিছু অন্যান্য পরামর্শ চেষ্টা করার পরে নিম্নলিখিতটি করেছি এবং এটি কোডের কয়েকটি সংখ্যক লাইনের সাথে ভাল কাজ করেছে।

আপনার ক্রিয়াকলাপ / খণ্ডগুলির জন্য কেবল বুলিয়ান ক্ষেত্র সেট করুন:

private Boolean spinnerTouched = false;

তারপরে আপনি আপনার স্পিনারের সেটঅন্ট আইটেমসলেক্টডলাইজনার সেট করার ঠিক আগে, একটি টাচলিস্টনার সেট করুন:

    spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Real touch felt.");
            spinnerTouched = true;
            return false;
        }
    });

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    ...
         if (spinnerTouched){
         //Do the stuff you only want triggered by real user interaction.
        }
        spinnerTouched = false;

1
এটি দুর্দান্ত কাজ করে এবং অ্যান্ড্রয়েড 6++ হ'ল এটিই একমাত্র পদ্ধতি যা কাজ করে। কিন্তু, আপনি সেটঅনকিলেলিস্টেনার () দিয়েও একই কাজ করতে হবে, বা কীবোর্ডের সাহায্যে ব্যবহারকারী নেভিগেট করলে এটি কাজ করে না।
স্টাফেন

দুর্দান্ত কাজ করে, অন্যান্য সমস্ত সমাধানে বিভিন্ন ফোনে কিছু সমস্যা আছে।
Ziwei Zeng

এটি সহজ এবং একেবারে নিখুঁত! অতিরিক্ত বাজে কোনও প্রয়োজন নেই, কেবল যুক্তিটি মাথায় রাখুন। আমি খুশি আমি এখানে অবধি সমস্ত দিকে স্ক্রোল করেছি!
ব্যবহারকারী 3833732

সেটঅনকিএলিস্টনার () এর পরিবর্তে, আপনি স্পিনার সাবক্লাস করে ফ্ল্যাগ স্পিনার সেট করতে পারেন: ওভাররাইড প্রিফর্মক্লিক () পদ্ধতিতে সত্য, যা উভয় ক্ষেত্রে (স্পর্শ / কী) বলা হয় called বিশ্রাম একই।
সর্বশক্তিমান

সাম্প্রতিক আমি এখানে পোস্ট করা ড্রপডাউন প্রেফারেন্সগুলির সাথে একই বাগটি সমাধান করার জন্য এটি কেবল উল্লেখ করতে চেয়েছিলাম: স্ট্যাকওভারফ্লো / জিজ্ঞাসা / 18১671111১৮৮/… আমি বিশ্বাস করতে পারি না এটি টিবিএইচ: ডি
ড্যানিয়েল উইলসন

13
spinner.setSelection(Adapter.NO_SELECTION, false);

3
কোডটি নিজের পক্ষে বলতে পারে, তবে কিছুটা ব্যাখ্যা অনেকদূর যেতে পারে :)
nhaarman

8

আমার চুল দীর্ঘ সময় ধরে টানানোর পরে এখন আমি আমার নিজের স্পিনার ক্লাস তৈরি করেছি। আমি এটিতে একটি পদ্ধতি যুক্ত করেছি যা শ্রোতাকে যথাযথভাবে সংযোগ বিচ্ছিন্ন করে এবং সংযুক্ত করে।

public class SaneSpinner extends Spinner {
    public SaneSpinner(Context context) {
        super(context);
    }

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

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

    // set the ceaseFireOnItemClickEvent argument to true to avoid firing an event
    public void setSelection(int position, boolean animate, boolean ceaseFireOnItemClickEvent) {
        OnItemSelectedListener l = getOnItemSelectedListener();
        if (ceaseFireOnItemClickEvent) {
            setOnItemSelectedListener(null);
        }

        super.setSelection(position, animate);

        if (ceaseFireOnItemClickEvent) {
            setOnItemSelectedListener(l);
        }
    }
}

এটি আপনার এক্সএমএলে এটি ব্যবহার করুন:

<my.package.name.SaneSpinner
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/mySaneSpinner"
    android:entries="@array/supportedCurrenciesFullName"
    android:layout_weight="2" />

আপনাকে যা করতে হবে তা হল মুদ্রাস্ফীতি এবং স্যানসপিনারের পরে স্যানস্পাইনারের উদাহরণটি পুনরুদ্ধার করতে হবে:

mMySaneSpinner.setSelection(1, true, true);

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


1
এটি আমার পক্ষে কাজ করে না, এটি এখনও আইটেম নির্বাচন করা ট্রিগার করে।
আরেথেজ

আরেথেজ দয়া করে ডাবল পরীক্ষা করে দেখুন যে আপনি সত্যই তৃতীয় যুক্তির সত্যতা পার করছেন। হ্যাঁ যদি অন্য কিছু এখানে ভুল হয়। সম্ভব হলে আপনার কোড পোস্ট করুন।
ফিউশন 44

8

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

spinner.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ensure you call it only once works for JELLY_BEAN and later
            spinner.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            // add the listener
            spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                    // check if pos has changed
                    // then do your work
                }

                @Override
                public void onNothingSelected(AdapterView<?> arg0) {
                }

            });

        }
    });

এটি কাজ করে এবং আইএমও এটি ওপি'র নির্দিষ্ট ইস্যুটির পরিষ্কার সমাধান। আমি নোট করতে চাই যে আপনি ViewTreeObserver.OnGlobalLayoutListenerজে এর নীচের সংস্করণগুলি কল করে মুছে ফেলতে পারেন ViewTreeObserver.removeGlobalOnLayoutListener, যা এই উত্তরটি ব্যবহার করে পদ্ধতিটির অবহিত এবং একইরকম নাম রয়েছে।
জ্যাক মিস্টার

7

আপনি যদি কোড হিসাবে নির্বাচন করছেন তবে এটি ঘটবে;

   mSpinner.setSelection(0);

পরিবর্তে উপরে বিবৃতি ব্যবহার

   mSpinner.setSelection(0,false);//just simply do not animate it.

সম্পাদনা করুন: এই পদ্ধতিটি এমআই অ্যান্ড্রয়েড সংস্করণ মি ইউআইয়ের জন্য কাজ করে না।


2
এটি অবশ্যই আমার জন্য সমস্যার সমাধান করেছে। আমি স্পিনার উইজেট সম্পর্কে ডকুমেন্টেশন পড়েছি .. এটির পার্থক্যটি বোঝা একেবারেই মুশকিল: সেটস্লেশন (ইন পজিশন, বুলিয়ান অ্যানিমেট) -> অ্যাডাপ্টারের ডেটাতে কোনও নির্দিষ্ট আইটেমে সরাসরি যান। setSelection (int অবস্থান) -> বর্তমানে নির্বাচিত আইটেমটি সেট করে Se
ম্যাট

5

আমি একটি খুব সহজ উত্তর পেয়েছি, এটি 100% নিশ্চিতভাবে কাজ করে:

boolean Touched=false; // this a a global variable

public void changetouchvalue()
{
   Touched=true;
}

// this code is written just before onItemSelectedListener

 spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Real touch felt.");
            changetouchvalue();
            return false;
        }
    });

//inside your spinner.SetonItemSelectedListener , you have a function named OnItemSelected iside that function write the following code

if(Touched)
{
 // the code u want to do in touch event
}

3

আমি এটির জন্য আরও অনেক মার্জিত সমাধান পেয়েছি। এর মধ্যে অ্যারেএডাপ্টার (আপনার ক্ষেত্রে "অ্যাডাপ্টার") কতবার আহবান করা হয়েছে তা গণনা জড়িত। ধরা যাক আপনার 1 জন স্পিনার আছে এবং আপনি কল করেছেন:

int iCountAdapterCalls = 0;

ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.pm_list, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

অনক্রিটের পরে এবং তারপরে আইটেমসিলিগ্রেটেড () পদ্ধতির অভ্যন্তরে কোনও ইন্টি কাউন্টার ঘোষনা করুন অ্যাটাপ্টারটি কতবার ডাকা হয়েছে তা যাচাই করার জন্য "যদি" শর্ত চাপান। আপনার ক্ষেত্রে আপনি এটি একবার মাত্র কল করেছেন:

if(iCountAdapterCalls < 1)
{
  iCountAdapterCalls++;
  //This section executes in onCreate, during the initialization
}
else
{
  //This section corresponds to user clicks, after the initialization
}

2

আমার ছোট অবদানটি উপরের কয়েকটিতে যা আমার জন্য কয়েকবার উপযোগী তা তারতম্য।

একটি পূর্ণসংখ্যের ভেরিয়েবলটিকে ডিফল্ট মান হিসাবে ঘোষণা করুন (বা সর্বশেষ ব্যবহৃত মানটি পছন্দগুলিতে সংরক্ষিত হয়েছে)। শ্রোতা নিবন্ধিত হওয়ার আগে সেই মানটি সেট করতে স্পিনার.সেটস্লেশন (মাইডিফল্ট) ব্যবহার করুন। অন ​​আইটেমসিলিগ্রেটেডে পরীক্ষা করে দেখুন যে নতুন স্পিনার মানটি কোনও পরবর্তী কোড চালানোর আগে আপনার নির্ধারিত মানের সমান কিনা।

ব্যবহারকারী যদি একই মানটি আবার বাছাই করে তবে কোডটি না চালানোর অতিরিক্ত সুবিধা রয়েছে।


1

একই সমস্যা হওয়ার পরে, আমি ট্যাগ ব্যবহার করে এই সমাধানে এসেছি। এর পিছনে ধারণাটি সহজ: স্পিনার যখনই প্রোগ্রামক্রমে পরিবর্তন হয় তখন নিশ্চিত হয়ে নিন যে ট্যাগটি নির্বাচিত অবস্থানটি প্রতিফলিত করে। শ্রোতার ক্ষেত্রে আপনি পরীক্ষা করে নির্বাচিত অবস্থানটি ট্যাগের সমান কিনা। যদি এটি হয় তবে স্পিনার নির্বাচনটি প্রোগ্রামক্রমে পরিবর্তন করা হয়েছিল।

নীচে আমার নতুন "স্পিনার প্রক্সি" শ্রেণি রয়েছে:

package com.samplepackage;

import com.samplepackage.R;
import android.widget.Spinner;

public class SpinnerFixed {

    private Spinner mSpinner;

    public SpinnerFixed(View spinner) {
         mSpinner = (Spinner)spinner;
         mSpinner.setTag(R.id.spinner_pos, -2);
    }

    public boolean isUiTriggered() {
         int tag = ((Integer)mSpinner.getTag(R.id.spinner_pos)).intValue();
         int pos = mSpinner.getSelectedItemPosition();
         mSpinner.setTag(R.id.spinner_pos, pos);
         return (tag != -2 && tag != pos);
    }

    public void setSelection(int position) {
        mSpinner.setTag(R.id.spinner_pos, position);
        mSpinner.setSelection(position);
    }

    public void setSelection(int position, boolean animate) {
        mSpinner.setTag(R.id.spinner_pos, position);
        mSpinner.setSelection(position, animate);
    }

    // If you need to proxy more methods, use "Generate Delegate Methods"
    // from the context menu in Eclipse.
}

আপনার Valuesডিরেক্টরিতে ট্যাগ সেটআপ সহ আপনার একটি এক্সএমএল ফাইলও লাগবে । আমি আমার ফাইলটির নাম দিয়েছি spinner_tag.xml, তবে এটি আপনার হাতে রয়েছে। দেখে মনে হচ্ছে:

<resources xmlns:android="http://schemas.android.com/apk/res/android">
  <item name="spinner_pos" type="id" />
</resources>

এখন প্রতিস্থাপন করুন

Spinner myspinner;
...
myspinner = (Spinner)findViewById(R.id.myspinner);

আপনার কোড সহ

SpinnerFixed myspinner;
...
myspinner = new SpinnerFixed(findViewById(R.id.myspinner));

এবং আপনার হ্যান্ডলারটিকে কিছুটা এমন দেখাচ্ছে:

myspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if (myspinner.isUiTriggered()) {
            // Code you want to execute only on UI selects of the spinner
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});

isUiTriggered()স্পিনারটি যদি ব্যবহারকারী দ্বারা পরিবর্তিত হয় তবেই ফাংশনটি সত্য হবে। মনে রাখবেন যে এই ফাংশনটির একটি পার্শ্ব প্রতিক্রিয়া রয়েছে - এটি ট্যাগটি সেট করবে, তাই একই শ্রোতার কলের দ্বিতীয় কলটি সর্বদা ফিরে আসবেfalse

এই মোড়কটি শ্রোতার সাথে লেআউট তৈরির সময় ডেকে আনা সমস্যাটিকেও পরিচালনা করবে।

মজা করুন, জেনস।


1

যেহেতু কিছুই আমার পক্ষে কাজ করে নি, এবং আমার দৃষ্টিতে আমার 1 টিরও বেশি স্পিনার রয়েছে (এবং আইএমএইচও-র একটি বুল ম্যাপ ধারণ করা একটি ওভারকিল) আমি ক্লিকগুলি গণনা করতে ট্যাগটি ব্যবহার করি:

spinner.setTag(0);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Integer selections = (Integer) parent.getTag();
            if (selections > 0) {
                // real selection
            }
            parent.setTag(++selections); // (or even just '1')
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });

1

ইতিমধ্যে প্রচুর উত্তর, এখানে আমার।

আমি এমন AppCompatSpinnerএকটি পদ্ধতি প্রসারিত এবং সংযোজন করেছি pgmSetSelection(int pos)যা একটি নির্বাচন কলব্যাক ট্রিগার না করে প্রোগ্রাম্যাটিক নির্বাচন সেটিংসের অনুমতি দেয়। আমি এটি আরএক্সজাভা দিয়ে কোড করে দিয়েছি যাতে নির্বাচনের ইভেন্টগুলি একটি এর মাধ্যমে সরবরাহ করা হয় Observable

package com.controlj.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;

import io.reactivex.Observable;

/**
 * Created by clyde on 22/11/17.
 */

public class FilteredSpinner extends android.support.v7.widget.AppCompatSpinner {
    private int lastSelection = INVALID_POSITION;


    public void pgmSetSelection(int i) {
        lastSelection = i;
        setSelection(i);
    }

    /**
     * Observe item selections within this spinner. Events will not be delivered if they were triggered
     * by a call to setSelection(). Selection of nothing will return an event equal to INVALID_POSITION
     *
     * @return an Observable delivering selection events
     */
    public Observable<Integer> observeSelections() {
        return Observable.create(emitter -> {
            setOnItemSelectedListener(new OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    if(i != lastSelection) {
                        lastSelection = i;
                        emitter.onNext(i);
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {
                    onItemSelected(adapterView, null, INVALID_POSITION, 0);
                }
            });
        });
    }

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

    public FilteredSpinner(Context context, int mode) {
        super(context, mode);
    }

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

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

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

তার ব্যবহার, ডেকে একটি উদাহরণ onCreateView()একটি Fragmentউদাহরণস্বরূপ:

    mySpinner = view.findViewById(R.id.history);
    mySpinner.observeSelections()
        .subscribe(this::setSelection);

setSelection()এনকোলেজিং ভিউতে এমন পদ্ধতি যেখানে দেখতে এটির মতো দেখা যায় এবং যাকে ব্যবহারকারীর নির্বাচনের ইভেন্ট থেকে উভয়ই Observableপ্রোগ্রামের মাধ্যমে এবং অন্যত্র বলা হয়, সুতরাং নির্বাচন পরিচালনা করার জন্য যুক্তি উভয় নির্বাচন পদ্ধতিতে সাধারণ।

private void setSelection(int position) {
    if(adapter.isEmpty())
        position = INVALID_POSITION;
    else if(position >= adapter.getCount())
        position = adapter.getCount() - 1;
    MyData result = null;
    mySpinner.pgmSetSelection(position);
    if(position != INVALID_POSITION) {
        result = adapter.getItem(position);
    }
    display(result);  // show the selected item somewhere
}

0

আমি ফোন করার চেষ্টা করব

spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());

আপনি সেটএডাপ্টার () কল করার পরে। অ্যাডাপ্টারের আগে কল করার চেষ্টা করুন।

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


0

বুলিয়ান পতাকা বা একটি কাউন্টার সহ সমাধানটি আমাকে সহায়তা করে না, 'আইটেমসিলিগ্রেড () পতাকা বা কাউন্টারের "ওভারফ্লিউ" কল করে ient

আমি সাবক্লাস করেছি android.widget.Spinnerএবং ছোট সংযোজন করেছি। সম্পর্কিত অংশগুলি নীচে রয়েছে। এই সমাধানটি আমার পক্ষে কাজ করেছিল।

private void setHandleOnItemSelected()
{
  final StackTraceElement [] elements = Thread.currentThread().getStackTrace();

  for (int index = 1; index < elements.length; index++)
  {
     handleOnItemSelected = elements[index].toString().indexOf("PerformClick") != -1; //$NON-NLS-1$

     if (handleOnItemSelected)
     {
        break;
     }
  }
}

@Override
public void setSelection(int position, boolean animate)
{
  super.setSelection(position, animate);

  setHandleOnItemSelected();
}

@Override
public void setSelection(int position)
{
  super.setSelection(position);

  setHandleOnItemSelected();
}

public boolean shouldHandleOnItemSelected()
{
  return handleOnItemSelected;
}

0

এটি কোনও মার্জিত সমাধান নয়। আসলে এটি বরং রুবে-গোল্ডবার্গ তবে এটি কার্যকর বলে মনে হচ্ছে। আমি নিশ্চিত হয়েছি যে অ্যারে অ্যাডাপ্টারটি প্রসারিত করে এবং এর getDropDownView ওভাররাইড করে স্পিনারটি অন্তত একবার ব্যবহার করা হয়েছে। নতুন গেটড্রপডাউনভিউ পদ্ধতিতে আমার কাছে একটি বুলিয়ান পতাকা রয়েছে যা ড্রপডাউন মেনুটি অন্তত একবার ব্যবহার করা হয়েছে তা দেখানোর জন্য সেট করা আছে। পতাকা সেট না হওয়া পর্যন্ত আমি শ্রোতাদের কাছে কল উপেক্ষা করি।

MainActivity.onCreate ():

ActionBar ab = getActionBar();
ab.setDisplayShowTitleEnabled(false);
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
ab.setListNavigationCallbacks(null, null);

ArrayList<String> abList = new ArrayList<String>();
abList.add("line 1");
...

ArAd  abAdapt = new ArAd (this
   , android.R.layout.simple_list_item_1
   , android.R.id.text1, abList);
ab.setListNavigationCallbacks(abAdapt, MainActivity.this);

ওভারডিডেন অ্যারে অ্যাডাপ্টার:

private static boolean viewed = false;
private class ArAd extends ArrayAdapter<String> {
    private ArAd(Activity a
            , int layoutId, int resId, ArrayList<String> list) {
        super(a, layoutId, resId, list);
        viewed = false;
    }
    @Override
    public View getDropDownView(int position, View convertView,
            ViewGroup parent) {
        viewed = true;
        return super.getDropDownView(position, convertView, parent);
    }
}

পরিবর্তিত শ্রোতা:

@Override
public boolean onNavigationItemSelected(
   int itemPosition, long itemId) {
   if (viewed) {
     ...
   }
   return false;
}

0

আপনার যদি ফ্লাইতে ক্রিয়াকলাপ পুনরায় তৈরি করা প্রয়োজন যেমন: থিম পরিবর্তন করা, একটি সাধারণ পতাকা / কাউন্টার অভ্যাস কাজ করে না

ব্যবহারকারীর ক্রিয়াকলাপ সনাক্ত করতে ব্যবহারকারীর অন্তর্নিহিতকরণ () ফাংশনটি ব্যবহার করুন,

তথ্যসূত্র: https://stackoverflow.com/a/25070696/4772917


0

আমি সহজ উপায় দিয়ে করেছি :

private AdapterView.OnItemSelectedListener listener;
private Spinner spinner;

onCreate ();

spinner = (Spinner) findViewById(R.id.spinner);

listener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {

            Log.i("H - Spinner selected position", position);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {

        }
    };

 spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            spinner.setOnItemSelectedListener(listener);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {

        }
    });

সম্পন্ন


এটি একটি আকর্ষণীয় সমাধান। আরও ব্যাখ্যা ব্যবহার করতে পারে। মূলত এটি প্রথমবারের আইটেমসিলেক্ট ইভেন্টটিকে ইচ্ছাকৃতভাবে উপেক্ষা করছে। এগুলি কিছু ক্ষেত্রে ভাল কাজ করতে পারে তবে অন্যের মতো নয় যেমন অ্যাক্সেসিবিলিটি বিকল্পগুলি সক্ষম করা হয় (জরিটের ব্যাখ্যা দেখুন)
jk7

0
if () {        
       spinner.setSelection(0);// No reaction to create spinner !!!
     } else {
        spinner.setSelection(intPosition);
     }


spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

         if (position > 0) {
           // real selection
         }

      }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

     }
});

0

এটি আমার চূড়ান্ত এবং সহজেই সমাধান সমাধান:

public class ManualSelectedSpinner extends Spinner {
    //get a reference for the internal listener
    private OnItemSelectedListener mListener;

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

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

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

    @Override
    public void setOnItemSelectedListener(@Nullable OnItemSelectedListener listener) {
        mListener = listener;
        super.setOnItemSelectedListener(listener);
    }

    public void setSelectionWithoutInformListener(int position){
        super.setOnItemSelectedListener(null);
        super.setSelection(position);
        super.setOnItemSelectedListener(mListener);
    }

    public void setSelectionWithoutInformListener(int position, boolean animate){
        super.setOnItemSelectedListener(null);
        super.setSelection(position, animate);
        super.setOnItemSelectedListener(mListener);
    }
}

ডিফল্ট ব্যবহার করুন setSelection(...)ডিফল্ট আচরণ বা ব্যবহারের জন্য setSelectionWithoutInformListener(...)OnItemSelectedListener কলব্যাক triggering ছাড়া স্পিনার এ একটি আইটেম নির্বাচন করার জন্য।


0

আমার mSpinnerভিউহোল্ডারটি ব্যবহার করা দরকার, তাই পতাকাটি mOldPositionবেনামে অভ্যন্তর শ্রেণিতে সেট করা আছে।

mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            int mOldPosition = mSpinner.getSelectedItemPosition();

            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
                if (mOldPosition != position) {
                    mOldPosition = position;
                    //Do something
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
                //Do something
            }
        });

0

অনক্লিকলিস্টনার অবজেক্ট তৈরির সময় আমি প্রাথমিক সূচকটি সঞ্চয় করতাম।

   int thisInitialIndex = 0;//change as needed

   myspinner.setSelection(thisInitialIndex);

   myspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

      int initIndex = thisInitialIndex;

      @Override
      public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
         if (id != initIndex) { //if selectedIndex is the same as initial value
            // your real onselecteditemchange event
         }
      }

      @Override
      public void onNothingSelected(AdapterView<?> parent) {
      }
  });

0

আমার সমাধান ব্যবহার করে onTouchListenerতবে এর ব্যবহার থেকে সীমাবদ্ধ করে না। এটি onTouchListenerপ্রয়োজনীয় যেখানে সেটআপ জন্য একটি আবরণ তৈরি করে onItemSelectedListener

public class Spinner extends android.widget.Spinner {
    /* ...constructors... */

    private OnTouchListener onTouchListener;
    private OnItemSelectedListener onItemSelectedListener;

    @Override
    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
        onItemSelectedListener = listener;
        super.setOnTouchListener(wrapTouchListener(onTouchListener, onItemSelectedListener));
    }

    @Override
    public void setOnTouchListener(OnTouchListener listener) {
        onTouchListener = listener;
        super.setOnTouchListener(wrapTouchListener(onTouchListener, onItemSelectedListener));
    }

    private OnTouchListener wrapTouchListener(final OnTouchListener onTouchListener, final OnItemSelectedListener onItemSelectedListener) {
        return onItemSelectedListener != null ? new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Spinner.super.setOnItemSelectedListener(onItemSelectedListener);
                return onTouchListener != null && onTouchListener.onTouch(view, motionEvent);
            }
        } : onTouchListener;
    }
}

0

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

লেআউট এক্সএমএল ফাইল

    <layout>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
xmlns:app="http://schemas.android.com/apk/res-auto">


<Spinner
    android:id="@+id/spinner"
    android:layout_width="150dp"
    android:layout_height="wrap_content"
    android:spinnerMode="dropdown"
    android:layout_below="@id/member_img"
    android:layout_marginTop="@dimen/activity_vertical_margin"
    android:background="@drawable/member_btn"
    android:padding="@dimen/activity_horizontal_margin"
    android:layout_marginStart="@dimen/activity_horizontal_margin"
    android:textColor="@color/colorAccent"
    app:position="@{0}"
    />
 </RelativeLayout>
 </layout>

app:position আপনি যেখানে নির্বাচিত হওয়ার জন্য অবস্থানটি পাস করছেন।

কাস্টম বাঁধাই

  @BindingAdapter(value={ "position"}, requireAll=false)
  public static void setSpinnerAdapter(Spinner spinner, int selected) 
  {

    final int [] selectedposition= new int[1];
    selectedposition[0]=selected;


    // custom adapter or you can set default adapter
        CustomSpinnerAdapter customSpinnerAdapter = new CustomSpinnerAdapter(spinner.getContext(), <arraylist you want to add to spinner>);
        spinner.setAdapter(customSpinnerAdapter);
            spinner.setSelection(selected,false);


    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            String item = parent.getItemAtPosition(position).toString();
        if( position!=selectedposition[0]) {
                        selectedposition[0]=position;
            // do your stuff here
                    }
                }


        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
}

আপনি এখানে কাস্টম ডেটা বাঁধাই সম্পর্কে আরও পড়তে পারেন অ্যান্ড্রয়েড কাস্টম সেটার

বিঃদ্রঃ

  1. আপনার গ্রেডল ফাইলটিতে ডেটাবাইন্ডিং সক্ষম করতে ভুলবেন না

       android {
     ....
     dataBinding {
     enabled = true
    }
    }
  2. <layout>ট্যাগগুলিতে আপনার বিন্যাসের ফাইলগুলি অন্তর্ভুক্ত করুন


-1
mYear.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View arg1, int item, long arg3) {
                if (mYearSpinnerAdapter.isEnabled(item)) {

                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

2
1) দয়া করে আপনার কোডটি সঠিকভাবে ফর্ম্যাট করুন। 2) আপনার কোড কী করছে সে সম্পর্কে একটি ব্যাখ্যাও প্রশংসা হবে। কোডটি পড়ার সাথে সাথে সমস্ত কোড স্নিপেটগুলি তত্ক্ষণাত বোঝা যায় না।
মাইক কোচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.