-1

I have this custom list adapter I made and for some reason I can get the txtTitle to work with the listeners, but the buttons always return a null object. Is there a specific way to add a button in a recyclerView like this? I implement it the same way I implement my other recycler adapters except they do not have buttons in them.

public class resource_list_adapter extends RecyclerView.Adapter<resource_list_adapter.ViewHolder> {

    private List<resource_list> listItems;
private Context context;
resource_list_adapter.OnItemClickListener onItemClickListener;

public resource_list_adapter(List<resource_list> listItems, Context context) {
    this.listItems = listItems;
    this.context = context;
}

@Override
public resource_list_adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.resource_list, parent, false);
    return new ViewHolder(v);
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    resource_list listItem = listItems.get(position);
    Double resource = listItem.getCurrent().doubleValue()/listItem.getMax().doubleValue();

    holder.txtTitle.setText(listItem.getTxtTitle() + ": " + listItem.getCurrent().toString() + "/" + listItem.getMax().toString() + " (" + String.valueOf((int)(100*resource)) + "%)");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        holder.pgResource.setProgressTintList(ColorStateList.valueOf(Color.rgb(listItem.getRed(),listItem.getGreen(),listItem.getBlue())));
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        holder.pgResource.setProgress((int)(100*resource), true);
    }

    holder.btnAddResource.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onItemClickListener.onResourceClick(position);
        }
    });
    holder.btnSubtractResource.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onItemClickListener.onResourceClick(position);
        }
    });

    holder.btnAddResource.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            onItemClickListener.onLongResourceClick(position);
            return true;
        }
    });
    holder.btnSubtractResource.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            onItemClickListener.onLongResourceClick(position);
            return true;
        }
    });

}

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

public class ViewHolder extends RecyclerView.ViewHolder {

    public TextView txtTitle;
    public ProgressBar pgResource;
    public Button btnAddResource;
    public Button btnSubtractResource;

    public ViewHolder(View itemView) {
        super(itemView);
        txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
        btnAddResource = (Button) itemView.findViewById(R.id.btnAdditionResource);
        btnSubtractResource = (Button) itemView.findViewById(R.id.btnSubtractResource);
        pgResource = (ProgressBar) itemView.findViewById(R.id.pgResource);
    }
}
public void setOnItemClickListener(resource_list_adapter.OnItemClickListener onItemClickListener){
    this.onItemClickListener = onItemClickListener;
}

public interface OnItemClickListener{
    void onResourceClick(int position);
    void onLongResourceClick(int position);
}
}

This is how I implement it on my Activity.

I implement implements resource_list_adapter.OnItemClickListener on my activity.

Declare variables:

private RecyclerView recyclerResource;
private resource_list_adapter resourceAdapter;
private List<resource_list> resourceList;
private List<String> resourceKeyList;

This is how I call the methods - the same place I call all other methods from the other adapters.

@Override
    public void onResourceClick(int position) {
        Toast.makeText(getContext(), "Test", Toast.LENGTH_SHORT).show();
        /*Intent intent = new Intent(getActivity(), AttributeDescription.class);
        intent.putExtra("SelectedCharacter", Home_Tab.activeCharacter);
        intent.putExtra("name", attributeKeyList.get(position).toString());
        intent.putExtra("category", "Attribute");
        if (character.Edit.equals("True")){
            intent.putExtra("mode", "Edit");
        }
        else{
            intent.putExtra("mode", "View");
        }
        startActivity(intent);*/
    }

    @Override
    public void onLongResourceClick(final int position) {
        /*if (character.Edit.equals("True")){
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setTitle("Remove Attribute");
            builder.setPositiveButton("Remove", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    character.removeAttribute(attributeKeyList.get(position).toString(), "Attribute");
                    attributeKeyList.remove(position);
                }
            })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // User cancelled the dialog
                        }
                    });
            // Create the AlertDialog object and return it
            AlertDialog dialog = builder.create();
            dialog.show();
        }*/
    }

This is how I set the listener to my adapter in my init() method (same way as the rest).

resourceAdapter = new resource_list_adapter(resourceList, getContext());
resourceAdapter.setOnItemClickListener(this);
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Torewin
  • 887
  • 8
  • 22

1 Answers1

2

You must be making a new RecyclerViewAdapter without setting the click listener. For example, you call notifyDataSetChanged, when you get new data, don't make a whole new adapter.

If you always want to force yourself to implement a click listener (since you have no null check), explicitly pass it in the constructor

final resource_list_adapter.OnItemClickListener onItemClickListener;

public resource_list_adapter(List<resource_list> listItems, Context context, resource_list_adapter.OnItemClickListener listener) {
    this.listItems = listItems;
    this.context = context;
    onItemClickListener = listener;
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • 1
    So that code didn't fix my problem, but you explaining about creating a new RecyclerViewAdapter made me realize that I may have been declaring it twice - which I was and I solved it! I guess it was more user error then anything. – Torewin Aug 29 '17 at 02:56
  • You would need to remove the other constructor and the setOnItemClickListener method for this code to work properly – OneCricketeer Aug 29 '17 at 03:10