Skip to content Skip to sidebar Skip to footer

Android Spinner Onitemselected Only On User Interaction

I know that this question has been answered multiple times, but I have not found any of them satisfactory and certainly not elegant. The issue is that OnItemSelected gets fired not

Solution 1:

So I am posting an answer, but any criticisms, improvements, or other more elegant answers are welcome.

The key is overriding onClick to set a flag which ties the onItemSelectedListener to user interaction and fires the onItemClickedListener.

If you don't feel comfortable using the API setOnItemClickedListener (for future compatibility perhaps), you can of course substitute your own method. I just felt like onItemClickedListener should have been implemented to this effect the whole time, so that is my subtle protest.

Also, if anyone can think of a reason that the spinnerTouched flag gets short circuited (stays true for longer than it should), please let us know so that it can be addressed. It seems to work pretty well so far though.

publicclassOnItemClickSpinnerextendsSpinnerimplementsAdapterView.OnItemSelectedListener {

    booleanspinnerTouched=false;
    OnItemClickListeneronItemClickListener=null;
    OnItemSelectedListeneronItemSelectedListener=null;

    publicOnItemClickSpinner(Context context) {
        super(context);
        super.setOnItemSelectedListener(this);
    }

    publicOnItemClickSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
        super.setOnItemSelectedListener(this);
    }

    publicOnItemClickSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        super.setOnItemSelectedListener(this);
    }

    @OverridepublicbooleanonTouchEvent(MotionEvent event) {
        spinnerTouched = true;
        returnsuper.onTouchEvent(event);
    }

    @OverridepublicvoidsetOnItemClickListener(OnItemClickListener listener) {
        onItemClickListener = listener;
    }

    @OverridepublicvoidsetOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) {
        this.onItemSelectedListener = onItemSelectedListener;
        super.setOnItemSelectedListener(this);
    }

    @OverridepublicvoidonItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if(spinnerTouched && this.onItemClickListener!=null) this.onItemClickListener.onItemClick(parent,view,position,id);
        if(this.onItemSelectedListener!=null) this.onItemSelectedListener.onItemSelected(parent,view,position,id);
        spinnerTouched=false;
    }

    @OverridepublicvoidonNothingSelected(AdapterView<?> parent) {
        if(this.onItemSelectedListener!=null) this.onItemSelectedListener.onNothingSelected(parent);
        spinnerTouched=false;
    }
}

Solution 2:

Had a similar issue with some UI component in iOS. I decided to use a similar hack.

So somewhere in the object that owns the spinner--maybe an activity--declare a member variable: private var isSelectionFromTouch: Boolean = false

The rest of the relevant code:

init {
    spinner.onItemSelectedListener = this
    spinner.setOnTouchListener { _, _ ->
        this.isSelectionFromTouch = truefalse
    }
}

// On Item SelectedoverridefunonItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
    if (!isSelectionFromTouch) { return }
    Log.d(TAG, "item selected. do something.")
    isSelectionFromTouch = false
}

overridefunonNothingSelected(parent: AdapterView<*>?) {
    isSelectionFromTouch = false
}

Post a Comment for "Android Spinner Onitemselected Only On User Interaction"