0

I am creating a GridLayout that gets filled with dynamic buttons and strings using a RecyclerView. Each button and string gets added to the view one at a time, and each time a button and string gets added, I want to send the dynamic string to my button's onClick in RecyclerViewHolder.

I tried to use this question as a guide:

how to send data using bundle inside RecyclerView onclick method

but they have a set list of strings and drawables to send to their RecyclerView.ViewHolder, whereas mine are being created dynamically. Here is where I am at and any help would be appreciated!

RecyclerView.ViewHolder where I want to send my string to onClick. In my log, I want to see the name of the button I am clicking on pop up.

public class RecyclerViewHolders extends RecyclerView.ViewHolder
    implements View.OnClickListener
{

public TextView AName;
public ImageButton AButton;
ItemObject itemObject;
List<ItemObject> namelist=HomeFragment.getListdata();


public RecyclerViewHolders(View itemView) {
    super(itemView);
    AName = (TextView) itemView.findViewById(R.id.new_name);
    AButton = (ImageButton) itemView.findViewById(R.id.new_button);
    itemView.findViewById(R.id.new_button).setOnClickListener(this);
}


public void onClick(View view) {

    String name = namelist.get(getAdapterPosition()).getName();
    Log.d("tag_name", "Name of button that was clicked" + name);
}
}

My Activity that initiates the RecyclerView, where I am trying to send the string from. "createButton" method is where drawable and string are first sent to from another method:

public class HomeFragment extends Fragment {

private GridLayoutManager lLayout;

RecyclerViewAdapter rcAdapter;
private static Context mContext;

static String Name;
static Drawable draw;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mContext = getContext();

    List<ItemObject> myList = new ArrayList<>();
    rcAdapter = new RecyclerViewAdapter(getActivity(), myList);

}

// onCreateView
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.home_fragment, container, false);


    Log.d("tag_name", "Go through onCreateView");

    lLayout = new GridLayoutManager(getActivity(), 2,
            GridLayoutManager.HORIZONTAL, false);

    RecyclerView rView = (RecyclerView) view.findViewById(R.id.recycler_view);

    rView.setHasFixedSize(true);
    rView.setLayoutManager(lLayout);
    rView.setAdapter(rcAdapter);


    return view;
}


public void createButton(Drawable d, String aName) {

    Name = aName;
    draw = d;

    Log.d("tag_name", "Make sure createButton is called" + rcAdapter);
    rcAdapter.addItem(new ItemObject(aName, d));
}



public static List<ItemObject> getListdata() {
    Log.d("tag_name", "List to send to onClickListener" + Name);
    List<ItemObject> namelist = new ArrayList<>();
    namelist.add(new ItemObject(Name,draw));
    return namelist;
}
}

And ItemObject:

public class ItemObject {

private String name;
private Drawable d;

public ItemObject(String name, Drawable d) {
    this.name = name;
    this.d = d;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Drawable getPhoto() {
    return d;
}

public void setPhoto(Drawable d) {
    this.d = d;
}
}

My current error, which occurs in RecyclerViewHolders, where I define "String Name":

05-24 14:12:53.350 7295-7295/it.anddev.bradipao.janus W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x437c0160)
05-24 14:12:53.360 7295-7295/it.anddev.bradipao.janus E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    Process: it.anddev.bradipao.janus, PID: 7295
                                                                    java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
                                                                        at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
                                                                        at java.util.ArrayList.get(ArrayList.java:308)
                                                                        at it.anddev.bradipao.janus.RecyclerViewHolders.onClick(RecyclerViewHolders.java:50)
                                                                        at android.view.View.performClick(View.java:4487)
                                                                        at android.view.View$PerformClick.run(View.java:18746)
                                                                        at android.os.Handler.handleCallback(Handler.java:733)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                        at android.os.Looper.loop(Looper.java:149)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5257)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:515)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:604)
                                                                        at dalvik.system.NativeStart.main(Native Method)
Community
  • 1
  • 1
Natalie
  • 315
  • 5
  • 18
  • Your view holder should be getting the data from the list in the Adapter. You are pulling the data from `HomeFragment.getListdata();` which is not updated if a new item is added to the RecyclerView. – cyroxis May 24 '16 at 18:48
  • @cyroxis I see... How could I access the list from my adapter in my RecyclerViewHolder? – Natalie May 24 '16 at 21:10
  • Typically by making your ViewHolder an inner class of the RecyclerAdpater. Optionally you can pass the RecyclerAdpater in the constructor of the ViewHolder. – cyroxis May 24 '16 at 21:12

3 Answers3

1

implement OnClickListener to your Fragment and pass in constructor to Adapter and inside to each RecyclerViewHolder

do you know that keeping as static your Drawable and Name results same drawable and name in each fragment you add? (last set)

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • 1
    More generally, static should be avoided for both Java and Android development, it will typically come back to bite you in the future. – cyroxis May 24 '16 at 18:50
  • Thanks for the feedback! I realize now that keeping my variables static will not work. When you say to "implement OnClickListener to your Fragment and pass in constructor to Adapter and inside to each RecyclerViewHolder", what do you mean? Is there an example of how to do this to help guide me? – Natalie May 24 '16 at 20:59
  • `public class HomeFragment extends Fragment implements View.OnClickListener` and pass this listener (using `this`) to custom adapter. how to create one you can find [HERE](https://developer.android.com/training/material/lists-cards.html), `onCreateViewHolder` is proper place to pass interface to your `RecyclerViewHolders` objects. inside `onBindViewHolder` you may set some tag (`setTag`) for every itemView with e.g. and then inside `onClick` in `Fragment` read id AND `getTag`. I'm suggesting you to get rid of all `static`s for first (which may "accidentally" fix), then repost cleaned code – snachmsm May 24 '16 at 21:43
  • [probably the best described sample of custom adapter for `RecyclerView` with handling `OnClickListener`](http://stackoverflow.com/questions/24885223/why-doesnt-recyclerview-have-onitemclicklistener-and-how-recyclerview-is-dif) – snachmsm May 24 '16 at 21:46
1

Looks like getAdapterPosition() is returning value greater than the length of your namelist (it is just one item). Try to figure this out.

gipsy
  • 3,859
  • 1
  • 13
  • 21
0

I found a link that helped me solve this problem, although my solution is slightly different. For anyone else who might have the same question.

Passing data on click in RecyclerView.Adapter

Reminder of what I wanted to accomplish: "I want to see the name of the button I am clicking on pop up." So, each button click will be unique with the name that I assigned the button.

I realized I can access the position of my click and the string associated with the click in RecyclerViewAdapter and attach my onClickListener to the RecyclerViewHolder. This makes the solution way more simple than what I was trying to do by sending my string list to RecyclerViewHolder.

So, in my RecyclerViewAdapter I created an onClickListener in a custom method:

private class downloadOnClickListener implements View.OnClickListener{

    String aName;

    public downloadOnClickListener(String file){
        this.aName = file;
    }

    @Override
    public void onClick(View v) {

        Log.d("tag_name", "Name of button being pressed" + aName);

    }
}

And in onBindViewHolder I attached the listener to the RecyclerHolder

 @Override
public void onBindViewHolder(RecyclerViewHolders holder, int position) {
    ItemObject itemObject = itemList.get(position);
    holder.itemObject = itemObject;
    holder.AButton.setOnClickListener(new downloadOnClickListener(itemList.get(position).getName()));
}
Community
  • 1
  • 1
Natalie
  • 315
  • 5
  • 18