1

I wish to set onClickListeners for buttons in a spinner which is furthur inside a recyclerView. The following is what I have built(using spinner in my case):-

(https://i.stack.imgur.com/DmyJl.jpg)

Each of the items in my recyclerView has its own spinner which contains two options for every item: Update details and Delete. How and in which class can I set onClickListeners for these buttons so that I may be able to retrieve that which button(Update details or delete) is clicked on which item of recyclerView, so that I may be able to update/delete that particular password in my database. My code:-

PasswordsActivity.java:-

public class PasswordsActivity extends AppCompatActivity {

RecyclerView recyclerView;
FloatingActionButton FAB;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_passwords);

    recyclerView = (RecyclerView) findViewById(R.id.password_list);
    FAB = (FloatingActionButton) findViewById(R.id.buttonAdd);

    getSupportActionBar().setTitle("Saved Passwords");

    DBHelper helper = new DBHelper(this);

    ArrayList<PasswordModel> passwordModelArrayList = new ArrayList<>();
    passwordModelArrayList.clear();

    passwordModelArrayList = helper.readPasswords();

    PasswordAdapter passwordAdapter = new PasswordAdapter(this, passwordModelArrayList );

    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);

    recyclerView.setItemAnimator(new DefaultItemAnimator());

    recyclerView.setLayoutManager(layoutManager);

    recyclerView.setAdapter(passwordAdapter);

    FAB.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(PasswordsActivity.this, AddPasswords.class);
            startActivity(intent);
        }
    });

}

@Override
protected void onResume() {
    super.onResume();
    DBHelper helper = new DBHelper(this);

    ArrayList<PasswordModel> passwordModelArrayList = new ArrayList<>();
    passwordModelArrayList.clear();

    passwordModelArrayList = helper.readPasswords();

    PasswordAdapter passwordAdapter = new PasswordAdapter(this, passwordModelArrayList );

    recyclerView.setAdapter(passwordAdapter);

}

PasswordAdapter.java:-

public class PasswordAdapter extends 
RecyclerView.Adapter<PasswordAdapter.MyViewHolder>{

Context context;
ArrayList<PasswordModel> arrayList;


@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.passwords_list, parent, false);

    return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    TextView username;
    TextView password;
    TextView website;

    username = holder.usernameView;
    password = holder.passwordView;
    website = holder.websiteView;

    username.setText(arrayList.get(position).getSavedUsername());
    password.setText(arrayList.get(position).getSavedPassword());
    website.setText(arrayList.get(position).getSavedWebsite());


}

@Override
public int getItemCount() {
    return arrayList.size();
}

@Override
public long getItemId(int position) {
    return position;
}

class MyViewHolder extends RecyclerView.ViewHolder
{
    TextView usernameView;
    TextView websiteView;
    TextView passwordView;

    public MyViewHolder(final View itemView)
    {
        super(itemView);

        this.passwordView = (TextView)itemView.findViewById(R.id.textPassword);
        this.usernameView = (TextView)itemView.findViewById(R.id.textUsername);
        this.websiteView = (TextView)itemView.findViewById(R.id.textWebsite);

       Spinner spinner = (Spinner)itemView.findViewById(R.id.spinner);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context.getApplicationContext(), R.array.options_array, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });
    }

}

public PasswordAdapter(Context context, ArrayList<PasswordModel> arrayList)
{
    this.context = context;
    this.arrayList = arrayList;
}

}

Please let me know if anything else is needed as well.

AsCress
  • 15
  • 4
  • Does this solution fit yours use case https://stackoverflow.com/a/28532057/3649629 ? – Gleichmut Feb 15 '23 at 02:49
  • @Gleichmut not quite. Can you however suggest the implementation of buttons in PasswordsActivity as suggested in the answer below ? – AsCress Feb 15 '23 at 05:41

1 Answers1

1

Welcome to SO! Yeah you can do it. Can you Please try changing your adapter class as following:

!!!UPDATE!!!

package com.xxx.sample;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

public class PasswordAdapter extends
        RecyclerView.Adapter<PasswordAdapter.MyViewHolder>{

    Context context;
    ArrayList<PasswordModel> arrayList;
    
    ItemClickCallBack callback;


    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.passwords_list, parent, false);

        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        PaaswordModel pwdModel = arrayList.get(position);
        holder.position = position;
        holder.bind(pwdModel);
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    class MyViewHolder extends RecyclerView.ViewHolder
    {
        TextView usernameView;
        TextView websiteView;
        TextView passwordView;
        int position;

        public MyViewHolder(final View itemView)
        {
            super(itemView);

            this.passwordView = (TextView)itemView.findViewById(R.id.textPassword);
            this.usernameView = (TextView)itemView.findViewById(R.id.textUsername);
            this.websiteView = (TextView)itemView.findViewById(R.id.textWebsite);

            Spinner spinner = (Spinner)itemView.findViewById(R.id.spinner);
            ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context.getApplicationContext(), R.array.options_array, android.R.layout.simple_spinner_item);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinner.setAdapter(adapter);
        }

        public void bind(PaaswordModel pwdModel) {
            usernameView.setText(pwdModel.getSavedUsername());
            passwordView.setText(pwdModel.getSavedPassword());
            websiteView.setText(pwdModel.getSavedWebsite());
            itemView.setOnClickListener(view -> {
                callback.onItemClickCallBack(pwdModel);
            });
    spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int i, long id) {
    String value = getResources().getStringArray(R.id.<value_array>)[i];
        callback.onSpinnerClickCallBack(value, position);
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here or leave empty
    }

});
        }
    }

    public PasswordAdapter(Context context, ArrayList<PasswordModel> arrayList, ItemClickCallBack callback)
    {
        this.context = context;
        this.arrayList = arrayList;
        this.callback = callback;
    }
    
    public interface ItemClickCallBack {
        void onItemClickCallBack(PasswordModel item);
        void onSpinnerClickCallBack(String item, int pos);
    }

}

After that, you might find an error to your activity class in the following line:

PasswordAdapter passwordAdapter = new PasswordAdapter(this, passwordModelArrayList, <argument missing>);

PasswordActivity:

public class PasswordsActivity extends AppCompatActivity {

RecyclerView recyclerView;
FloatingActionButton FAB;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_passwords);

.....

    PasswordAdapter passwordAdapter = new PasswordAdapter(this, passwordModelArrayList, new PasswordAdapter.ItemClickCallBack{
@Override
public void onItemClickCallBack(PasswordModel model) {
// do your code using this model
}
@Override
public void onSpinnerClickCallBack(String spinnerItem, int pos) {
// do your code using this model
// spinnerItem gives the text of spinner item selected and pos gives the position of the item in recyclerView
}
});

Or you can pass this so that you might be able to implement the callback method inside your view class or activity class, and then you will be able to get the information from the 2 (two) overrides methods which are onItemClickCallBack (from item click) and onSpinnerClickCallBack (for spinner item click). Now you should be able to do your next work from here and on. Hopefully it will help you. Happy coding.

AsCress
  • 15
  • 4
A S M Sayem
  • 2,010
  • 2
  • 21
  • 28
  • Thank you so much! I am not quite confident of being able to implement these buttons in my activity class. Can you tell how can I set listeners in my activity class after this. Sorry, a bit new to android. – AsCress Feb 15 '23 at 03:21
  • Does this solve the purpose of clicking on a particular item in the spinner? I mean, how would we implement that in PasswordsActivity ? – AsCress Feb 15 '23 at 05:19
  • Pass this to the last param, where you have initialized the adapter. You are just implementing the `onClickListener` to the `itemView`, that is what I showed in the Answer. If you want to select the item from the spinner list, then you might need to update a little bit. I will be updating my answer soon. Please have a look, when you see update at the top of the answer. Thanks – A S M Sayem Feb 15 '23 at 05:44
  • Thanks. Yes, I want that if I click the update option for a particular password in the list a new activity should open up...etc....for delete. Now, I just wanted that I get the ID of the element in recyclerView so that I can update/delete that particular password. Every item in the recyclerView has the same set of options in the spinner.....(Update details/delete)... – AsCress Feb 15 '23 at 06:05
  • @AsCress, I have updated my answer, you can pass whatever value you want to fulfill your goal with the callbacks when you implement it inside your activity. Please let me know if it works, I couldn't test but logically this should work. – A S M Sayem Feb 15 '23 at 07:21
  • @ASMSayem Thanks again for your time. I just wanted to know that how could I now implement this solution in my ParkingActivity, since this concept is a bit new to me. Could you please share the code of what you mean to do exactly in my activity using the callback, I mean like for eg.:- code for selecting the delete button of third entry in the recyclerView. – AsCress Feb 15 '23 at 07:36
  • @AsCress please check this link: http://wiseassblog.com/tutorials/java/android/interface/2016/09/13/android-java-interfaces/ and let me know you still have confusion about the implementation. Also check the updated version of the answer again. Thanks – A S M Sayem Feb 15 '23 at 07:57
  • That's fine. But in the onSpinnerClickCallback, how do I know that the spinner of which item in recyclerView is selected ? – AsCress Feb 15 '23 at 08:12
  • Thanks very much for your help. I solved the issue by adding a bit to your code. Can I update your answer and then accept it ? – AsCress Feb 16 '23 at 02:09
  • Sure go for it. Happy to help! Btw, here is how you get the selected item (you can also pass the position if you needed through the interface/callback as well): ` spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView> parentView, View selectedItemView, int position, long id) { String value = getResources().getStringArray(R.id.)[position]; callback.onSpinnerClickCallBack(); } } ` Please give a up vote while Accepting my answer. – A S M Sayem Feb 16 '23 at 02:50
  • I've edited and accepted your answer. The edit will be visible as soon as approved I guess. Thanks for helping again ! – AsCress Feb 18 '23 at 03:39
  • 1
    I have approved your edit, please don't for get to upvote. I need to reach 2k rep. Thanks, happy days – A S M Sayem Feb 21 '23 at 06:33