When I create my activity, I setup a Spinner, assigning it a listener and an initial value. I know that the onItemSelected
callback is called automatically during a
I am updating @Andres Q.'s answer in Kotlin.
Create an inner class in which you're using Spinner
inner class SpinnerInteractionListener : AdapterView.OnItemSelectedListener, View.OnTouchListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
if (userSelect) {
//Your selection handling code here
userSelect = false
}
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
userSelect = true
return false
}
internal var userSelect = false
}
Then declare instance variable outside onCreate()
as globally like
lateinit var spinnerInteractionListener: SpinnerInteractionListener
then initialise it inside onCreate()
by
spinnerInteractionListener = SpinnerInteractionListener()
and use it like
spinnerCategory.onItemSelectedListener = spinnerInteractionListener
spinnerCategory.setOnTouchListener(spinnerInteractionListener)
here spinnerCategory
is Spinner
You can just call to setSelection
once you know have the list of items and the position to be selected, in that way you avoid onItemSelected
to be called twice.
I've created an article about what I think is a better approach How to avoid onItemSelected to be called twice in Spinners
Managed to find a solution in another stackoverflow question:
spinner.post(new Runnable() {
public void run() {
spinner.setOnItemSelectedListener(listener);
}
});
Try this:
boolean mConfigChange = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
mConfigChange = false;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mainf);
Log.i("SpinnerTest", "Activity onCreate");
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.colors,
android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
((Spinner) findViewById(R.id.spin)).setAdapter(adapter);
((Spinner) findViewById(R.id.spin)).setSelection(2);
((Spinner) findViewById(R.id.spin)).setOnItemSelectedListener(this);
}
@Override
protected void onResume() {
mConfigChange = true;
super.onResume();
}
@Override
public void onItemSelected(AdapterView<?> spin, View selview, int pos, long selId) {
if (!mConfigChange)
Log.i("Test", "spin:" + spin + " sel:" + selview + " pos:" + pos + " selId:" + selId);
else
mConfigChange = false;
}
The first time the onItemSelected
runs, the view
is not yet inflated. The second time it is already inflated. The solution is to wrap methods inside onItemSelected
with if (view != null)
.
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (view != null) {
//do things here
}
}
This is what i did:
Do a local variable
Boolean changeSpinner = true;
On the saveInstanceMethod save the selected item position of the spinner
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("ItemSelect",mySpinner.getSelectedItemPosition());
}
Then on the activity created get that int from savedInstanceState and if the int is != 0 then set the boolean variable on false;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
if (savedInstanceState!=null) {
if (savedInstanceState.getInt("ItemSelect")!=0) {
changeSpinner = false;
}
}
}
And for last on the OnItemSelected from the spinner do this
mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,android.view.View v, int position, long id) {
if (changeSpinner) {
[...]
} else {
changeSpinner= true;
}
});
So, the first time when is called is not going to do anything, just make the boolean variable true, and the second time is going to execute the code. Maybe not the best solution but it work.