user3718908x100
user3718908x100

Reputation: 8509

Set Selected Items Without Triggering OnItemSelectedListener

I have been struggling with this for days now, I have a list of items I am loading from my server. When the items are loaded I display the list and I set the selected item for each spinner. Now these are my problems.

Case 1: The onItemSelectedListener for each item in my adapter gets triggered on page load.

So I did some research online and decided to use a variable to check the state. When the view is created I set firstTime to true in the on click listener like this:

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

        if (!firstTime) {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);

            builder.setTitle("Confirm");
            builder.setMessage("Are you sure you want to change this?");

            builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    int selectedPosition = Integer.parseInt(viewHolder.id.getTag().toString());
                    String selectedId = viewHolder.id.getText().toString();
                    updateStatus(selectedPosition, selectedId,
                            ((ArrayAdapter<String>) viewHolder.spStatus.getAdapter())
                                    .getItem(selectedPosition));
                }

            });

            builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // Do nothing
                    dialog.dismiss();
                }
            });

            AlertDialog alert = builder.create();
            alert.show();
        }

        firstTime = false;
    }

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

Now this is what happens when I do this it's either when I scroll the onItemSelected change listener fires depending on where I put firstTime=false or when I filter the list I have to tap twice before the event is triggered.

Upvotes: 2

Views: 1983

Answers (3)

Hishara Dilshan HishD
Hishara Dilshan HishD

Reputation: 63

You can do it like this,

    public void setSelection(int position, boolean animate, boolean noTrigger, OnItemSelectedListener onItemSelectedListener) {
    if(noTrigger) {
        Log.e("SET_SELECTION", "No trigger at position " + position);
        this.setOnItemSelectedListener(null);
    }

    super.setSelection(position, animate);
    this.post(new Runnable() {
        @Override
        public void run() {
            setOnItemSelectedListener(onItemSelectedListener);
        }
    });
}

Upvotes: 1

fbiego
fbiego

Reputation: 418

Solution for RecyclerView Adapter in Kotlin

class DataAdapter(myData: ArrayList<MyData>) : RecyclerView.Adapter<DataAdapter.DataHolder>(){


    override fun onViewRecycled(holder: DataHolder){
        holder.mSpinner.onItemSelectedListener = null   //remove listener when item is out of view
        super.onViewRecycled(holder)
    }
    
    
    class DataHolder(itemView: View, private val context: Context) : RecyclerView.ViewHolder(itemView) {
        
        val mSpinner: Spinner = itemView.findViewById(R.id.spinner)
        
        fun bind(data: MyData){
            
            var pass = false // variable to check first run
            val adapter = SpinnerAdapter(context)
            mSpinner.adapter = adapter
            
            val onSelectListener = object : AdapterView.OnItemSelectedListener{
                override fun onNothingSelected(p0: AdapterView<*>?) {

                }


                override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
                    
                    if (pass){
                        // actions onSelected
                    }
                    pass = true

                }

            }
            
            mSpinner.setSelection(3)    //the onItemSelected will be triggered when the item is first created
            mSpinner.onItemSelectedListener = onSelectListener
        
        }
    
    }
}

Upvotes: 0

B&#246; macht Blau
B&#246; macht Blau

Reputation: 13009

If I understand correctly, you have a ViewHolder with an itemView which contains a Spinner. You want to be able to set the selected position of the Spinner programmatically without triggering the OnItemSelectedListener of the Spinner.

Right now you are using an anonymous OnItemSelectedListener. If you make this listener a field of the ViewHolder class

private OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener(){
    // listener code goes here
    // ...
    };

... then you can "unset" the listener before setting the selected position programmatically and "reset" it afterwards like the following method shows:

private void setPosition(int position){
    if(listener != null){
        spinner.setOnItemClickListener(null);
    }
    spinner.setSelection(position);
    spinner.setOnItemClickListener(listener);
}

Upvotes: 0

Related Questions